From 6f22aed47c31b64d37c0c97042bfa47d3fc6c199 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Fri, 14 Aug 2026 13:36:02 +0700 Subject: [PATCH] refactor: dedupe split-view render, strengthen persistence test - Extract ConsoleArea helper to eliminate ~60 lines of duplicated layout toggle + grid rendering shared between currentLane and !currentLane branches - Fix persistence test to validate the component's actual write path instead of manually re-seeding localStorage (proves writeSplitViewState is called) - Remove orphaned grid/pane code left by incomplete merge --- client/src/pages/Workspace.tsx | 241 +++++++++--------- client/src/pages/__tests__/Workspace.test.tsx | 6 - 2 files changed, 123 insertions(+), 124 deletions(-) diff --git a/client/src/pages/Workspace.tsx b/client/src/pages/Workspace.tsx index 85fca3e..c91c8c7 100644 --- a/client/src/pages/Workspace.tsx +++ b/client/src/pages/Workspace.tsx @@ -54,6 +54,97 @@ import type { SplitViewState, SplitLayout } from "../lib/splitViewStorage"; // ── Page ────────────────────────────────────────────────────────────── +function ConsoleArea({ + lanes, + selectedLaneId, + splitView, + setLayout, + setPaneLaneId, + binaryStatus, + cwdSuggestions, + activeRuns, + wsConnected, + defaultCwd, + onHasActiveRunChange, + onLaneCreated, + onLaneIdChange, +}: { + lanes: Lane[]; + selectedLaneId: number | null; + splitView: SplitViewState; + setLayout: (layout: SplitLayout) => void; + setPaneLaneId: (index: number, id: number) => void; + binaryStatus: { found: boolean; path: string | null } | null; + cwdSuggestions: CwdSuggestion[]; + activeRuns: RunListResponse | null; + wsConnected: boolean; + defaultCwd: string; + onHasActiveRunChange: (val: boolean) => void; + onLaneCreated: (lane: Lane) => void; + onLaneIdChange: (id: number | null) => void; +}) { + const { t: tLanes } = useTranslation("lanes"); + + return ( + <> +
+ {([1, 2, 4] as const).map((n) => ( + + ))} +
+ {splitView.layout === 1 ? ( + + ) : ( +
+ {splitView.paneLaneIds.map((id, i) => ( + setPaneLaneId(i, newId)} + onLaneCreated={onLaneCreated} + binaryStatus={binaryStatus} + cwdSuggestions={cwdSuggestions} + activeRuns={activeRuns} + wsConnected={wsConnected} + defaultCwd={defaultCwd} + /> + ))} +
+ )} + + ); +} + export function Workspace() { const { t: tLanes } = useTranslation("lanes"); const wsConnected = useSyncExternalStore(eventBus.onConnection, () => eventBus.connected); @@ -552,132 +643,46 @@ export function Workspace() { )}
-
- {([1, 2, 4] as const).map((n) => ( - - ))} -
- {splitView.layout === 1 ? ( - setSelectedLaneId(id)} - onLaneCreated={(lane) => - setLanes((prev) => (prev.some((l) => l.id === lane.id) ? prev : [...prev, lane])) - } - binaryStatus={binaryStatus} - cwdSuggestions={cwdSuggestions} - activeRuns={activeRuns} - wsConnected={wsConnected} - defaultCwd={defaultCwd} - onHasActiveRunChange={setPaneHasActiveRun} - /> - ) : ( -
- {splitView.paneLaneIds.map((id, i) => ( - setPaneLaneId(i, newId)} - onLaneCreated={(lane) => - setLanes((prev) => - prev.some((l) => l.id === lane.id) ? prev : [...prev, lane] - ) - } - binaryStatus={binaryStatus} - cwdSuggestions={cwdSuggestions} - activeRuns={activeRuns} - wsConnected={wsConnected} - defaultCwd={defaultCwd} - /> - ))} -
- )} -
- - )} - - {!currentLane && ( -
-
- {([1, 2, 4] as const).map((n) => ( - - ))} -
- {splitView.layout === 1 ? ( - setSelectedLaneId(id)} - onLaneCreated={(lane) => - setLanes((prev) => (prev.some((l) => l.id === lane.id) ? prev : [...prev, lane])) - } + selectedLaneId={selectedLaneId} + splitView={splitView} + setLayout={setLayout} + setPaneLaneId={setPaneLaneId} binaryStatus={binaryStatus} cwdSuggestions={cwdSuggestions} activeRuns={activeRuns} wsConnected={wsConnected} defaultCwd={defaultCwd} onHasActiveRunChange={setPaneHasActiveRun} + onLaneCreated={(lane) => + setLanes((prev) => (prev.some((l) => l.id === lane.id) ? prev : [...prev, lane])) + } + onLaneIdChange={setSelectedLaneId} /> - ) : ( -
- {splitView.paneLaneIds.map((id, i) => ( - setPaneLaneId(i, newId)} - onLaneCreated={(lane) => - setLanes((prev) => - prev.some((l) => l.id === lane.id) ? prev : [...prev, lane] - ) - } - binaryStatus={binaryStatus} - cwdSuggestions={cwdSuggestions} - activeRuns={activeRuns} - wsConnected={wsConnected} - defaultCwd={defaultCwd} - /> - ))} -
- )} +
+ + )} + + {!currentLane && ( +
+ + setLanes((prev) => (prev.some((l) => l.id === lane.id) ? prev : [...prev, lane])) + } + onLaneIdChange={setSelectedLaneId} + />
)} diff --git a/client/src/pages/__tests__/Workspace.test.tsx b/client/src/pages/__tests__/Workspace.test.tsx index ac3f7c7..201dc84 100644 --- a/client/src/pages/__tests__/Workspace.test.tsx +++ b/client/src/pages/__tests__/Workspace.test.tsx @@ -671,12 +671,6 @@ describe("split terminal view", () => { await settle(); unmount(); - localStorage.clear(); - localStorage.setItem( - "ccam.workspace.splitView", - JSON.stringify({ layout: 2, paneLaneIds: [null, lanesToReturn[1]!.id] }) - ); - await renderWorkspace(); const persistedSelects = screen.getAllByTestId("pane-lane-select"); expect(persistedSelects).toHaveLength(2);