Skip to content

feat(diff): add a side-by-side view to the inline diff preview - #570

Merged
xintaofei merged 3 commits into
xintaofei:mainfrom
asteroida123:feat/diff-side-by-side
Aug 25, 2026
Merged

feat(diff): add a side-by-side view to the inline diff preview#570
xintaofei merged 3 commits into
xintaofei:mainfrom
asteroida123:feat/diff-side-by-side

Conversation

@asteroida123

Copy link
Copy Markdown
Collaborator

功能

UnifiedDiffPreview(聊天消息 diff、权限弹窗、任务详情、文件面板中使用的轻量 diff 预览)增加左右分栏视图,现有内联视图保留为默认。

Closes #537

实现说明

  • 预览右上角新增 内联 / 分栏 图标切换按钮,选择持久化到 localStorage(workspace:diff-view-mode),对所有宿主生效
  • 分栏视图将 hunk 行重新配对:context 行两侧同显;删除块与紧随的新增块按位置一一对应(GitHub split 视图的对齐方式),较长一侧的剩余行对面显示留空单元格
  • 两栏默认严格等宽(flex-1 basis-0 + 最小宽度兜底),超长行保持横向滚动;纯新增文件(NewFileLines)两种模式下都保持单栏展示
  • 默认仍为内联视图,不改变现有用户体验;500 行截断与展开逻辑在两种视图下同样生效

手动验证

打开任意一条包含 diff 的聊天消息(或权限弹窗、任务详情的 diff),点击预览右上角的分栏图标:删除行居左、新增行居右、上下文行两侧同显;刷新后选择仍保持。

验证

  • npx vitest run src/components/diff/unified-diff-preview.test.tsx — 11 个测试(新增 7 个:默认内联、持久化读取、切换与写回、配对算法三例)
  • pnpm test — 353 个测试文件 / 4875 个测试全部通过
  • pnpm build — 静态导出构建通过(与 CI 一致)
  • npx tsc --noEmiteslint 通过

asteroida123 and others added 3 commits August 25, 2026 12:06
- Toggle (inline / side-by-side) in the preview's top-right, persisted to
  localStorage under workspace:diff-view-mode and shared by every host
  (chat message diffs, permission dialog, task sheet, file panel)
- Split pairing: context rows span both sides; a delete-run and its
  following add-run are zipped positionally, the longer run's remainder
  faces a filler cell (GitHub-style split alignment)
- Equal-width columns via flex-1 basis-0 with a min-width floor so long
  lines keep the horizontal scroll; new-file previews stay single-column
- Default remains the inline view — nothing changes until opted in

Closes xintaofei#537
The view mode is one global preference, but each preview read it into its
own `useState` at mount. A transcript renders one preview per Edit/Write
tool call — and a permission dialog stacks another on top — so flipping
one left every sibling inline until it happened to remount, which is not
what "applies to all hosts" means.

Move the load/save pair to `lib/diff-view-mode-prefs`, the module shape
this repo already uses for cross-surface toggles, and broadcast on write
so every mounted preview subscribes to the same value. The new mode rides
on the event, so the toggle still responds when the localStorage write
throws.

Also:
- `toSplitRows` advanced its cursor only for context/add/delete rows. The
  fourth `ParsedDiffRow` type ("modified") matched no branch and spun the
  loop forever — a synchronous hang no test timeout can interrupt. Key the
  spanning branch off "not added and not deleted" so every pass consumes a
  row by construction.
- Hide the toggle when every file in the diff is a new file: those render
  as plain content in both modes, so the control was a visible no-op on
  exactly the previews a Write tool call produces.
…ping

Each split row was its own flex container of two `flex-1 basis-0` cells.
That container resolves to the tracks' MINIMUM size, and `flex-1` then
halves it — so whenever a row's two sides differ in length, which is the
normal case for a replaced line, the longer side overflowed its cell and
painted across the divider. The opposite column's tinted background and
its own text then painted on top: two lines of code rendered over each
other, illegible. Measured in Chromium (240px of bleed on a 700px host)
and confirmed visually in WebKit.

Give the hunk one grid instead. Shared tracks mean every row breaks at the
same x by construction, and `w-max` sizes the grid to twice its widest
cell so no track is ever narrower than the line it holds; the enclosing
x="scroll" ScrollArea scrolls it, and `min-w-full` keeps short diffs
filling the host. Verified across narrow/medium/wide hosts and across
hunks of differing widths.

Reported by Codex in review; my own first-pass analysis of the flex
intrinsic sizing had it backwards.
@xintaofei

Copy link
Copy Markdown
Owner

codeg work task 102 is done — #570 (13 files, +589/-15).

@xintaofei
xintaofei merged commit 4022805 into xintaofei:main Aug 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

【建议】diff差异支持左右双栏对比视图,现在只支持内联视图

2 participants