Skip to content

Latest commit

 

History

History
103 lines (70 loc) · 5.14 KB

STEP3.md

File metadata and controls

103 lines (70 loc) · 5.14 KB

LiteDiff — Step 3 交付说明

同步滚动加固、Minimap 交互、折叠策略。这一轮修掉了 4 个真实缺陷,全部先在浏览器里复现、再修、再验证。

修的缺陷

1. ⌘] / ⌘[ 会卡在同一个差异块(阻塞级)

现象:连按下一个差异,第二次之后位移不再变化。

根因:导航锚点用的是 win.start,它包含视口上方的 overscan 行,永远在视口顶部之上一段。跳到 hunk R 后锚点仍 < R,nextChangeHunk(1) 又返回 R —— 同一个目标无限循环。

修法:Window 增加 firstVisible(不含 overscan 的真实顶部),导航锚定它。

2. 折叠后跳转完全失效(比缺陷 1 更深)

现象:修复 1 后,在 1240 行文档上按 ⌘] 完全不动了。

根因:折叠使显示项与源行成了两套坐标系。(displayIndex − context) × rowHeight 对靠前的目标算出 0,scrollTop 被 clamp 到 0,视口回到顶部,锚点仍是第 0 行 —— 又回到缺陷 1 的循环。同时 displayIndexForRow 只能落到可见项,目标行若被折叠条盖住,它只解析到折叠条本身。

修法:

  • 跳转位移一律在显示索引空间计算,不再混用源行;
  • 新增 foldHidingRow():命中被折叠的行先展开该折叠再跳;
  • 引入 navHunk 记录"上次到达的 hunk",前进/后退按 hunk 序号走,摆脱对滚动位置的依赖;
  • programmaticScroll 标志区分程序滚动与用户滚动,避免自身回显清掉锚点。

3. 长行被静默截断,且横向滚动不同步

现象:代码行被裁掉且无法查看;左栏横向滚动右栏不跟随。

根因:.code 上有 overflow: hidden,.window 是绝对定位且 width: 100%——绝对定位子元素不贡献固有宽度,父级 max-content 也算不出宽度,于是永远没有横向滚动条。

修法:.window 改 width: max-content,去掉 .code/.cell 的裁剪与 contain: layout;横向偏移纳入同一套「单一权威」同步。

4. 展开上方折叠时内容跳动

现象:展开视口上方的折叠条,眼前内容突然上移,丢失阅读位置。

根因:折叠条被替换成 N 行,视口上方内容增高 N−1 行,但 scrollTop 未补偿。

修法:scrollTopAfterExpand() 按折叠条是否在视口上方决定是否补偿。

新增交互

能力 实现
Minimap 点击跳转 按 Y 比例映射到源行
Minimap 拖动擦洗 Pointer Capture,可拖出条外继续
Minimap 键盘 ↑↓ / PageUp/Down / Home / End,带 aria-valuetext
折叠全部 / 展开全部 工具栏按钮 + ⌘⌥E,按当前状态切换
Minimap 视口指示器 改用真实可见行数,不再含 overscan

验证(实测)

Rust

cargo test           51 + 19 + 1 + 5 = 76 passed
cargo clippy         0 warnings

前端

npm test             34 passed(viewport 28 + 渲染模型 2 + 其他 4)
svelte-check         0 errors, 0 warnings
npm run build        60 KB JS / 8 KB CSS(gzip 22.6 / 2.3 KB)

浏览器实测(真实 DOM,非推测)

  • 1240 行文档只渲染 38 行 → 虚拟滚动生效
  • 左栏 scrollTop=1200 → 右栏 1200;右栏 scrollTop=400 → 左栏 400 → 双向严格同步
  • del 底色实测 rgba(244, 63, 94, 0.08),ins 实测 rgba(34, 197, 94, 0.08)
  • pill 实测 rgba(244, 63, 94, 0.28) + border-radius: 2px
  • 斜纹为 repeating-linear-gradient(45deg, …)
  • 行号 font-variant-numeric: tabular-nums
  • 折叠条显示「⋯ 38 行未变动」
  • ⌘] 连续 6 次、⌘[ 连续 3 次,位移单调推进/回退
  • ⌘D 双向切换分栏/内联正常

性能(21,500 行文档)

折叠投影  0.3ms
224 次窗口计算  0.1ms
单屏最多渲染  65 行

应用冒烟:release 二进制 4.8 MB,启动后进程稳定、窗口创建、无 stderr 输出。

新增开发能力

vite dev 下可用 window.__litediffMock 注入 fixture 跑真实 UI。这让前端能在没有 Rust 后端时完整调试布局;打包后该分支不可达(真实 IPC 恒存在)。

仍未做

  • 就地编辑 / ⌘S 覆写 / "采纳更改"箭头:后端 save_file(原子写)已就绪,前端编辑器与虚拟滚动冲突,需要单独设计。
  • 内联视图未虚拟化:显示项翻倍仍在预算内,10 万行级需并入同一窗口算式。
  • 文件夹拖拽:expand_directory 已实现,前端只处理单文件。
  • ⌘⇧W 语义:当前是 ignore_all_whitespace(忽略全部空白),原始规格写的是"忽略首尾空白与换行符"。严格按字面只需改一行。

一个需要你决定的设计问题

缺陷 1/2 暴露了一个更深的产品问题:折叠状态下,相邻差异块在视觉上可能只隔几十像素(因为中间的大段未变动内容被折叠了)。我现在的做法是每步都精确跳到目标 hunk,此时视口里常常同时出现多个差异块。

如果你希望"⌘] 一次只看一个差异"(即跳转时自动展开目标块前后的上下文),这需要改折叠策略,我等你确认再动。