Skip to content

Commit efcc410

Browse files
authored
Merge pull request #110 from yangboxuan726/codex/windows-compact-diff
fix(windows): match compact IDEA diff layout
2 parents 9550655 + c468391 commit efcc410

28 files changed

Lines changed: 1073 additions & 63 deletions
20.4 KB
Loading
90.2 KB
Loading
20.1 KB
Loading
460 KB
Loading
46.7 KB
Loading
54.1 KB
Loading

windows/tauri/design-qa.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Design QA: Windows Source Control diff
2+
3+
- Added-file reference: `D:/Downloads/document/xwechat_files/wxid_id17m8qt937c22_c153/temp/RWTemp/2026-08/1aede52250875b292d874992a7f6d5b7/f38120ff65bc487d72adb50de30e6dc7.png`
4+
- Split modified-file reference: `D:/Downloads/document/xwechat_files/wxid_id17m8qt937c22_c153/temp/RWTemp/2026-08/1aede52250875b292d874992a7f6d5b7/2d6a05680ba07a8527dd10e69bdecacc.png`
5+
- Native Windows added-file capture: `design-qa-artifacts/native-windows-added-diff.png`
6+
- Native Windows modified-file capture: `design-qa-artifacts/native-windows-split-diff.png`
7+
- Combined reference/implementation input: `design-qa-artifacts/native-reference-comparison.png`
8+
- Native viewport: 1362 x 856, dark theme.
9+
10+
## Result
11+
12+
The working-tree diff now follows the reference hierarchy: file/status title, compact diff toolbar, explicit version header, blue hunk header, and semantic code body. The implementation keeps Lithe's native Windows chrome and design tokens while matching the reference's information architecture.
13+
14+
### Added file
15+
16+
- The untracked three-line fixture reports `+3 -0` in Source Control and `+3` on the file row.
17+
- Selecting the file opens the diff surface, not a normal text editor or serialized patch.
18+
- The header identifies `ADDED`, `WORKTREE`, and `Added version`.
19+
- The hunk range is visible as `@@ -0,0 +1,3 @@`.
20+
- All three source rows use the full-width added background with an added rail and independent line numbers.
21+
- Side-by-side mode is disabled because a new file has no previous version.
22+
23+
### Modified file
24+
25+
- The left pane is labeled `Index version`; the right pane is labeled `Current version`.
26+
- Both panes use independent line-number gutters and compact source streams.
27+
- Removed content is red on the left and added content is green on the right.
28+
- The center connector gutter is 28 px and shows curved transition bands with direction markers.
29+
- The layout does not add fake blank code rows to the side that does not own a line.
30+
31+
### Interaction and native verification
32+
33+
- Verified in the running Tauri Windows application through native window capture and input.
34+
- Clicking both untracked and tracked file rows opens the expected diff.
35+
- Unified/side-by-side controls follow file type, and the whitespace control remains interactive.
36+
- The temporary tracked-file change used for split verification was restored; the test repository was left with only the user's original untracked `c.txt`.
37+
38+
### Automated verification
39+
40+
- `bun test`: 51 passed, 0 failed.
41+
- `bun run typecheck`: passed.
42+
- `bun run lint -- ...`: passed for the changed files; existing unrelated repository warnings remain.
43+
44+
No actionable P0, P1, or P2 visual mismatch remains in the requested added-file and modified-file diff flows.
45+
46+
final result: passed

windows/tauri/src-tauri/src/platform.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,29 @@ mod tests {
679679
);
680680
}
681681

682+
#[test]
683+
fn translates_untracked_diff_file_pathspec() {
684+
let (command, payload) = translate(
685+
"git_diff_file",
686+
json!({
687+
"repoPath": "C:/work",
688+
"filePath": "new.txt",
689+
"untracked": true
690+
}),
691+
)
692+
.unwrap();
693+
694+
assert_eq!(command, "git.diff");
695+
assert_eq!(
696+
payload,
697+
json!({
698+
"root": "C:/work",
699+
"pathspecs": ["new.txt"],
700+
"untracked": true
701+
})
702+
);
703+
}
704+
682705
#[test]
683706
fn translates_status_diff_stats_whole_tree() {
684707
let (command, payload) = translate(

windows/tauri/src/features/editor/stores/buffer-pane-sync.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { PaneGroup } from "@/features/panes/types/pane.types";
33
import type { PaneContent } from "@/features/panes/types/pane-content.types";
44
import { ensureBufferInPane } from "@/features/panes/utils/pane-buffer-actions";
55
import {
6+
resolveMainPaneForBufferOpen,
67
resolveMainPaneForExternalOpen,
78
resolveWritablePaneForBuffer,
89
} from "@/features/panes/utils/pane-routing";
@@ -64,6 +65,22 @@ export const syncAndFocusBufferInPane = (bufferId: string, workspaceId?: string)
6465
syncBufferToPane(bufferId, workspaceId);
6566
};
6667

68+
export const syncAndFocusBufferInMainPane = (bufferId: string, workspaceId?: string) => {
69+
const paneStore = getPaneState(workspaceId);
70+
const targetPane = resolveMainPaneForBufferOpen({
71+
activePaneId: paneStore.activePaneId,
72+
bufferId,
73+
mostRecentActivePaneIds: paneStore.mostRecentActivePaneIds,
74+
root: paneStore.root,
75+
});
76+
if (!targetPane) return;
77+
78+
if (targetPane.id !== paneStore.activePaneId) {
79+
paneStore.actions.setActivePane(targetPane.id);
80+
}
81+
syncBufferToPane(bufferId, workspaceId);
82+
};
83+
6784
export const syncPanePreviewForBuffer = (
6885
bufferId: string,
6986
isPreview: boolean,

windows/tauri/src/features/file-system/stores/file-system.store.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import {
1515
clearQueuedWorkspaceSessionSave,
1616
useBufferStore,
1717
} from "@/features/editor/stores/buffer.store";
18+
import {
19+
activateMainEditorPane,
20+
syncAndFocusBufferInMainPane,
21+
} from "@/features/editor/stores/buffer-pane-sync";
1822
import { getBufferById, getBufferByPath } from "@/features/editor/utils/buffer-index";
1923
import { fileOpenBenchmark } from "@/features/editor/utils/file-open-benchmark";
2024
import { getLineSlice } from "@/features/editor/utils/large-file";
@@ -1476,6 +1480,8 @@ const createFileSystemStore = (workspaceId: string): StoreApi<ScopedFileSystemSt
14761480
fileOpenBenchmark.ensureStarted(path, isPreview ? "preview" : "definite");
14771481
fileOpenBenchmark.mark(path, "file-select-handler");
14781482

1483+
activateMainEditorPane(workspaceId);
1484+
14791485
const {
14801486
buffers,
14811487
activeBufferId,
@@ -1486,6 +1492,7 @@ const createFileSystemStore = (workspaceId: string): StoreApi<ScopedFileSystemSt
14861492
const existingBuffer = getBufferByPath(buffers, path);
14871493
if (existingBuffer) {
14881494
const wasAlreadyActive = existingBuffer.id === activeBufferId;
1495+
syncAndFocusBufferInMainPane(existingBuffer.id, workspaceId);
14891496
setActiveBuffer(existingBuffer.id);
14901497
recordLocalFileAccess(path, fileName, workspaceRootPath, getWorkspaceFolderPaths(get));
14911498

0 commit comments

Comments
 (0)