feat(editor): optional side-by-side diff view#926
Conversation
📝 WalkthroughWalkthroughAdds a persisted "inline"/"split" diff view preference (DiffViewMode) with a General settings selector, a new SplitDiffView CodeMirror MergeView component, shared read-only extensions and diff themes, and wires GitDiffPane to render either the split view or the existing unified merge view based on the preference. ChangesSplit diff view feature
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/modules/editor/SplitDiffView.tsx (1)
39-98: 🚀 Performance & Scalability | 🔵 TrivialRAM cost: split mode doubles editor instances per diff tab, and tabs never unmount.
MergeViewhere spins up two full CodeMirrorEditorViews (with their own line-numbers, fold-gutter, search, syntax-highlighting extensions) versus one for inline mode. Per TERAX.md, git-diff tabs are kept mounted (hidden, not destroyed) when switched away from, so every background diff tab left in split mode carries roughly 2x the CodeMirror memory footprint of inline mode indefinitely. Given the project's explicit "how much RAM it costs" bar for every change, worth confirming this is an acceptable tradeoff for the feature, or considering some form of idle teardown/lazy-mount for inactive split-mode diff tabs (similar in spirit to the terminal module's renderer pooling).As per coding guidelines, "For every change ask: how much RAM it costs... whether it adds IPC round-trips or redundant requests, whether it triggers extra re-renders or wasted work".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/modules/editor/SplitDiffView.tsx` around lines 39 - 98, SplitDiffView’s MergeView setup keeps two full EditorView instances mounted per diff tab, which doubles RAM usage for background split-mode tabs that never unmount. Update SplitDiffView to avoid retaining the full MergeView when inactive, or add an idle teardown/lazy-mount path for split-mode tabs, using the existing SplitDiffView, MergeView, and viewRef lifecycle to destroy and recreate the editor only when needed.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/modules/editor/SplitDiffView.tsx`:
- Around line 39-98: SplitDiffView’s MergeView setup keeps two full EditorView
instances mounted per diff tab, which doubles RAM usage for background
split-mode tabs that never unmount. Update SplitDiffView to avoid retaining the
full MergeView when inactive, or add an idle teardown/lazy-mount path for
split-mode tabs, using the existing SplitDiffView, MergeView, and viewRef
lifecycle to destroy and recreate the editor only when needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cac04e94-aaf6-437f-9ccd-a9f8c0bc0095
📒 Files selected for processing (6)
src/modules/editor/GitDiffPane.tsxsrc/modules/editor/SplitDiffView.tsxsrc/modules/editor/lib/diffTheme.tssrc/modules/editor/lib/extensions.tssrc/modules/settings/store.tssrc/settings/sections/GeneralSection.tsx
What
Adds a "Diff view" setting so git diffs can render side by side (original left, modified right, aligned line by line) instead of the current inline view. Inline stays the default.
Why
On files with dense changes the inline view gets hard to follow, since deletions and insertions are interleaved in one column. VS Code's side-by-side layout reads much better there. I wanted the same in Terax without forcing it on anyone, so it's a preference.
How
diffViewModepreference ("inline" | "split"), exposed as a Select row under Settings > General > Editor. Follows the existing pref pattern insettings/store.ts, syncs across windows like the rest.SplitDiffViewcomponent wrappingMergeViewfrom@codemirror/merge(already a dependency, the inline view usesunifiedMergeViewfrom the same package).MergeViewis a class managing two editors rather than an extension, so it can't go through<CodeMirror>. The wrapper builds it once per file and then updates in place: content changes land as doc-replacing dispatches and theme changes go through a compartment, so scroll position and expanded regions survive file saves and theme switches.GitDiffPanepicks the view from the pref, which covers both working-tree diffs and commit-file diffs. The binary/large-file patch fallback is unchanged.lib/diffTheme.tsso the inline and split views can't drift apart when colors get tuned.No Rust changes.
git_diff_contentalready returns both full sides of the file, so the split view had everything it needed.Testing
pnpm exec tsc --noEmitcleansrc-tauri/) not applicable, frontend only#[tauri::command]signature) not applicablepnpm tauri devManual flows exercised: toggled the setting with diff tabs open (open tabs switch layout live), working-tree diff and commit diff both render split, saving the file while its split diff is open keeps scroll position, Cmd+F opens search inside the split view, switching editor theme keeps scroll, binary files still fall back to the patch view.
pnpm testpasses (254 tests), biome clean on touched files.Screenshots / GIFs
Notes for reviewer
.cm-mergeViewwithoverflow: auto), which is howMergeViewkeeps the panes aligned. There is no per-pane scrolling.@uiw/react-codemirror'sbasicSetup, so the keymaps and gutters the inline view gets for free (searchKeymap,defaultKeymap, fold gutter, special-char highlighting) are added explicitly. If a parity gap shows up later, that extension list is the place to look.