Skip to content

feat(UI): 全面对齐 VS Code 1.136 最佳实践——修复 9 项缺陷并系统性升级控件/交互/API 适配 - #116

Merged
ThreeFish-AI merged 13 commits into
feature/1.x.xfrom
ThreeFish-AI/vscode-ui-best-practice-audit
Sep 9, 2026
Merged

feat(UI): 全面对齐 VS Code 1.136 最佳实践——修复 9 项缺陷并系统性升级控件/交互/API 适配#116
ThreeFish-AI merged 13 commits into
feature/1.x.xfrom
ThreeFish-AI/vscode-ui-best-practice-audit

Conversation

@ThreeFish-AI

Copy link
Copy Markdown
Owner

概述

对系统 UI 做全方位审计(Webview UI / 原生 API / 清单集成三路并行)后,基于最新版 VS Code(1.136,2026-09)最佳实践完成的系统性适配:12 个提交、46+ 文件、+1500/−460,涵盖 9 项缺陷修复、进度反馈/入门导览/批量操作/输入校验等新能力、控件全面令牌化与无障碍加固。

审计基线

  • 最新稳定版 VS Code 1.136(集成测试即在该版本真实宿主上全绿);官方已废弃 Webview UI Toolkit(2025-01),推荐纯 --vscode-* CSS 变量方案——本项目路线正确,本 PR 补齐其执行深度。
  • engines.vscode 维持 ^1.85(审计确认所有待用 API ≤1.85,无需抬基线)。

修复的缺陷(Fixed)

# 缺陷 影响
1 webview 回调内重复调用 acquireVsCodeApi() Merge「保存→拒绝→取消」取消失效(第二次调用抛异常)
2 Commit 草稿随视图销毁丢失 message/amend/signoff/skipHooks 全丢且模板重灌覆盖
3 深浅主题切换后 Graph 泳道色停留旧主题 JS 快照无 MutationObserver 监听
4 分支树文件夹节点出现分支级菜单 11 处 viewItem =~ 正则未锚定误匹配 branchFolder
5 CLI 通道失败不可诊断 execFile 丢弃 stderr
6 交互 rebase 的 reword 可能拉起新 VS Code 窗口 GIT_EDITOR 未设 ELECTRON_RUN_AS_NODE
7 窗口 reload 后 Rebase/Merge 面板空白 registerWebviewPanelSerializer
8 git 扩展不可用时多视图报 "no tree view registered" 缺空 provider 兜底
9 Blame 注解悬浮换行折叠 / split 编辑器无注解 / 泄漏 MarkdownString + 可见编辑器订阅

另有对抗性验证工作流确认并已修复的 2 项次生问题:草稿跨仓泄漏(切到无草稿仓库时旧仓 amend 标志残留并持久化污染)、hyperGit.hasConflicts 恒 false(vscode.git 的 unmerged 只在 mergeChanges,原 getChanges() 谓词不可达,Accept Ours/Theirs 在面板永久隐藏)。

新能力(Added)

  • 长时操作进度反馈:pull/push/fetch/merge/rebase/cherry-pick/reset/updateProject 全部 withProgress(默认标题栏非阻塞);失败通知附 "Show Output" 直达 Console
  • 入门导览walkthroughs 5 步导览 + 2 条无冲突默认键位(Alt+B Blame、Alt+G Graph 过滤)
  • Stash/Worktrees 多选批量操作(降序 drop 防位移)、新建后视图定位、provider 失败 TreeView.message 内联呈现
  • 分支/标签名即时校验engine/ref/ref-name 纯函数(check-ref-format UI 子集,9 组单测)挂接全部 8 处输入框
  • QuickPick:提交选择器 hash 可搜(matchOn*)、Separator 分段、codicon 图标统一
  • 键盘可达性:Commit 文件列表方向键/Enter/Escape 导航、Rebase Alt+↑/↓ 键盘重排 + 确认层焦点圈禁

控件与主题(Changed)

  • 滚动条/checkbox/下拉/阴影全面走主题令牌;字号以 --vscode-font-size calc 派生(随用户设置缩放);高对比度主题下彩色胶囊改描边;Graph 行高/列宽常量单源化
  • 文件状态点 M/A/U/R/D/C 字母标记(色盲可辨,对齐官方 SCM);8 处 Unicode 字符图标 SVG 化
  • 日志通道迁 LogOutputChannel(自动时间戳/级别,懒创建);确认框多行正文迁 MessageOptions.detail;用户可见文案统一英文
  • 清单治理extensionKind: workspaceuntrustedWorkspaces: unsupported、11 项设置补 scope、5 个预留设置中性化(默认值清除个人化内容,默认值变更)、palette 补 when 限定
  • 同步 IO 清理(Shelf 全量 fs.promises、worktree realpath 记忆化)

验证

  • ✅ 420 单测通过(新增 ref-name 9 组、menus-guard 5 组守护测试)
  • ✅ 集成测试在真实 VS Code 1.136.2 宿主全绿(单仓 8/8 + 多根 4/4)
  • ✅ 四维对抗性验证工作流(webview 内联 JS 语法/XSS、host 正确性、清单一致性、回归风险):确认 2 项真实问题均已修复并复验
  • 每批次独立 commit(12 个),逐批 compile + lint + test:unit

明确不做(后续立项)

l10n、codicon 字体引入、webview 拆分打包、README/图片优化、engines 提升、CI 最低版本矩阵档、withProgress 真取消。

🤖 Generated with Claude Code, CodeX, Gemini
Co-Authored-By: Aurelius Huangthreefish.ai@gmail.com

- merge/rebase 面板脚本回调内重复调用 acquireVsCodeApi()(每 webview 仅允许一次)改为顶部获取后全程复用,修复 merge「保存→拒绝确认→取消」路径取消失效的问题;
- reword 的 GIT_EDITOR 经 process.execPath(扩展宿主内为 Electron 二进制)运行,补 ELECTRON_RUN_AS_NODE=1 防止拉起新编辑器进程;
- rebase/merge 两个 retainContextWhenHidden 面板补 registerWebviewPanelSerializer:窗口 reload 后 rebase 按 webview state(base + 用户编辑后的 todo 行序/action/subject)恢复,merge 按 filePath 重拉三阶段冲突数据恢复,无有效 state 时渲染过期占位页;
- 面板 onDidReceiveMessage 订阅随 onDidDispose 释放;
- 抽公共 getNonce(randomUUID hex)替代各 webview 内联 nonce 生成,本批迁移 merge/rebase。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- Webview state v2 升 v3:byRepo 分区新增 draft(message + amend/signoff/skipHooks),视图隐藏销毁或窗口 reload 后草稿可恢复,对齐内置 SCM 输入框草稿语义;
- 草稿在输入/勾选变更时即时落盘(saveState 从 DOM 现值取数),彻底消除 200ms debounce 尾丢与模板重灌覆盖问题;
- 草稿回灌仅两时机(webview 重建首帧 / 活跃仓库切换),且先于 reconcileChecked 执行,避免 state 推送往返中覆盖当前编辑内容;
- 提交成功清空草稿(失败保留供重试);最近消息 chip 应用与模板注入同步入草稿;
- 旧版 state(v2 byRepo / v1 平铺)无感升级;nonce 生成迁移至公共 getNonce。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- Graph 泳道色由启动期一次性 getComputedStyle 快照改为 MutationObserver 监听 body 属性(rAF 节流重算),深浅主题热切换后泳道色/chip 即时更新(webview 不随换主题重载,此前 JS 快照停留旧主题);
- Blame 注解:hover 改 MarkdownString.appendText(换行真实生效 + markdown 转义);订阅 onDidChangeVisibleTextEditors——split 编辑器自动补挂/卸载装饰,文档全部关闭后移出注解表(防泄漏);
- 行内提交 CodeLens:title 改 $(check) codicon(随 product icon theme 渲染);provideCodeLenses 补 CancellationToken 检查;emitter 补 dispose 并入 subscriptions;临时 patch 文件改异步 IO;
- 用户可见文案统一英文:分支/远程分支删除确认(cleanup/remote-ref)、Conventional Commits 校验提示;同步更新 ref-cleanup/ref-remote 测试断言;
- 树 tooltip 冗余赋值清理(构造器第二参即 supportThemeIcons);relativeDate 委托 engine/log/format-time.formatRelative(单一事实源,措辞对齐官方 GRAPH)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 runWithProgress 封装:pull/push/fetch/prune/cherry-pick/revert/reset/merge 默认 ProgressLocation.Window(标题栏非阻塞,对齐内置 Git 视图),updateProject 与交互 rebase 用 Notification;只包裹用户交互完成后的 git 执行段;
- 日志通道迁移 LogOutputChannel(1.74+,自动时间戳与级别、统一日志视图):Hyper Git 运行日志懒创建 + 随扩展释放;Hyper Git Console 保留 $ git 命令誊录形态并纳入统一日志;
- execFile 透传 stderr:真实失败原因挂到错误对象并记入 Console(此前 CLI 通道失败只报通用 message,不可诊断);
- git 操作失败通知统一加 "Show Output" 动作按钮(showGitError helper),直达 Console 诊断信息;
- 4 处 modal 确认框多行正文从 message 首参迁至 MessageOptions.detail(模态框次要文字载体,对齐 VS Code 对话框规范):本地/远程分支删除、Worktree 删除与 prune。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- stash/worktrees 由 registerTreeDataProvider 统一改 createTreeView:canSelectMany 启用批量操作——Stash 批量 Drop(按 index 降序删除防位移错删)、Worktree 批量 Remove(main/当前打开项跳过并明示);Branches 树补 showCollapseAll;
- provider 加载失败经 TreeView.message 视图内联呈现(stash/worktree 接线 setViewMessageSink,不再静默成空树);stash label 截断移交渲染层(VS Code 树自带省略,完整内容在 tooltip);
- git 扩展不可用分支兜底:branches/stash/worktrees/shelf 注册空 provider(viewsWelcome 生效),Commit/Graph webview 渲染静态占位说明页(此前视图报 no tree view registered / 空白);
- 新建 stash/worktree/shelf 后聚焦对应视图引导定位(三视图默认隐藏);
- 同步 IO 热点清理:worktree 路径归一 realpathSync 结果记忆化(原每行渲染同步 IO);ShelfService 全量迁 fs.promises(listShelves 在 getChildren UI 请求路径,原同步 readdir/readFile 阻塞扩展宿主),迁移语义零变(零删除/零覆盖/可重试);
- 顺带完成 stash/worktree/shelf 错误通知的 Show Output 迁移(承接上一提交)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 engine/ref/ref-name.validateRefName 纯函数(git check-ref-format 的 UI 子集:空值/首尾空白/前导 -/非法字符集/../@{/.lock/点组件/斜杠规则,branch 禁 HEAD、tag 禁 #)+ 9 组单测矩阵;
- 分支/标签名输入框全部挂接即时校验(branchCreate/branchRename/tagCreate/createBranchFromCommit/createTagFromCommit/checkoutAsNew/stashBranch/worktreeAdd),非法输入内联提示无需提交后才报错;worktree 多步输入补 ignoreFocusOut(失焦不丢上下文);
- 提交选择器(cherry-pick/revert/reset/reword 等 pickCommitHash/pickResetTarget)补 matchOnDescription/matchOnDetail——输入 hash 前缀可直接命中;
- rebase base 选择与 tagCreate 目标选择插 QuickPickItemKind.Separator 分段(快捷项 ⇄ Recent Commits);
- Commit 视图文件右键菜单与 pushDialog 危险模式项统一 $(codicon) 图标(⚠ Unicode 字符移除)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 11 处 viewItem =~ 正则补 ^…$ 锚定:未锚定正则误匹配 contextValue 前缀(hyperGit.branchFolder 命中 /hyperGit.branch|…/ 导致分支树文件夹行出现 Checkout/Merge/Rebase 等菜单),worktrees 同理;
- 补 extensionKind: workspace(依赖本地 git,防止远程场景误分类到 UI 侧)与 capabilities.untrustedWorkspaces: supported=false(扩展会执行 commit/push/discard,受限工作区不应照常启用);
- 11 项设置全部补 scope(commit.*/log.ci.*→resource、agent.*→window、claudeCode.executablePath→machine-overridable);
- 5 个预留设置中性化:ai.enabled 与 agent.* 描述明确标注 Reserved(当前版本无效果),agent 偏好默认值清除个人化内容(个人签名/提交规约/mcp__conductor__* 引用不再分发给所有用户);
- commandPalette 补 when 限定:log.scope*/detailTree/detailFlat 仅 Graph 视图聚焦时可见;acceptOurs/acceptTheirs 按新增 hyperGit.hasConflicts context key 显隐(extension.ts 于刷新快路径计算冲突存在性);
- 图标语义修正:ignorePath $(eye-closed)→$(diff-ignored);rebase 相关 $(call-out)→$(arrow-right);6 个可见视图补 contextualTitle(拖出容器时标题不退化);容器 SVG 注释修正(Panel 容器而非 activity-bar);
- 新增 menus-guard 守护单测:viewItem 正则必须锚定 / 设置必须有 scope / 可见视图必须有 contextualTitle / extensionKind 与 untrustedWorkspaces 声明。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 walkthroughs 贡献点(Get Started with Hyper Git,5 步):打开 Panel 容器 → Commit 与 changelist → Graph 与过滤 → Branches 分组树 → Shelf/Stash/Worktrees,primary 指向 Commit 步;素材为 media/walkthrough/ 下 5 个轻量 markdown(含 command: 跳转链接,无重截图依赖);
- 新增 2 条无冲突默认键位(when 严格限定作用域):Alt+B 切换 Blame 注解(editorTextFocus)、Alt+G 打开 Graph 过滤(focusedView == hyperGit.log);Ctrl/Cmd+Enter 提交已内建于 Commit webview 消息输入框(键入态宿主键绑定不拦截,manifest 绑定无增益,不重复声明)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- shared-styles 升级为全局控件基线:滚动条走 --vscode-scrollbarSlider-*(webview iframe 内 Chromium 原生滚动条与宿主主题割裂)、checkbox accent-color(--vscode-checkbox-background,深色主题不再白底黑框)、新增 .hg-select 基类(统一 dropdown token)、forced-colors 高对比回退、body 行高 1.4;
- Graph 行高/泳道列宽单源化:导出 GRAPH_ROW_H/GRAPH_LANE_W 常量,CSS 变量与内联 JS 常量同源注入(原 --hg-row: 24px 与 ROW_H=24 双源,用户调大字号时会漂移裁切);
- 字号全线 calc(var(--vscode-font-size) - Npx) 派生(四个 webview 共 25 处硬编码 px),随用户字号设置缩放;
- 高对比度主题:Graph 彩色引用 chip 改 contrastBorder 描边 + 主题前景色(!important 覆盖行内注入,消除 HC 下大面积彩色填充);
- 硬编码色清整:CI 浮层/确认框阴影 rgba(0,0,0,.35/.4) → --vscode-widget-shadow;#8b949e GitHub-dark 回退清理;monospace 泛型回退 → UI 字体;commit body 补 --vscode-sideBar-background 声明(防白闪);
- rebase select 与 commit changelist 下拉统一迁 .hg-select(原 input/dropdown token 混用);commit 最近消息 .chip 改名 .hg-chip(消除与 Graph 泳道 chip 跨文件同名冲突);commit spinner 补 prefers-reduced-motion 降频豁免;死 token 清理(--hg-radius-panel/--hg-space-3/4/6/.hg-row 类);log nonce 迁公共 getNonce(收尾);
- shared-styles 测试同步:常量与 CSS 一致性断言、控件基线断言、字号派生断言。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 文件状态点 ●(仅靠颜色区分状态,色盲不可辨)改为 M/A/U/R/D/C 字母标记:protocol 契约新增 CommitFileItem.letter,host 下发 status-decoration 的 letter,webview 着色渲染(对齐官方 SCM 角标与 Graph 面板既有形态);
- 8 处 Unicode 字符图标全部 SVG 化(跨平台字体渲染不一致且部分进读屏):▸▾ 折叠箭头 → chevron SVG(CSS rotate 表达折叠态,commit/Graph 面板两处);⋯ changelist 菜单 → ellipsis SVG;⌥ 空态占位(语义完全错误的 Option 键符号)→ git-commit 型 SVG;⇠ merge 标记 → 双父节点 graph SVG;× 关闭 → X SVG;‹› 冲突导航 → 旋转 chevron;
- 校验前缀 ✓/⚠/ℹ 与文本分离(图标字符 aria-hidden 不进读屏)+ \\uFE0E 强制文本呈现(防部分平台渲染为彩色 emoji);
- Commit 文件列表键盘可达(复刻 Graph #viewport 模式):容器 tabindex=0 role=tree,ArrowUp/Down/Home/End 移动、Enter 触发行、Escape 归还焦点;键盘焦点描边样式;
- Rebase 拖拽补键盘替代路径(WCAG 2.1.1):行内 Alt+↑/↓ 整行移动;确认层补 Escape 关闭、Tab 焦点圈禁(背景表格不可达)、关闭后焦点还原触发按钮;
- .seg 分段按钮与 .hg-chip 最近消息补 :focus-visible(此前键盘 Tab 无任何焦点指示);
- 共享 SVG 图标常量沉淀 shared-styles(ICON_CHEVRON_DOWN/ICON_CLOSE/ICON_ELLIPSIS,currentColor 随主题)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- CHANGELOG Unreleased 段新增 Fixed/Added/Changed/Docs 四组共 17 条目,覆盖本次 10 个批次(功能性 bug 修复、进度反馈/导览/键位/批量操作/输入校验新能力、控件主题化与设置治理、文档与 Issue 沉淀);
- issue.md 新增 #17(acquireVsCodeApi 回调内重复调用)与 #18(Commit 草稿随视图销毁丢失)两条跨上下文经验(表因/根因/处理/防范/同类影响)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- Commit 草稿回灌改为切换/重建时无条件同步 DOM(目标仓库无草稿则清空 message 与 amend/signoff/skipHooks):原 `restoreDraft && draft` 门控在切到无草稿仓库时残留旧仓库内容,随后 saveState 从 DOM 取数将旧仓草稿持久化写入新仓分区(跨仓串扰;amend=true 泄漏最坏静默改写新仓 HEAD);清空分支同步上报 messageChanged 使宿主校验态一致;
- loadPersistedFor 的 '' 条目兜底仅限旧版 state(v1/v2 迁移语义),v3 起按仓严格隔离,杜绝无仓库会话期的草稿回灌到其他仓库;
- hyperGit.hasConflicts 改用 vscode.git 的 mergeChanges 为事实源:7 种 unmerged 状态只进该数组,getChanges 的 status 映射恒判不出冲突,原实现致 context key 恒 false、Accept Ours/Theirs 在命令面板永久隐藏;
- 两项均由四维对抗性验证工作流确认(含 DOM shim 实测复现与修复后验证)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- shelf: migrateLegacyShelves 异步化后补回 shelvesBase 存在性守卫,全新安装
  (从未创建过 shelf)时 readdir 不再以 ENOENT 误报 migrateLegacy:failed 污染
  Hyper Git Console("Show Output" 引导的诊断通道);
- commit: 新增 stateV3Written 标志,本会话首写 v3 state 后即关闭 '' 条目兜底——
  修复 persistedRaw.v 启动快照导致升级/全新会话内跨仓草稿回灌门未生效的问题,
  按仓隔离无需等到下一次 webview 重建。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
@ThreeFish-AI
ThreeFish-AI merged commit 2a81a95 into feature/1.x.x Sep 9, 2026
5 checks passed
@ThreeFish-AI
ThreeFish-AI deleted the ThreeFish-AI/vscode-ui-best-practice-audit branch September 9, 2026 15:58
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.

1 participant