From e593d07405e24cc0c33482bbff4e30e896c03fe1 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Wed, 11 Nov 2026 08:26:29 +0800 Subject: [PATCH] fix(vcs): list files in the Compare tool window and open each diff in the editor (#2611) The Compare tool window rendered the side-by-side diff inline next to the file tree; in a sidebar the file names were cut off and the diff was a few pixels tall. It now lists only the changed files, and double-click or Show Diff opens the diff in an editor tab. Swap Sides and Jump to Source are unchanged; the Changes Between dialog keeps its inline diff. --- src/features/vcs/ComparisonTree.tsx | 5 ++++- src/features/vcs/__tests__/compareTool.test.tsx | 10 ++++++++++ src/features/vcs/compareTool.tsx | 1 + src/features/vcs/operations.tsx | 5 +++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/features/vcs/ComparisonTree.tsx b/src/features/vcs/ComparisonTree.tsx index 7b9d1d1bf..d953d740e 100644 --- a/src/features/vcs/ComparisonTree.tsx +++ b/src/features/vcs/ComparisonTree.tsx @@ -17,6 +17,7 @@ export function ComparisonTree({ openOnActivate = false, getColor, onOpen, + inlineDiff = true, }: { tree: FileTreeNode[]; current: F | null; @@ -27,10 +28,12 @@ export function ComparisonTree({ openOnActivate?: boolean; getColor?: (entry: F) => string | undefined; onOpen?: () => void; + /** Show the selected file's diff beside the tree; off where there is no room (a sidebar). */ + inlineDiff?: boolean; }) { const [selected, setSelected] = useState>(new Set()); const [expanded, setExpanded] = useState | null>(null); - const data = current && diffFor(current); + const data = inlineDiff && current && diffFor(current); const input = data ? diffInput(data) : null; return (
diff --git a/src/features/vcs/__tests__/compareTool.test.tsx b/src/features/vcs/__tests__/compareTool.test.tsx index b720ca82c..9b29457e2 100644 --- a/src/features/vcs/__tests__/compareTool.test.tsx +++ b/src/features/vcs/__tests__/compareTool.test.tsx @@ -114,6 +114,16 @@ describe("CompareToolWindow", () => { expect(mocks.openFile).toHaveBeenCalledWith("/workspace/client/src/app.ts", { focus: true }); }); + it("lists files without an inline diff and opens a file's diff in the editor", async () => { + mocks.openDiff.mockResolvedValue(undefined); + render(); + const file = await screen.findByText("app.ts"); + fireEvent.mouseDown(file, { button: 0 }); + expect(screen.queryByTestId("diff")).toBeNull(); + fireEvent.doubleClick(file); + expect(mocks.openDiff).toHaveBeenLastCalledWith(expect.objectContaining({ path: "/workspace/client/src/app.ts" })); + }); + it("has no Jump to Source for a file deleted from the working tree", async () => { render(); fireEvent.mouseDown(await screen.findByText("old.ts"), { button: 0 }); diff --git a/src/features/vcs/compareTool.tsx b/src/features/vcs/compareTool.tsx index b37b671bc..f2617b40a 100644 --- a/src/features/vcs/compareTool.tsx +++ b/src/features/vcs/compareTool.tsx @@ -93,6 +93,7 @@ export function CompareToolWindow() { from={target.from} to={target.to} native + listOnly swapped={swapped} onSelect={select} onShowDiff={showDiff} diff --git a/src/features/vcs/operations.tsx b/src/features/vcs/operations.tsx index bfc618a1a..0c9764f01 100644 --- a/src/features/vcs/operations.tsx +++ b/src/features/vcs/operations.tsx @@ -602,6 +602,7 @@ export function ChangesBetweenDialog({ onShowDiff, swapped = false, onSelect, + listOnly = false, }: { from: Revision; to: Revision | null; @@ -615,6 +616,8 @@ export function ChangesBetweenDialog({ swapped?: boolean; /** Reports the selected file (the Compare tool window's Jump to Source / Swap Sides). */ onSelect?: (file: ComparisonFile | null) => void; + /** Files only, each diff opening in the editor (the Compare tool window's narrow sidebar). */ + listOnly?: boolean; }) { const [root] = useState(currentRepoRoot); const [repo] = useState(currentRepo); @@ -741,6 +744,8 @@ export function ChangesBetweenDialog({ diffFor={diffFor} getColor={(f) => KIND_COLOR[f.kind === "untracked" ? "added" : f.kind]} ariaLabel="Changed files" + inlineDiff={!listOnly} + openOnActivate={listOnly} renderDetails={(n) => n.file ? ( <>