From ee7410c203ef217f1c83a955e27a15bb9fa1fede Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 14 Jul 2026 14:42:22 -0700 Subject: [PATCH] fix(ui): center external session conversations (#107781) --- ui/src/e2e/claude-sessions.e2e.test.ts | 30 ++++++++++++++++++++++++++ ui/src/pages/chat/chat-view.ts | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ui/src/e2e/claude-sessions.e2e.test.ts b/ui/src/e2e/claude-sessions.e2e.test.ts index 04c99cac6a97..231b0680f42b 100644 --- a/ui/src/e2e/claude-sessions.e2e.test.ts +++ b/ui/src/e2e/claude-sessions.e2e.test.ts @@ -1,3 +1,5 @@ +import fs from "node:fs/promises"; +import path from "node:path"; import { chromium, type Browser } from "playwright"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { @@ -162,6 +164,34 @@ suite("Claude native session catalog", () => { await expect .poll(() => page.getByText("This session is on a paired node and is view-only.").count()) .toBe(1); + const artifactDir = process.env.OPENCLAW_UI_E2E_ARTIFACT_DIR?.trim(); + const expectCenteredLayout = async (screenshotName: string) => { + const [workbenchBox, threadBox, composerBox] = await Promise.all([ + page.locator(".chat-workbench").boundingBox(), + page.locator(".chat-thread-inner").boundingBox(), + page.locator(".agent-chat__composer-shell").boundingBox(), + ]); + expect(workbenchBox).not.toBeNull(); + expect(threadBox).not.toBeNull(); + expect(composerBox).not.toBeNull(); + const workbenchCenter = workbenchBox!.x + workbenchBox!.width / 2; + expect(Math.abs(threadBox!.x + threadBox!.width / 2 - workbenchCenter)).toBeLessThanOrEqual( + 1, + ); + expect( + Math.abs(composerBox!.x + composerBox!.width / 2 - workbenchCenter), + ).toBeLessThanOrEqual(1); + if (artifactDir) { + await fs.mkdir(artifactDir, { recursive: true }); + await page.screenshot({ + path: path.join(artifactDir, screenshotName), + fullPage: true, + }); + } + }; + await expectCenteredLayout("claude-external-session-centered-1280.png"); + await page.setViewportSize({ width: 1600, height: 900 }); + await expectCenteredLayout("claude-external-session-centered-1600.png"); expect((await gateway.getRequests("sessions.catalog.read")).at(-1)?.params).toMatchObject({ catalogId: "claude", cursor: "older", diff --git a/ui/src/pages/chat/chat-view.ts b/ui/src/pages/chat/chat-view.ts index e31e08a88eb3..04d0157bec9f 100644 --- a/ui/src/pages/chat/chat-view.ts +++ b/ui/src/pages/chat/chat-view.ts @@ -219,6 +219,7 @@ export function renderChat(props: ChatProps) { const splitRatio = props.splitRatio ?? 0.6; const sidebarOpen = Boolean(props.sidebarOpen && props.onCloseSidebar); const sidebarStacked = props.sidebarStacked === true; + const workspaceCollapsed = props.sessionWorkspace?.collapsed !== false; const workspaceDockBottom = Boolean( props.sessionWorkspace && (props.sessionWorkspace.dock === "bottom" || props.sessionWorkspace.narrowLayout), @@ -470,7 +471,7 @@ export function renderChat(props: ChatProps) { requestUpdate, )}