fix: restore consistent controls, usable overlays and narrow layouts
Resolve 15 shared-control, overlay and responsive-layout issues plus the MCP editor being hidden behind settings. Restore theme contrast, danger and disabled states, visible keyboard focus, and consistent Continue fields. Keep the workbar add button reachable and model protocol values readable in narrow containers.
Make nested MCP and image dialogs usable above their parents with focus restoration, keep project Escape handling within the active modal, release native browser views for overlapping help, and restore keyboard access and Escape in sandboxed HTML previews without relaxing sandbox permissions. Add unit and real Electron regression coverage and update design and validation documentation.
Release note: 修复深浅主题下控件边框、危险操作、禁用状态和键盘焦点显示不一致的问题。MCP 编辑器与图片预览可在父弹窗上正常操作,HTML 全屏预览支持键盘进入和 Escape 返回;窄工作栏的添加按钮保持可用,模型连接协议文字完整可读。
Validation: the full suite recorded 5309 passed, 3 failed and 83 skipped. The ProjectSwitcher initial-focus regression was then fixed, and App, ProjectSwitcher and overlay Electron tests passed all 331 cases. The other two HeartbeatCenter failures were reproduced on isolated HEAD 11facf0 and remain pre-existing. Typecheck and lint passed after the fix; staged whitespace checks passed. The full suite was not rerun after the focused fix.
Limits: Electron evidence is from Windows development runs, with fixtures for unrelated services and native occlusion throttling disabled in some drivers. No production build, packaging, macOS/Linux, remote Agent host or external MCP connection validation; skipped tests and the documented scaling and native-select coverage gaps remain.
This commit is contained in:
@@ -81,12 +81,14 @@ Record<ConversationId, Record<BrowserTabId, BrowserLiveState>>
|
||||
|
||||
`BrowserViewport` 统一观察 body Portal 的插入、移除和可见属性变化,以及浮层尺寸、
|
||||
窗口尺寸、滚动和过渡结束。`browser-viewport-occlusion.ts` 按共享语义识别
|
||||
`aria-modal="true"`、dialog、alertdialog、menu 和应用通知:可见应用级 Modal 始终释放
|
||||
`aria-modal="true"`、dialog、alertdialog、menu、tooltip 和应用通知:可见应用级 Modal 始终释放
|
||||
viewport,其余浮层只在与浏览器区域相交时释放。隐藏节点和隐藏祖先不阻塞浏览器。
|
||||
最后一个遮挡消失后,只有当前活动实例恢复同一 viewport 租约;网页、历史和页面状态不变。
|
||||
终端关闭确认复用此机制,不再维护单独的隐藏条件。页面无需逐个登记弹窗,也不能靠提高
|
||||
CSS `z-index` 覆盖原生子视图。此逻辑仅涉及 Desktop Renderer 的显示租约,不改变
|
||||
Runtime、MCP 或远端 Agent 的请求、导航与生命周期。
|
||||
同行帮助仍使用 `role="tooltip"`;相交判定使用其内容矩形,不使用铺满窗口的
|
||||
`FloatingPortal` 宿主。真实 App 的相交与非相交验证见[浮层审查修复记录](../../quality/overlay-review-2026-09-27.md)。
|
||||
|
||||
浏览器应用声明 `visibleAcrossContextSwitches: true`,打开的 Tab 跨项目、会话切换继续显示。
|
||||
切换活动 Conversation 不改变当前选中的浏览器或其 `targetRef.conversationId`;用户在会话 B
|
||||
|
||||
@@ -234,7 +234,7 @@ Runtime
|
||||
从当前聊天右栏迁移时,Task Center 和工作区作为默认打开、单实例且不可关闭的基础应用保留;
|
||||
浏览器保留一个默认打开实例,但注册为可关闭的多实例应用;成果保持默认打开、单实例且可
|
||||
关闭;终端不默认打开,由用户通过“+”创建,并从首期开始支持多实例。Tab 必须单行横向滚动,
|
||||
不能自动隐藏或缩写到不可辨认,“+”紧随最后一个 Tab 并随标签滚动,溢出时两端提供固定滚动箭头。Task Center 继续作为 Task 的现有
|
||||
不能自动隐藏或缩写到不可辨认。“+”固定在滚动区外的行末,溢出时页签区两端提供固定滚动箭头,箭头不覆盖“+”。Task Center 继续作为 Task 的现有
|
||||
入口;审批定位到所属 Task 或 Runtime。智能心跳不作为工作栏页签,其报告、建议、历史和
|
||||
完整配置统一归属“智能心跳”菜单入口。当前阶段不新增独立自动化中心。
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# 工作栏实现与验证进度
|
||||
|
||||
## 2026-09-27:窄栏添加入口
|
||||
|
||||
“+”已移出页签滚动容器;左右箭头和溢出测量使用扣除添加按钮宽度后的页签区域。
|
||||
Windows Electron 回归覆盖 `300px` 工作栏、默认四页签和 16 个含长标题的页签,验证
|
||||
原生鼠标打开应用目录、创建浏览器实例、Escape 返回、箭头滚动及 Home/End 激活。
|
||||
窄栏扩到 `900px` 后,默认页签的溢出箭头消失,缩回后恢复。
|
||||
中英文、浅深主题均通过,模型调用 0 次。范围与命令见
|
||||
[窄容器布局修复记录](../../quality/responsive-controls-review-2026-09-27.md)。
|
||||
|
||||
## 2026-09-27 Continue Update Status
|
||||
|
||||
The shared Continue adapter now skips the update service before it emits the
|
||||
|
||||
@@ -180,9 +180,9 @@ stdio fallback。首期远程终端随 SSH Channel 结束,不提供跨 SSH 或
|
||||
|
||||
- 已打开实例位于一个语义化 `tablist` 中。
|
||||
- 每个实例使用独立 `tab` 和 `tabpanel`。
|
||||
- “+”固定在 Tab 行末尾,但位于 `tablist` 之外。
|
||||
- Tab 过多时实例区域单行横向滚动,不换行、不自动隐藏实例。“+”紧随最后一个标签并随标签一起滚动,滚到末尾时可见。
|
||||
- 标签全部可见时隐藏左右滚动按钮;溢出时左右箭头透明浮动于工作区两端,不占标签布局宽度。鼠标移入标签栏时显示可滚动方向的箭头,移出后隐藏;键盘聚焦箭头时显示,无悬停能力的设备保持可滚动方向的箭头可见。悬停箭头时显示轻微底色。点击滚动约一屏,边界方向禁用并隐藏,避免与末尾“+”重叠,且不拦截下方标签的指针操作。切换或新增激活标签时将其滚入可见区域。未激活标签使用低对比度灰蓝底色和细边框,激活标签保留亮底与强调色顶线。
|
||||
- “+”固定在 Tab 行末尾,位于 `tablist` 和页签滚动容器之外,占用独立宽度。
|
||||
- Tab 过多时实例区域单行横向滚动,不换行、不自动隐藏实例。“+”在 `300px` 工作栏内也保持可见和可点击。
|
||||
- 标签全部可见时隐藏左右滚动按钮;溢出时左右箭头透明浮动于页签区域两端,不占标签布局宽度,也不进入“+”的点击区域。鼠标移入标签栏时显示可滚动方向的箭头,移出后隐藏;键盘聚焦箭头时显示,无悬停能力的设备保持可滚动方向的箭头可见。悬停箭头时显示轻微底色。点击滚动约一屏,边界方向禁用并隐藏,且不拦截下方标签的指针操作。切换或新增激活标签时将其滚入可见区域。未激活标签使用低对比度灰蓝底色和细边框,激活标签保留亮底与强调色顶线。
|
||||
- 终端 Tab 默认使用递增标题,例如“终端 1”“终端 2”;状态栏持续显示项目、Host、
|
||||
工作目录和 Shell。用户可以重命名终端。
|
||||
- 任务中心、工作区、成果及新建终端的默认标题随界面语言切换,恢复布局时也使用当前语言。
|
||||
@@ -565,7 +565,7 @@ Schema、假数据终端或不可用入口的中间产品。
|
||||
- [x] 连续选择浏览器会创建页面、导航状态和元素引用相互独立的浏览器 Tab。
|
||||
- [x] 连续选择终端会创建多个互相独立的终端 Tab。
|
||||
- [ ] 关闭可关闭实例、切换和重排实例后,“+”仍保持可用。
|
||||
- [ ] Tab 溢出时单行横向滚动,两端箭头固定,“+”跟随最后一个 Tab,滚到末尾可见,不把 Tab 换成下拉框。
|
||||
- [ ] Tab 溢出时单行横向滚动,页签区两端箭头固定,“+”在滚动区外持续可见,不把 Tab 换成下拉框。
|
||||
- [x] 关闭可关闭的活动 Tab 后激活正确的相邻 Tab 并恢复焦点。
|
||||
- [x] 当前 Tab 的背景、边框、顶部指示和字重清晰可辨;关闭按钮仅在悬停、焦点或无悬停
|
||||
设备上出现,且不引发布局位移。
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 会话 HTML 渲染实现进度
|
||||
|
||||
2026-09-27 浮层审查修复:全屏 iframe 已纳入共享焦点循环,跨文档 Escape 通过受限
|
||||
Main/Preload 通知返回外层。真实 App 中的带链接及纯正文预览均已验证键盘进入和 Escape,
|
||||
带链接预览另验证正反向 Tab 返回;没有开放 sandbox 权限或执行预览脚本。
|
||||
实现与测试范围见[浮层审查修复记录](../../quality/overlay-review-2026-09-27.md)。
|
||||
|
||||
## 已实现
|
||||
|
||||
- [x] 应用级持久开关,默认开启,并提供旧设置迁移。
|
||||
|
||||
@@ -56,6 +56,17 @@ iframe 无法按内容自适应高度,因为 `sandbox=""` 不含 `allow-same-o
|
||||
嵌入预览完全相同的清理后文档,不额外放宽 Sandbox 或 CSP。切换回复时,源码面板与全屏
|
||||
预览按当前 source 派生开合状态,不使用会引发级联渲染的重置 effect。
|
||||
|
||||
全屏 iframe 提供 `tabIndex=0`,共享焦点候选包含 iframe。关闭按钮的正向 Tab 显式进入
|
||||
预览,支持没有链接的长文;iframe 后的焦点守卫将原生 Tab 返回到后续 Modal 控件或关闭
|
||||
按钮。守卫本身不作为焦点循环的首尾,通知关闭按钮仍参与循环。
|
||||
|
||||
iframe 内的 Escape 不会冒泡到父文档。`registerWindowIpcHandlers` 只在主窗口直接子
|
||||
`about:srcdoc` frame 获得焦点且收到 Escape keyDown 时,向主 Renderer 发送
|
||||
`window:preview-escape`。Preload 暴露无参数订阅 `app.onPreviewEscape`;全屏组件仅在
|
||||
自己的 iframe 当前聚焦且所属 Modal 未被 inert 隔离时关闭。组件卸载移除订阅,窗口 IPC
|
||||
释放时移除输入监听。此路径不执行预览脚本、不授予同源权限,也不暴露原始键盘事件或
|
||||
Electron 对象;iframe 的 Sandbox/CSP 保持原值。
|
||||
|
||||
## 验证范围
|
||||
|
||||
- 应用设置默认值、关闭持久化和版本 10 迁移。
|
||||
@@ -65,4 +76,5 @@ iframe 无法按内容自适应高度,因为 `sandbox=""` 不含 `allow-same-o
|
||||
- 源码按钮的 `aria-expanded` 切换,以及全屏预览的初始焦点、背景 inert、Escape 关闭和
|
||||
焦点恢复。
|
||||
- 主 Agent、子 Agent、用户、推理和流式状态边界。
|
||||
- 真实 Electron 中带链接与纯正文 iframe 的进入、正反向 Tab 返回和内部 Escape;通过生产 Main/Preload 事件订阅完成关闭。
|
||||
- 从设置 Switch 到当前会话重新渲染的应用级集成路径。
|
||||
|
||||
@@ -81,6 +81,49 @@
|
||||
|
||||
## 已验证证据
|
||||
|
||||
### 2026-09-27 MCP 编辑器遮挡修复
|
||||
|
||||
真实 Electron App 经“设置 → 能力与工具 → MCP → 自定义 MCP → 添加 Server”复现。
|
||||
修复前编辑器层级为 `70`、设置为 `130`,输入框中心命中设置页签容器;名称输入框虽已
|
||||
获得焦点,父设置仍为 `inert=false`。添加和编辑现接入共享 Modal 层级与背景隔离,
|
||||
遮罩关闭保留触发按钮焦点。没有修改 Runtime、Agent 或 MCP 传输实现。
|
||||
|
||||
`overlay-layering.electron.test.ts` 新增真实 App 用例,复用生产 preload、IPC、
|
||||
`CapabilityService`、设置存储与 `BrowserService`。已通过的场景:
|
||||
|
||||
| 场景 | 验证结果 |
|
||||
| --- | --- |
|
||||
| 无浏览器,浅色 `1280 × 900`、深色 `960 × 420` | 添加/编辑鼠标命中、文字输入、父设置隔离、Tab/Shift+Tab 循环通过 |
|
||||
| 右侧原生浏览器打开,浅色 `1280 × 900`、深色 `1280 × 420` | 设置及 MCP 期间原生视图隐藏;设置关闭后恢复相同 webContents ID、URL 和页面内标记,无重建或刷新 |
|
||||
| 关闭与焦点 | X、取消、Escape、遮罩、保存成功返回原触发按钮;关闭子层保留设置,关闭设置返回其入口 |
|
||||
| 持久化 | 四次 UI 保存经生产 IPC 写入临时配置,新建 `CapabilityService` 重读四条记录;编辑重开回显名称 |
|
||||
|
||||
原有 overlay Electron 用例也通过,继续覆盖解析菜单、二级结果、通知、应用中心、本机
|
||||
推理监控和原生 `dialog`。回归禁用 Windows 原生窗口遮挡节流,避免其他桌面窗口暂停
|
||||
测试的帧等待;未改变产品窗口选项。浏览器页面使用本地 HTTP 服务;MCP 测试配置保存为
|
||||
停用状态,不启动外部 MCP 命令。真实模型调用 **0 次**。
|
||||
|
||||
证据范围为 Windows x64 开发态 Electron。无关启动服务使用 harness 替身,未配置的
|
||||
向量模型与 Runtime 原生能力服务会返回不可用;未验收这些服务、外部 MCP 连接、远程
|
||||
Agent 或其他操作系统。短窗口从已打开设置调整尺寸;宽度跨越工作栏自动收起阈值的路径
|
||||
不作为浏览器保持打开的验收场景。
|
||||
|
||||
最终 focused 集合为 6 文件、215 项通过;`npm run typecheck`、`npm run lint` 和
|
||||
`git diff --check` 通过。本轮未运行全仓 `npm test` 或打包。验证命令:
|
||||
|
||||
```text
|
||||
npx vitest run tests/overlay-layering.electron.test.ts src/renderer/src/McpSettingsSection.test.tsx src/renderer/src/SettingsPanel.test.tsx src/renderer/src/FloatingPortal.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx src/renderer/src/RightAssistantSidebar.resize.test.tsx
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
git diff --check
|
||||
```
|
||||
|
||||
调试期间的失败记录:旧代码在真实鼠标命中断言失败;接入共享焦点后补修遮罩关闭的默认
|
||||
焦点转移。harness 的帧等待曾受 Windows 窗口遮挡节流影响,浏览器导航曾在创建或输入
|
||||
状态提交前触发;分别关闭测试进程的遮挡节流,并等待可用控件与实际页面加载后验证。
|
||||
这些失败未计为产品验收通过。中文文档扫描无阻断项;本节的并列项是实测关闭入口和覆盖
|
||||
组件清单,保留以便核对。
|
||||
|
||||
### 2026-09-03 `v0.12.0` 失败标签恢复
|
||||
|
||||
- 不可变标签工作流 `33704483505` 的 Windows x64/ARM64 与 macOS x64/ARM64 托管 Python
|
||||
|
||||
@@ -279,6 +279,14 @@ stdio MCP:
|
||||
Tab、不渲染占位面板。
|
||||
- 页签直接包装层使用 `flex: 0 0 auto`,并由 CSS 回归测试保证在滚动设置布局中不可收缩。
|
||||
|
||||
`McpSettingsSection` 的添加与编辑共用 body Portal,遮罩使用 `--z-dialog`。
|
||||
打开前记录并聚焦触发按钮,再由 `activateModalFocus` 隔离父设置、聚焦名称并在关闭时
|
||||
恢复原隔离状态与焦点;键盘事件在子层停止传播。遮罩的 `mousedown` 关闭分支阻止默认
|
||||
焦点转移,避免恢复到触发按钮后又失焦。原生浏览器继续复用
|
||||
`browser-viewport-occlusion.ts`,无需 MCP 专用隐藏条件。
|
||||
真实 App 回归位于 `tests/overlay-layering.electron.test.ts`,使用生产 preload、IPC、
|
||||
配置存储及 `BrowserService`,验证添加、持久化、编辑、父层隔离与原生浏览器恢复。
|
||||
|
||||
### 11.2 工具环境状态与 IPC
|
||||
|
||||
Renderer 接收:
|
||||
|
||||
@@ -113,6 +113,12 @@ MCP 面板
|
||||
- MCP 原有四个内层页签继续保留,外层和内层使用不同的 `aria-label` 与 `idPrefix`。
|
||||
- 窄屏时外层页签保持单行并允许水平滚动,不折成多行,不替换为下拉框。
|
||||
|
||||
“MCP / 自定义 MCP”的添加和编辑共用设置上方的子 Modal。打开后聚焦名称输入框,
|
||||
父设置与工作区保持不可交互;Tab 和 Shift+Tab 在编辑器内循环。X、取消、Escape、
|
||||
遮罩及保存成功均返回原添加或编辑按钮,Escape 只关闭编辑器。保存期间禁止关闭,
|
||||
失败保留输入。右侧浏览器沿用应用级 Modal 的视图释放规则,编辑器关闭后仍由父设置
|
||||
保持隔离,设置关闭后恢复网页。
|
||||
|
||||
## 4. 工具下载源
|
||||
|
||||
使用原生 Radio Group:
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# 模型连接请求定制进度
|
||||
|
||||
## 2026-09-27:窄容器协议显示
|
||||
|
||||
连接管理布局改用命名容器查询,不超过 `640px` 时列表和表单上下排列;移除原先仅在
|
||||
窗口不超过 `720px` 时切换的规则。LLM、向量连接及角色编辑共用同一布局样式。
|
||||
Windows Electron 验证覆盖 `680/720/721/740/960/1180px` 窗宽、短窗口、中英文及浅深
|
||||
主题;另在 `1180px` 窗口中单独缩窄设置面板,确认布局由实际容器宽度决定。
|
||||
协议文字完整、表单无横向溢出,原生 Tab 与方向键可选择并还原协议。没有保存配置或发送
|
||||
模型请求。验证命令、截图说明和未测范围见
|
||||
[窄容器布局修复记录](../../quality/responsive-controls-review-2026-09-27.md)。
|
||||
|
||||
## 2026-09-20:模型设置可用性修复
|
||||
|
||||
- 模型接口 URL 保存失败时按连接名称显示错误,URL 字段同步提供 `aria-invalid` 和就地
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
`aria-invalid` 并关联就地错误,避免只显示无法定位的“Invalid URL”。
|
||||
- LLM 模型连接的分类标题和模型类型分段页签在内容滚动时共同粘附在内容区顶部;左侧连接
|
||||
列表仍可独立滚动。
|
||||
- 连接列表和编辑表单按自身容器宽度切换左右或上下排列,断点及列表滚动上限遵循
|
||||
[设置中心布局规则](../../../UI-DESIGN.md#138-设置中心)。窄窗口中收起的接口协议选择框
|
||||
保留完整中英文当前值,不能依赖展开选项才能辨认协议。
|
||||
- 每个已保存或正在编辑的 LLM 连接提供“复制连接”。复制会生成新的连接名称和 ID,保留
|
||||
地址、模型、协议、请求定制、认证方式及当前草稿 API Key。已保存的 API Key 通过 Main
|
||||
进程的加密凭据复制路径保存,不回传到 Renderer;原连接和默认连接不改变。
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# 浮层审查修复记录
|
||||
|
||||
日期:2026-09-27。本阶段处理全局样式审查中的五项浮层问题。既有 MCP 子 Modal 修复和
|
||||
[共享控件阶段](shared-controls-review-2026-09-27.md)保持原实现,菜单危险色覆盖未重复修改。
|
||||
|
||||
## 修复与验证
|
||||
|
||||
| 入口与问题 | 实现 | 实际验证 |
|
||||
| --- | --- | --- |
|
||||
| 附件解析结果打开大图,图片被父遮罩盖住 | 图片遮罩复用 `--z-dialog`;解析正文及图片回调保持稳定,关闭后原触发节点仍在 | 完整 App、浅深主题;读取窗口合成截图中大图中心红色像素,检查父层 inert,Escape 返回图片入口,再关闭解析层 |
|
||||
| 同行帮助被原生浏览器盖住 | 共享 occlusion selector 增加 tooltip,内容矩形沿用相交检测及 ResizeObserver | 运行记录页真实 InlineHelp;1600px 窗口与工作栏最小宽度下不相交,1000px 窗口重开工作栏并调至最大宽度后相交;检查真实 WebContentsView 隐藏/恢复,实例 ID 与页面内标记不变 |
|
||||
| HTML 全屏无法键盘进入 iframe | iframe 加入共享焦点候选,显式进入及返回守卫;内部 Escape 使用受限窗口通知 | 完整 App、生产 Main/Preload;带链接预览正反向进入/返回及内部 Escape,纯正文进入、PageDown 和内部 Escape;保留空 sandbox 与禁脚本 CSP |
|
||||
| 窄侧栏项目 Modal 的 Escape 同时关闭两层 | ProjectSwitcher 接入 `activateModalFocus`,忽略已处理或被隔离弹层的按键 | 760px 窗口侧栏中新建项目,一次 Escape 仅关闭项目且焦点回到项目入口,第二次才关闭侧栏 |
|
||||
| 知识引用遮罩仍是原生拖动区域 | 加入共享 no-drag;自动发现测试按 fixed/inset 扫描,覆盖 `-dialog` 类名 | 完整 App 点击知识引用;Windows 原生命中返回 HTCLIENT,临时清除 no-drag 的对照返回 HTCAPTION |
|
||||
|
||||
解析大图路径另暴露了焦点恢复问题:ReactMarkdown 的图片组件在 App Context 更新时被
|
||||
重建。稳定 `SectionContent` 与图片页签回调后,返回焦点断言通过,没有改为聚焦无关按钮。
|
||||
|
||||
HTML 键盘桥只转发主窗口直接 srcdoc 子 frame 的 Escape keyDown。窗口级单测另检查
|
||||
主 frame、普通网页、间接子 frame、Tab、keyUp 不转发,以及监听释放后不再发送。
|
||||
它不为预览授予 scripts、same-origin、forms 或 navigation 权限。技术接线由
|
||||
[HTML 渲染技术设计](../features/conversation-html-rendering/technical-design.md#ui-与无障碍)维护。
|
||||
|
||||
## 测试组织
|
||||
|
||||
真实路径位于 [overlay-paths-main.ts](../../tests/support/overlay-paths-main.ts),由
|
||||
[overlay-layering.electron.test.ts](../../tests/overlay-layering.electron.test.ts)启动。App、
|
||||
preload、窗口事件 IPC、BrowserService 及 viewport 调用使用生产实现;解析结果及图片是
|
||||
受控数据,其他无关启动服务使用 fixture。测试使用独立 profile/SQLite 和本地 HTTP 网页,
|
||||
不启动模型,模型请求尝试为 0。
|
||||
|
||||
设置 `GB_OVERLAY_PATHS_ARTIFACTS` 可保留浅深大图、两种帮助布局的 PNG 与结果 JSON。
|
||||
原生命中在 Windows 使用 WM_NCHITTEST;其他平台只执行其余行为和 computed no-drag 检查。
|
||||
测试启动器退出后删除隔离 profile 和构建目录。
|
||||
|
||||
此前漏测的原因分别是:只检查 Modal DOM 存在、原生遮挡用例未枚举 tooltip、HTML 用例
|
||||
未用真实 Tab 穿越 frame、项目和侧栏单独测试,以及遮罩自动发现依赖类名后缀。本次回归
|
||||
对应加入组合路径与原生断言。
|
||||
|
||||
## 验证边界
|
||||
|
||||
本机验证为 Windows、Electron 43.2.0,DPR 1。未把解析 fixture 当作真实 OCR 验收;未执行
|
||||
macOS/Linux 原生输入、全页面缩放矩阵;本阶段之后的全仓结果见
|
||||
[最终验证汇总](responsive-controls-review-2026-09-27.md#全部样式修复最终验证)。
|
||||
|
||||
已执行的定向回归:
|
||||
|
||||
- Renderer 共享控件、浮层、浏览器租约、Markdown、ProjectSwitcher、DocumentResultPreview 及窗口事件:9 文件、176 项通过。
|
||||
- Main IPC、窗口事件、Preload sandbox 及画布 IPC:4 文件、197 项通过,1 项原有跳过。旧 WebContents fixture 补充了事件订阅/移除方法,没有给生产代码添加 mock 专用兼容分支。
|
||||
- App Modal 与侧栏筛选:分别 4 项和 15 项通过,其余由名称筛选排除。
|
||||
- `tests/overlay-layering.electron.test.ts`:3 项通过,包含原有菜单/通知、MCP 完整 App 以及本阶段五条路径。MCP 保留四个浅深/短窗口/浏览器场景及生产保存重读断言。
|
||||
- `tests/shared-controls.electron.test.ts`、`tests/inline-help.electron.test.ts`、`tests/magic-notes-capture.electron.test.ts`:通过,保留前一阶段 338 组 computed style 与危险按钮回归。
|
||||
- 最终调整项目初始焦点与 iframe 事件归属断言后,`MarkdownRenderer.test.tsx`、`ProjectSwitcher.test.tsx`、`window-ipc.test.ts` 共 53 项通过;整个 overlay Electron 文件再次 3 项通过。
|
||||
- `npm run typecheck`、`npm run lint`、`git diff --check`:通过。新增质量记录中文审校无阻断项;键盘事件枚举保留为技术测试条件。
|
||||
|
||||
最终测试已通过 `GB_OVERLAY_PATHS_ARTIFACTS` 导出 PNG 与结果 JSON,并人工查看浅深图片
|
||||
Modal 和帮助相交截图。浏览器可见性以 Main 中实际 WebContentsView 状态为准,Renderer
|
||||
截图不作为原生视图已隐藏的替代证据。
|
||||
|
||||
扩大验证曾发现窗口先销毁再执行 IPC dispose 的清理错误,已改为使用注册时捕获的
|
||||
WebContents 引用,单测及 MCP Electron 复跑通过。测试脚本也修正了异步窗口尺寸/工作栏
|
||||
展开的等待条件和旧 fixture 接口,未放宽像素、焦点、命中或浏览器可见性断言。
|
||||
@@ -57,11 +57,14 @@ AI 列 280。测试同步原生输入与实际状态后独立复跑通过,保
|
||||
[UI 设计系统](../../UI-DESIGN.md)。
|
||||
|
||||
**防复发**:`WorkspacePrimitives.test.tsx` 的
|
||||
"releases the native drag region for every full-window overlay" 从 Renderer 顶层全部 CSS 文件自动发现
|
||||
全部 `position: fixed` 遮罩并逐个校验,新增遗漏会直接失败。
|
||||
"releases the native drag region for every full-window overlay" 递归扫描 Renderer CSS,按
|
||||
`position: fixed` 与 `inset` 声明发现遮罩,排除不接收指针的透明宿主,并校验共享 no-drag。
|
||||
|
||||
**历史**:`e9679fe`、`ca4a58c` 各修了一部分被人工点到的弹窗,同一批改动又新增了两个未覆盖
|
||||
的遮罩;后续复查改为共享规则加自动发现测试。
|
||||
2026-09-27 复查发现自动发现仍依赖 `backdrop/modal` 后缀,漏掉知识引用的
|
||||
`.knowledge-citation-dialog`。补入共享规则并移除后缀限制;真实 App 的 Windows
|
||||
`WM_NCHITTEST` 回归验证修复后为 `HTCLIENT`,临时清除该规则的对照为 `HTCAPTION`。
|
||||
|
||||
## 共享控件样式依赖页面祖先
|
||||
|
||||
@@ -80,6 +83,15 @@ AI 列 280。测试同步原生输入与实际状态后独立复跑通过,保
|
||||
|
||||
**历史**:2026-09-27 同次检查确认草稿确认及上述四处调用均受同一作用域错误影响。
|
||||
|
||||
同日后续全局审查发现,控件已有全局定义仍会被容器与状态规则覆盖:深色通用输入规则替换
|
||||
控件边框,普通图标 hover 覆盖危险图标,菜单按钮规则覆盖危险确认;`.field input` 还将
|
||||
Radio 与 Switch 当成文本字段。共享规则现已排除二元控件,恢复全局焦点轮廓,降低菜单
|
||||
默认样式特异性,并移除深色控件兜底覆盖。Continue 独立字段通过 `.field-control` 复用
|
||||
输入规则。`shared-controls.electron.test.ts` 检查浅深主题、设置容器、body Portal、菜单
|
||||
组合、默认/悬停/禁用/选中态及原生 Tab 焦点,并渲染实际 Continue 组件。令牌测试同时检查
|
||||
主按钮 hover 白字与控件背景的对比度。[审查修复记录](shared-controls-review-2026-09-27.md)
|
||||
保留本次范围、验证结果和未测项。
|
||||
|
||||
## 网页浮层遗漏原生浏览器视图
|
||||
|
||||
**症状**:知识库实例、项目设置等 Modal 的右侧被浏览器网页覆盖,通知或菜单也可能
|
||||
@@ -97,6 +109,9 @@ AI 列 280。测试同步原生输入与实际状态后独立复跑通过,保
|
||||
|
||||
**历史**:先前浏览器多实例修正只覆盖了终端关闭确认;2026-09-13 用户在知识库实例
|
||||
Modal 再次复现,同一检查确认其他应用级 Modal 均缺少处理。
|
||||
2026-09-27 同行帮助的 tooltip 仍未进入选择器。现已纳入同一相交判定和尺寸观察;
|
||||
Electron 回归从运行记录页打开真实 InlineHelp,并通过工作栏分隔条形成相交与非相交布局,
|
||||
检查实际 WebContentsView 可见性及恢复后的页面标记,确认网页没有重建或刷新。
|
||||
|
||||
## Modal 内的菜单与通知被遮挡或隔离
|
||||
|
||||
@@ -117,6 +132,18 @@ Modal,兼顾 top layer 绘制、辅助技术的模态归属及焦点循环;
|
||||
**历史**:2026-09-19 同次检查确认解析测试菜单和应用级通知两处挂载机制错误,后者影响
|
||||
多个全局 Modal;统一宿主后补完整 App 的真实保存通知与 TXT 解析复验。
|
||||
|
||||
2026-09-27 在真实 App 的“设置 → 能力与工具 → MCP → 自定义 MCP → 添加 Server”
|
||||
再次复现子层遮挡:MCP body Portal 沿用 `z-index: 70`,低于设置的 `130`,输入框中心
|
||||
实际命中父设置页签。编辑器仅手动聚焦,父设置未设为 `inert`。添加与编辑统一接入
|
||||
`--z-dialog` 和 `activateModalFocus`;遮罩关闭阻止默认鼠标焦点转移,Escape 停在子层。
|
||||
新增 Electron 回归检查真实鼠标命中、输入、Tab 循环、各关闭入口、生产 IPC 保存及重读,
|
||||
并检查浏览器在父子 Modal 期间隐藏、最后恢复同一未刷新的网页。子 Modal 应使用共享模态
|
||||
机制;上述 `FloatingPortal` 仍用于非模态菜单与通知。
|
||||
同次审查确认解析结果打开图片时也沿用低于父层的 `z-index: 80`,现复用 `--z-dialog`。
|
||||
解析正文使用稳定的组件与图片回调,避免 App 打开大图时重建触发节点而丢失返回焦点。
|
||||
窄侧栏打开项目 Modal 也已接入共享背景隔离,避免一次 Escape 同时关闭两层。
|
||||
本阶段实现、键盘边界和 Electron 证据见[浮层审查修复记录](overlay-review-2026-09-27.md)。
|
||||
|
||||
## Flex 滚动内容压缩页签和分段控件
|
||||
|
||||
**症状**:知识库来源选择被长参数表单压成窄缝,标签和按钮文字被裁掉。
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# 窄容器布局审查修复记录
|
||||
|
||||
日期:2026-09-27。范围为全局样式审查第三阶段的工作栏添加入口和模型设置布局。
|
||||
此前 MCP、共享控件、浮层和深色主按钮对比度修复均保留。
|
||||
|
||||
## 修复
|
||||
|
||||
工作栏原先将“+”放在页签滚动区内,`300px` 栏宽下默认四个页签就会将按钮卷出可见区。
|
||||
现在添加按钮独立占用行末宽度,页签及两端滚动箭头放在剩余区域内;溢出测量也读取该区域。
|
||||
没有改动应用目录、实例策略、持久化或终端生命周期。
|
||||
|
||||
模型设置原先按整窗 `720px` 断点切换单列。`721px` 窗口仍保留分类、连接列表和表单三列,
|
||||
协议选择框宽度只有约 `136px`。现在 `.model-connection-manager` 自身作为命名容器,
|
||||
可用宽度不超过 `640px` 时让列表及详情各占整行,列表保留 `180px` 的内部滚动上限。
|
||||
更宽时沿用原双栏。LLM、向量连接和角色编辑共用这条规则,没有增加页面专属断点。
|
||||
|
||||
产品规则见 [UI-DESIGN.md](../../UI-DESIGN.md)、
|
||||
[工作栏页签 PRD](../features/assistant-workbar/terminal-tabs-prd.md#71-tab-行)和
|
||||
[模型连接 UI 设计](../features/model-connections/ui-design.md)。工作栏两份 PRD 中“+ 随页签
|
||||
滚动”的旧说明已纠正。
|
||||
|
||||
## Electron 证据
|
||||
|
||||
[workbar-settings-layout.electron.test.ts](../../tests/workbar-settings-layout.electron.test.ts)
|
||||
在隔离 profile 中加载当前生产 `WorkbarShell`、`SettingsPanel`、共享样式及字体。
|
||||
测试使用受控 IPC 配置数据,不访问模型服务。Windows Electron 共记录 32 组结果,包含:
|
||||
|
||||
- 中文与英文、浅色与深色主题。
|
||||
- `300px` 工作栏的默认四个页签、16 个含长标题的页签,以及从目录新建第 17 个实例。
|
||||
检查“+”位于可见栏内且中心点可命中,原生鼠标打开目录、创建浏览器实例;Escape 返回
|
||||
添加按钮。滚动箭头不改变活动页签,Home/End 激活并显示首末页签。
|
||||
- 默认页签下将工作栏扩到 `900px` 再缩回 `300px`,检查溢出箭头退出及恢复。
|
||||
- 设置内容区窗口为 `680×560`、`720×560`、`721×560`、`740×560`、`960×560`、
|
||||
`1180×760`。另在 `1180×560` 窗口中将设置面板限定为 `740px`,检查同一窗口内的
|
||||
容器响应,而非仅检查媒体断点。
|
||||
- 长连接名称下,协议当前值的真实字体测量宽度小于控件扣除内边距及箭头后的可用宽度。
|
||||
设置内容区、连接管理区及详情无横向溢出,协议框可命中;原生 Tab 进入后,方向键改变
|
||||
协议,Home 还原。`721px` 窗宽下控件 clientWidth 为 `370px`,英文协议文字约 `233px`。
|
||||
|
||||
通过 `GB_LAYOUT_ARTIFACTS` 可输出截图和 `result.json`。已查看英文深色 `721px` 设置、
|
||||
英文宽窗口窄容器及中英文工作栏截图。测试退出后删除专用 profile 与 Vite 缓存。
|
||||
|
||||
## 验证命令
|
||||
|
||||
```text
|
||||
npm test -- src/renderer/src/WorkbarShell.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx src/renderer/src/SettingsPanel.test.tsx src/renderer/src/EmbeddingSettingsSection.test.tsx src/renderer/src/RolePromptSettingsSection.test.tsx src/renderer/src/RightAssistantSidebar.resize.test.tsx tests/workbar-settings-layout.electron.test.ts tests/shared-controls.electron.test.ts
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
```
|
||||
|
||||
Focused 回归 8 文件、238 项通过;typecheck 和 lint 通过。前阶段共享控件 Electron
|
||||
回归的 338 组状态测量仍通过。模型调用 0 次,未提交代码。
|
||||
补强页签焦点与选中态同步断言后,新增 Electron 回归连续三次完整通过,每次 32 组结果。
|
||||
|
||||
新驱动调试期间修正了目录按钮选择器、环境变量类型声明和 Electron 方向键名称。
|
||||
原生 select 弹出菜单的关闭时序曾使驱动超时,最终使用原生 Tab 与方向键验证字段操作,
|
||||
并保留命中、文字宽度和溢出断言;没有放宽产品断言或增加生产代码补丁。
|
||||
后续联合运行曾停在调整窗口后的动画帧等待。驱动补充了超时脚本记录,并在测试进程中关闭
|
||||
Windows 原生遮挡节流,等待窗口焦点和尺寸后再同步绘制及发送鼠标输入。该设置不进入产品。
|
||||
最终连续三次回归通过;超时记录不足以单独证明此前每次停顿的唯一原因。
|
||||
|
||||
## 限制
|
||||
|
||||
这是当前生产组件的真实 Electron 布局与输入回归,IPC 数据使用 fixture;不证明完整 App
|
||||
的配置保存或模型调用链路。未覆盖原生 select 弹出菜单的鼠标选项选择、macOS/Linux、
|
||||
系统缩放、200% 字号、原生窗口遮挡节流和全部设置类别。向量连接和角色编辑运行了组件回归,但本次 Electron
|
||||
矩阵仅验证 LLM 连接表单。本阶段定向验证未运行全仓测试或生产构建;后续全仓结果见下节。
|
||||
|
||||
## 全部样式修复最终验证
|
||||
|
||||
2026-09-27 在 Windows 开发环境完成最终验证。范围为共享控件 8 项、浮层 5 项、
|
||||
窄容器 2 项,共 15 项样式问题,以及 MCP 子 Modal 修复。先读取根目录 `AGENTS.md`,
|
||||
检查未提交源码和文档 diff;原有 37 个已跟踪修改文件、12 个未跟踪文件均保留,暂存区为空。
|
||||
本次新增的生产修正仅为 `ProjectSwitcher.tsx` 的初始字段选择器一行,未改测试断言。
|
||||
|
||||
| 命令与执行范围 | 实际结果 |
|
||||
| --- | --- |
|
||||
| `npm test`,当前工作树,全仓且无 bail | 463 文件:450 通过、2 失败、11 跳过;5395 项:5309 通过、3 失败、83 跳过。耗时 696.22 秒 |
|
||||
| `npm test -- src/renderer/src/HeartbeatCenter.test.tsx`,隔离 HEAD `11facf0` | 1 文件失败;40 项通过、2 项失败,耗时 4.86 秒,与当前工作树同一行、同一中英文断言失败 |
|
||||
| `npm test -- src/renderer/src/App.test.tsx src/renderer/src/ProjectSwitcher.test.tsx tests/overlay-layering.electron.test.ts`,焦点修复后 | 3 文件、331 项通过,耗时 80.57 秒 |
|
||||
| `npm run typecheck` | 全仓测试后及焦点修复后均通过,覆盖 node、agent、web 三份 TypeScript 配置 |
|
||||
| `npm run lint` | 全仓测试后及焦点修复后均通过 |
|
||||
| `git diff --check` | 通过;Git 提示已有 LF 将转换为 CRLF,没有空白错误 |
|
||||
|
||||
完整 `npm test` 只启动一次,超时设为 1,200,000 毫秒,等待正常结束,没有 bail、
|
||||
中止或重复启动。修复后只复跑相关集合,未把定向通过改写成全仓通过。
|
||||
|
||||
### 失败归因与处理
|
||||
|
||||
`App.test.tsx:8921` 是本次回归。项目 Modal 新接入的初始焦点逻辑只查询 input,
|
||||
覆盖了通道项目说明 textarea 的原有自动聚焦,实际焦点落到后面的默认工作目录。
|
||||
确认组件结构和失败输出后,选择器改为按 DOM 顺序查询未禁用的 input、textarea、select,
|
||||
无字段时仍退回按钮。原有说明字段焦点断言保持不变,App 全文件及项目切换组件、真实
|
||||
Electron 浮层回归共 331 项通过,包含窄侧栏 Escape 隔离与 MCP 保存重读路径。
|
||||
|
||||
`HeartbeatCenter.test.tsx:213` 的中文、英文两项失败为既有问题。测试要求全页只有
|
||||
1 个 tablist,并要求内容面板内没有 tablist;但图谱有事件数据时,
|
||||
`SupervisorWorkspace.tsx:677` 已渲染事件、实体、关系的内层 `PageTabs`,实际总数为 2。
|
||||
未带本轮改动的 HEAD `11facf0` 使用相同依赖独立执行该文件,也得到 40 通过、2 失败。
|
||||
本次保留组件与断言,后续需按图谱导航设计确认测试范围;没有将预期数量直接改为 2。
|
||||
|
||||
### Electron 结果与未测范围
|
||||
|
||||
全仓运行中,共享控件输出 338 组 computed style 测量,窄容器输出 32 组布局和输入结果。
|
||||
overlay 文件 3 项通过,包含 MCP 四种主题/窗口/浏览器场景、生产 IPC 保存与重新读取,
|
||||
以及大图、iframe、项目 Modal、tooltip、知识引用五条路径;焦点修正后该文件再次通过。
|
||||
这些样式与 MCP 驱动的模型请求尝试为 0。全仓另有隔离的 403 fixture 输出,每种凭据来源
|
||||
各记录 1 次请求;这不作为真实模型生成证据,也不据此声称全仓外部调用总数为 0。
|
||||
|
||||
剩余失败为上述两项 HeartbeatCenter 既有断言。全仓跳过的 11 文件、83 项仍未形成通过证据。
|
||||
本次没有运行生产构建、打包、macOS/Linux 验证、远程 Agent 实机或外部 MCP 连接;
|
||||
未覆盖强制颜色、完整系统缩放/200% 字号矩阵、原生 select 弹出菜单的鼠标选项选择,
|
||||
也未将组件 fixture 当作全部 App 业务入口验收。部分 Electron 驱动关闭了 Windows
|
||||
原生遮挡节流,不能据此宣称产品在原生遮挡状态下也已覆盖。没有 commit 或 push。
|
||||
@@ -0,0 +1,55 @@
|
||||
# 共享控件审查修复记录
|
||||
|
||||
日期:2026-09-27。范围为全局样式审查第一阶段,包含原审查六项、会话菜单危险按钮覆盖及
|
||||
深色主按钮 hover 对比度。原有 MCP 子 Modal 修复保留,本阶段没有改动其组件或业务逻辑。
|
||||
|
||||
## 修复范围
|
||||
|
||||
| 问题与触发位置 | 共享修复 | 验证 |
|
||||
| --- | --- | --- |
|
||||
| 深色设置输入框、次按钮边框被兜底规则覆盖 | 删除通用输入覆盖及次按钮边框覆盖,使用主题 `--border-control` | 设置容器和 body Portal 读取最终边框;输入边框与实际背景至少 3:1 |
|
||||
| `.field` 与浏览器地址框丢失焦点环;Radio 被拉高 | 文本字段规则排除 Checkbox/Radio,删除局部 outline 清除和未定义 `--focus-ring` 引用 | 原生 Tab 后轮廓为 2px 强调色;Switch 为 38×22px,Checkbox/Radio 为 15×15px |
|
||||
| 图标按钮、分段控件禁用后仍像可操作 | 共享禁用透明度和光标;普通图标 hover 排除禁用项 | 禁用时光标为 not-allowed,透明度降低,hover 不恢复可用颜色 |
|
||||
| Continue 删除图标丢失危险颜色 | 普通图标 hover 排除危险修饰类,移除深色普通图标覆盖 | 组合类及实际 Continue 删除按钮在两种主题下保留危险前景和悬停背景 |
|
||||
| Continue Rule/Prompt 输入回退原生样式 | 五个独立文本字段使用 `.field-control`,复用原表单规则 | 实际组件字段使用共享边框、字体、内边距和至少 38px 高度,并保留键盘焦点 |
|
||||
| 默认 PageTabs hover 覆盖 active | hover 只作用于未选中项 | 当前项悬停前后背景及文字颜色不变 |
|
||||
| 会话菜单 button 覆盖 danger-button | 会话与工作区文件菜单的通用规则降低特异性,删除多余文件菜单危险补丁 | 实际 `DestructiveConfirmActions` 从入口进入确认后保留危险实心背景、反白文字;禁用危险图标不高亮 |
|
||||
| 深色主按钮 hover 白字对比度约 4.31:1 | `--accent-solid-hover` 调整为 `#1a77c5` | 白字对比度 4.68:1;令牌及真实按钮默认/hover 均检查至少 4.5:1 |
|
||||
|
||||
回归另发现浅色 `--border-control` 在 `--surface-subtle` 上只有约 2.90:1。
|
||||
共享边框令牌由 `#7f95aa` 调整为 `#748a9f`,对白底、subtle、muted 背景分别为
|
||||
3.57:1、3.35:1、3.02:1。没有按页面另设边框颜色。
|
||||
|
||||
实现主要位于 [styles.css](../../src/renderer/src/styles.css);Continue 接线位于
|
||||
[RuntimeCustomizationSection.tsx](../../src/renderer/src/RuntimeCustomizationSection.tsx)。
|
||||
共享规范由 [UI-DESIGN.md](../../UI-DESIGN.md) 维护。
|
||||
|
||||
## 回归证据
|
||||
|
||||
[shared-controls.electron.test.ts](../../tests/shared-controls.electron.test.ts) 使用当前源码组件、
|
||||
共享样式和主题函数。Continue 数据使用受控 IPC fixture,菜单使用实际
|
||||
`DestructiveConfirmActions`。测试在真实 Electron/Chromium 中读取 computed style,
|
||||
覆盖浅深主题、设置容器和真实 body Portal,共记录 338 组状态测量,包含 PageTabs 的
|
||||
default 与 segmented 变体。焦点通过原生 Tab
|
||||
进入;hover 通过 CDP 强制伪状态检查,不作为原生鼠标命中证据。模型调用为 0。
|
||||
|
||||
本机环境为 Windows、Electron 43.2.0、Chromium 150,内容区 1280×800,DPR 1。
|
||||
已打开审阅浅深 Continue 字段及深色 Portal 的原尺寸 PNG;共享输入边框、删除图标和
|
||||
焦点轮廓符合计算值。截图与完整 computed JSON 可通过 `GB_SHARED_CONTROLS_ARTIFACTS`
|
||||
指定目录输出,测试专用 profile 与 Vite 缓存在退出后删除。
|
||||
|
||||
已执行:
|
||||
|
||||
- `npx vitest run tests/shared-controls.electron.test.ts tests/overlay-layering.electron.test.ts src/renderer/src/WorkspacePrimitives.test.tsx src/renderer/src/SettingsPanel.test.tsx src/renderer/src/WorkspaceFilesPanel.test.tsx`:最终 5 文件、181 项通过。
|
||||
- MCP 浮层回归的 4 个场景通过:浅深主题、短窗口、原生鼠标命中与焦点循环、生产 IPC 保存及重读;有浏览器的场景保持 Modal 期间隐藏、关闭后恢复同一未刷新的网页。模型请求尝试为 0。
|
||||
- `npm run typecheck` 通过;`npm run lint` 通过。
|
||||
|
||||
首轮新回归在对话框输入的浅色边框对比度断言失败,修正共享令牌后通过。测试启动器曾有
|
||||
环境变量对象类型错误,增加 `NodeJS.ProcessEnv` 标注后类型检查通过。未放宽视觉断言。
|
||||
|
||||
## 剩余边界
|
||||
|
||||
本阶段上述八类问题已修复。共享控件测试属于组件视觉层,不证明完整 App 的全部业务入口;
|
||||
MCP 原有集成回归独立验证其真实保存与浏览器隔离路径。本阶段未执行全仓测试、macOS/Linux、
|
||||
强制颜色、200% 缩放及全页面四档窗口矩阵。后续全部 15 项样式修复与 MCP 的
|
||||
[最终验证汇总](responsive-controls-review-2026-09-27.md#全部样式修复最终验证)记录全仓结果及剩余失败。
|
||||
Reference in New Issue
Block a user