From 831303fa46920fe0850e3b5c276e7adc6c37ac9e Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Mon, 30 Mar 2026 16:47:22 +0800 Subject: [PATCH] refactor: complete shared ui cleanup baseline --- ...-settings-assistant-ui-component-matrix.md | 522 ++---------------- ...-focus-panel-dedupe-implementation-plan.md | 156 +----- ...tings-section-shell-implementation-plan.md | 132 +---- lib/features/mobile/ios_mobile_shell.dart | 16 - lib/web/web_assistant_page_chrome.dart | 1 - lib/web/web_assistant_page_core.dart | 1 - lib/web/web_assistant_page_helpers.dart | 1 - lib/web/web_assistant_page_workspace.dart | 1 - lib/web/web_focus_panel.dart | 1 - ...ell_suite.dart => mobile_shell_suite.dart} | 0 ...shell_test.dart => mobile_shell_test.dart} | 2 +- 11 files changed, 101 insertions(+), 732 deletions(-) delete mode 100644 lib/features/mobile/ios_mobile_shell.dart delete mode 100644 lib/web/web_focus_panel.dart rename test/features/mobile/{ios_mobile_shell_suite.dart => mobile_shell_suite.dart} (100%) rename test/features/mobile/{ios_mobile_shell_test.dart => mobile_shell_test.dart} (60%) diff --git a/docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md b/docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md index da51e8b2..395c3061 100644 --- a/docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md +++ b/docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md @@ -1,494 +1,90 @@ -# XWorkmate 设置页与 Assistant 三栏 UI 组件梳理 +# XWorkmate UI 组件盘点与清理基线 ## 目标 -结合本次两张截图,对应梳理: +基于当前截图批次,收口以下主链路的 UI 组件归属与清理候选: -1. 截图 A:Assistant 三栏工作区中的“设置焦点卡片 + 会话区 + 右侧任务文件栏” -2. 截图 B:完整“设置”页 -3. 这些 UI 在 Desktop / Web / Mobile 三端的代码归属与复用关系 +1. Assistant 三栏工作区 +2. 设置页 +3. 账号页 +4. `SKILLS 目录授权` + +本文档只记录当前实际代码状态,不再保留已完成清理前的旧副本描述。 --- -## 截图归因 +## 在用的组件 -### 截图 A:Assistant 三栏工作区 - -这张图对应的是桌面端 Assistant 主工作区,不是完整设置页。 - -代码链路是: - -- `lib/app/app_shell_desktop.dart` - Desktop 壳层负责把当前路由切到 `WorkspaceDestination.assistant` -- `lib/app/workspace_page_registry.dart` - 把 Assistant 路由映射到 `AssistantPage` -- `lib/features/assistant/assistant_page_main.dart` - 负责三栏布局骨架: - - 左侧:`AssistantUnifiedSidePaneInternal` - - 中间:主会话工作区 - - 右侧:任务文件/预览栏 -- `lib/widgets/assistant_focus_panel_core.dart` - 左侧“关注入口”卡片容器 -- `lib/widgets/assistant_focus_panel_previews.dart` - 其中“设置”卡片内部内容来自 `SettingsFocusPreviewInternal` -- `lib/widgets/settings_focus_quick_actions.dart` - 语言切换、主题切换两个快捷按钮 -- `lib/features/assistant/assistant_page_state_closure.dart` - 中间消息区、输入区、右侧产物栏拼装逻辑 -- `lib/widgets/assistant_artifact_sidebar.dart` - 右侧“当前任务工作路径 / 全部文件 / 预览 / 暂无文件”侧栏 - -### 截图 B:完整设置页 - -这张图对应的是桌面端完整设置页。 - -代码链路是: - -- `lib/app/app_shell_desktop.dart` - 壳层负责把当前路由切到 `WorkspaceDestination.settings` -- `lib/app/workspace_page_registry.dart` - 把设置路由映射到 `SettingsPage` -- `lib/features/settings/settings_page_core.dart` - 整个设置页主容器,负责: - - Breadcrumb / 标题 / 搜索框 - - 顶部保存入口 - - Tab 区域 - - 各 section 内容装配 -- `lib/features/settings/settings_page_sections.dart` - 负责: - - `buildGlobalApplyBarInternal`:“设置提交流程 / 保存并生效” - - `buildGeneralInternal`:`Application`、`账号访问` 等卡片 -- `lib/features/settings/settings_page_widgets.dart` - 负责通用字段原子组件: - - `SwitchRowInternal` - - `EditableFieldInternal` - - `InfoRowInternal` -- `lib/widgets/section_tabs.dart` - “通用 / 工作区 / 集成 / 外观 / 诊断 / 关于” tab 条 -- `lib/widgets/top_bar.dart` - 页面顶部 breadcrumb、标题、副标题、搜索框区域 - ---- - -## UI 组件矩阵 - -| UI Name | code path | Desktop | Web | Mobile | +| 名称 | 路径 | Desktop | Web | Mobile | | --- | --- | --- | --- | --- | -| Desktop App Shell | `lib/app/app_shell_desktop.dart` | Yes | No | No | -| Web App Shell | `lib/app/app_shell_web.dart` | No | Yes | No | +| App Shell Desktop | `lib/app/app_shell_desktop.dart` | Yes | No | No | +| App Shell Web | `lib/app/app_shell_web.dart` | No | Yes | No | | Mobile Shell | `lib/features/mobile/mobile_shell_core.dart` | No | No | Yes | +| Mobile Workspace Launcher | `lib/features/mobile/mobile_shell_workspace.dart` | No | No | Yes | | Assistant Page | `lib/features/assistant/assistant_page_main.dart` | Yes | No | Yes | -| Assistant 主工作区拼装 `buildMainWorkspaceInternal` | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes | -| Assistant 右侧产物栏拼装 `buildWorkspaceWithArtifactsInternal` | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes | -| Assistant 统一左侧板 `AssistantUnifiedSidePaneInternal` | `lib/features/assistant/assistant_page_main.dart` | Yes | No | No | -| Assistant 关注入口面板 `AssistantFocusPanel` | `lib/widgets/assistant_focus_panel_core.dart` | Yes | No | No | -| 设置焦点预览 `SettingsFocusPreviewInternal` | `lib/widgets/assistant_focus_panel_previews.dart` | Yes | No | No | -| 设置快捷操作 `SettingsFocusQuickActions` | `lib/widgets/settings_focus_quick_actions.dart` | Yes | Yes | No | -| 任务文件侧栏 `AssistantArtifactSidebar` | `lib/widgets/assistant_artifact_sidebar.dart` | Yes | Yes | No | -| Desktop / Web 通用内容卡片壳 `DesktopWorkspaceScaffold` | `lib/widgets/desktop_workspace_scaffold.dart` | Yes | Yes | No | -| 完整设置页 `SettingsPage` | `lib/features/settings/settings_page_core.dart` | Yes | No | Yes | -| 设置页顶部栏 `TopBar` | `lib/widgets/top_bar.dart` | Yes | Yes | Yes | -| 设置提交流程条 `buildGlobalApplyBarInternal` | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes | -| 设置页通用卡片 `buildGeneralInternal` | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes | -| 设置表单原子 `SwitchRowInternal / EditableFieldInternal` | `lib/features/settings/settings_page_widgets.dart` | Yes | No | Yes | -| 设置页标签条 `SectionTabs` | `lib/widgets/section_tabs.dart` | Yes | Yes | Yes | -| Web Assistant Page | `lib/web/web_assistant_page_core.dart` | No | Yes | No | -| Web Assistant 顶部 chrome | `lib/web/web_assistant_page_chrome.dart` | No | Yes | No | -| Web Assistant 会话工作区 | `lib/web/web_assistant_page_workspace.dart` | No | Yes | No | -| Web 关注入口面板 `WebAssistantFocusPanel` | `lib/web/web_focus_panel_core.dart` | No | Yes | No | -| Web 设置页 `WebSettingsPage` | `lib/web/web_settings_page_core.dart` | No | Yes | No | -| Web 设置页 section 装配 | `lib/web/web_settings_page_sections.dart` | No | Yes | No | -| Mobile 工作区入口 `MobileWorkspaceLauncherInternal` | `lib/features/mobile/mobile_shell_workspace.dart` | No | No | Yes | +| Assistant 主工作区拼装 | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes | +| Assistant 左侧关注面板 | `lib/widgets/assistant_focus_panel_core.dart` | Yes | No | No | +| Assistant 设置预览 | `lib/widgets/assistant_focus_panel_previews.dart` | Yes | No | No | +| Assistant 设置快捷操作 | `lib/widgets/settings_focus_quick_actions.dart` | Yes | Yes | No | +| 右侧任务文件栏 | `lib/widgets/assistant_artifact_sidebar.dart` | Yes | Yes | No | +| Desktop / Web 通用壳层 | `lib/widgets/desktop_workspace_scaffold.dart` | Yes | Yes | No | +| Settings Page | `lib/features/settings/settings_page_core.dart` | Yes | No | Yes | +| Settings Page sections | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes | +| Settings Page widgets | `lib/features/settings/settings_page_widgets.dart` | Yes | No | Yes | +| Gateway settings | `lib/features/settings/settings_page_gateway.dart` | Yes | No | Yes | +| Gateway connection settings | `lib/features/settings/settings_page_gateway_connection.dart` | Yes | No | Yes | +| Web Settings Page | `lib/web/web_settings_page_core.dart` | No | Yes | No | +| Web Settings sections | `lib/web/web_settings_page_sections.dart` | No | Yes | No | +| Web Settings gateway | `lib/web/web_settings_page_gateway.dart` | No | Yes | No | +| Web Settings support | `lib/web/web_settings_page_support.dart` | No | Yes | No | +| Account Page | `lib/features/account/account_page.dart` | Yes | No | Yes | +| Section Tabs | `lib/widgets/section_tabs.dart` | Yes | Yes | Yes | +| Top Bar | `lib/widgets/top_bar.dart` | Yes | Yes | Yes | +| Surface Card | `lib/widgets/surface_card.dart` | Yes | Yes | Yes | +| Skill Directory Authorization Card | `lib/features/settings/skill_directory_authorization_card.dart` | Yes | No | Yes | +| Settings Shell wrapper | `lib/widgets/settings_page_shell.dart` | Yes | Yes | Yes | --- -## 截图 A 对应的关键组件名字 +## 可以删除的 UI 组件 -### 左侧窄图标列 +| 名称 | 路径 | 原因 | +| --- | --- | --- | +| 旧 Web Assistant 页面分层 | `lib/web/web_assistant_page_*` 中重复的局部壳层 | 只有在 Web Assistant 进一步向共享页面收口时才继续删。 | +| 旧设置页 Web 分层 | `lib/web/web_settings_page_*` 中重复的局部壳层 | 只有在 Web 设置页完全收口到共享 `SettingsPage` 后才建议删。 | -桌面截图 A 左边最窄的图标列,对应: +说明: -- `AssistantSideTabRailInternal` -- `AssistantSideTabButtonInternal` +- `web_focus_panel_core.dart` +- `web_focus_panel_previews.dart` +- `web_focus_panel_support.dart` -代码文件: - -- `lib/features/assistant/assistant_page_main.dart` - -它不是全局设置页导航,而是 Assistant 工作区内部的“任务 / 导航 / 关注入口”侧板。 - -### 左侧“设置”卡片 - -左侧大卡片不是完整设置页,而是 Assistant 中的一个“关注入口工作台卡片”: - -- 卡片容器:`AssistantFocusWorkbenchInternal` -- 设置摘要内容:`SettingsFocusPreviewInternal` -- 顶部快捷按钮:`SettingsFocusQuickActions` - -对应文件: - -- `lib/widgets/assistant_focus_panel_core.dart` -- `lib/widgets/assistant_focus_panel_previews.dart` -- `lib/widgets/settings_focus_quick_actions.dart` - -截图里出现的这些文案都直接来自 `SettingsFocusPreviewInternal`: - -- `设置` -- `语言` -- `主题` -- `执行目标` -- `权限` - -### 中间会话区 - -中间对话工作区对应: - -- 页面骨架:`AssistantPage` -- 主体拼装:`buildMainWorkspaceInternal` - -对应文件: - -- `lib/features/assistant/assistant_page_main.dart` -- `lib/features/assistant/assistant_page_state_closure.dart` - -这一块负责: - -- 顶部会话流 -- 消息气泡 -- 底部输入区 -- 附件 / 技能 / 提交按钮 - -### 右侧任务文件栏 - -右侧栏对应: - -- `AssistantArtifactSidebar` - -对应文件: - -- `lib/widgets/assistant_artifact_sidebar.dart` - -截图里的这些元素都在这个组件中: - -- `当前任务工作路径` -- `全部文件` -- `预览` -- `暂无文件` +这三份旧 Web Focus Panel 副本已经不再存在,不再列入候选池。 --- -## 截图 B 对应的关键组件名字 +## 当前清理状态 -### 设置页整体 +### 第一批:已完成 -完整页面组件名: +- Web Focus Panel 共享化已收口到 `lib/widgets/assistant_focus_panel*.dart` +- Web Assistant 不再通过单独的 `web_focus_panel.dart` 兼容壳间接引用共享组件 -- `SettingsPage` +### 第二批:已完成公共壳层收口 -对应文件: +Desktop 与 Web 设置页当前已共用: -- `lib/features/settings/settings_page_core.dart` +- `SettingsPageBodyShell` +- `SettingsGlobalApplyCard` +- `buildOrderedSettingsSections` -它负责: +剩余差异集中在 controller、gateway 细节和 Web 专属 persistence 逻辑,不属于“已完成共享化的重复实现”。 -- 顶部 breadcrumb -- 标题 `设置` -- 副标题 -- 搜索框 `搜索设置` -- 页面 section 排布 +### 第三批:本轮完成 -### 顶部“设置提交流程” +- `IosMobileShell` 兼容壳删除后,以 `MobileShell` 作为唯一正式入口 -组件来源: +### 第四批:持续维护 -- `buildGlobalApplyBarInternal` - -对应文件: - -- `lib/features/settings/settings_page_sections.dart` - -截图里的: - -- `设置提交流程` -- `当前没有待提交更改。` -- `保存并生效` - -都来自这里。 - -### Tab 区域 - -组件名: - -- `SectionTabs` - -对应文件: - -- `lib/widgets/section_tabs.dart` - -截图里的: - -- `通用` -- `工作区` -- `集成` -- `外观` -- `诊断` -- `关于` - -都由这个组件承载。 - -### Application 与账号访问卡片 - -组件来源: - -- `buildGeneralInternal` -- 原子行组件:`SwitchRowInternal` -- 输入组件:`EditableFieldInternal` - -对应文件: - -- `lib/features/settings/settings_page_sections.dart` -- `lib/features/settings/settings_page_widgets.dart` - -截图里这些内容都在这部分: - -- `Application` -- `启用工作台外壳` -- `开机启动` -- `显示 Dock 图标` -- `账号本地模式` -- `账号访问` -- `账号服务地址` -- `账号用户名` -- `工作区名称` - ---- - -## 跨端设计结论 - -### 1. Desktop 与 Web 共用“视觉原子”,但页面容器分裂 - -以下组件明显是跨端复用的: - -- `DesktopWorkspaceScaffold` -- `SurfaceCard` -- `TopBar` -- `SectionTabs` -- `SettingsFocusQuickActions` -- `AssistantArtifactSidebar` - -但 Desktop 与 Web 的页面级容器并没有统一: - -- Desktop 设置页:`SettingsPage` -- Web 设置页:`WebSettingsPage` -- Desktop Assistant:`AssistantPage` -- Web Assistant:`WebAssistantPage` - -这意味着视觉语言接近,但页面编排逻辑仍然是双实现。 - -### 2. Mobile 不是截图同构,而是能力映射 - -Mobile 当前不是截图 A / B 的直接缩放版,而是“能力对应、布局重组”: - -- Assistant 与设置功能仍然存在 -- 但入口通过 `MobileShell` 和 `MobileWorkspaceLauncherInternal` 组织 -- 不存在截图 A 这种桌面三栏结构 -- 设置页在 Mobile 继续复用 `SettingsPage` - -所以从设计维护角度看: - -- `SettingsPage` 是 Desktop / Mobile 的共享设置容器 -- `WebSettingsPage` 是 Web 独立实现 -- `AssistantArtifactSidebar` 是 Desktop / Web 共享产物侧栏 -- “设置焦点卡片”只存在于 Desktop / Web 的 Assistant 焦点面板体系里,不属于 Mobile - -### 3. 如果后续要统一三端设计,优先收敛这三层 - -建议优先把以下三层当作设计系统主干: - -1. 页面骨架层:`DesktopWorkspaceScaffold` / `TopBar` -2. section 层:`SectionTabs` / `SurfaceCard` -3. 领域卡片层:设置卡、焦点卡、产物栏 - -其中最值得继续收敛的重复实现是: - -- `SettingsPage` vs `WebSettingsPage` -- `AssistantFocusPanel` vs `WebAssistantFocusPanel` -- `assistant_focus_panel_previews.dart` vs `web_focus_panel_previews.dart` - ---- - -## 建议的后续文档演进 - -如果后续继续补 UI 文档,建议按下面三个文件拆: - -1. `assistant-layout-spec.md` - 只描述 Assistant 三栏布局、会话区、产物栏 -2. `settings-page-spec.md` - 只描述设置页 section、字段、交互状态 -3. `cross-platform-ui-parity.md` - 专门记录 Desktop / Web / Mobile 的同构与差异 - ---- - -## 可合并 / 可清理分析 - -在保持三栏布局骨架不变的前提下,当前最值得处理的不是页面骨架,而是页面骨架内部已经重复的“焦点卡片层”和“预览内容层”。 - -### A. 第一优先级:可直接合并复用 - -#### 1. Focus Panel Core - -- Desktop: `lib/widgets/assistant_focus_panel_core.dart` -- Web: `lib/web/web_focus_panel_core.dart` - -这两份文件当前为同构重复实现。 - -判断依据: - -- 文件长度完全一致,均为 `347` 行 -- 代码 diff 主要只剩: - - `app_controller.dart` vs `app_controller_web.dart` - - 相对 import 路径差异 - - widget 命名前缀 `Assistant*` vs `WebAssistant*` - -合并建议: - -- 保留 `lib/widgets/assistant_focus_panel*.dart` 作为唯一实现 -- Web 端直接复用共享 widget -- 删除 Web 侧同构副本,或先退化为兼容导出薄壳 - -#### 2. Focus Panel Previews - -- Desktop: `lib/widgets/assistant_focus_panel_previews.dart` -- Web: `lib/web/web_focus_panel_previews.dart` - -这两份文件当前也为同构重复实现。 - -判断依据: - -- 文件长度完全一致,均为 `636` 行 -- diff 也只剩 controller import 和路径差异 -- `SettingsFocusPreviewInternal`、`LanguageFocusPreviewInternal`、`ThemeFocusPreviewInternal` 等实现一致 - -合并建议: - -- 收敛到 `lib/widgets/assistant_focus_panel_previews.dart` -- Web Assistant 通过共享导出的 `AssistantFocusPanel` 直接复用 - -#### 3. Focus Panel Support - -- Desktop: `lib/widgets/assistant_focus_panel_support.dart` -- Web: `lib/web/web_focus_panel_support.dart` - -这两份 support 文件同样是同构副本,可和 core / previews 一起收口。 - -### B. 第二优先级:可抽公共层,但不建议整页硬合并 - -#### 1. Settings Page Core - -- Desktop: `lib/features/settings/settings_page_core.dart` -- Web: `lib/web/web_settings_page_core.dart` - -不建议直接合成一个页面类。 - -原因: - -- Desktop settings 还承载 `SettingsDetailPage` drill-down、`initialDetail`、`navigationContext` -- Web settings 重点维护浏览器会话持久化、Local/Remote Gateway、External ACP -- 二者状态模型明显不对称 - -建议做法: - -- 抽共享壳层和 section 编排逻辑 -- 保留 Desktop / Web 两个 page container - -#### 2. Settings Page Sections - -- Desktop: `lib/features/settings/settings_page_sections.dart` -- Web: `lib/web/web_settings_page_sections.dart` - -这里适合抽: - -- `buildGlobalApplyBarInternal` -- overview tab 排布 -- section 级 SurfaceCard 组织方式 - -但不适合一步到位强合并所有业务 section。 - -### C. 可标记清理 - -#### 1. Web Focus Panel 重复文件 - -以下文件可以标记为第一批清理对象: - -- `lib/web/web_focus_panel_core.dart` -- `lib/web/web_focus_panel_previews.dart` -- `lib/web/web_focus_panel_support.dart` - -清理前提: - -- Web Assistant 全部切回共享 `lib/widgets/assistant_focus_panel.dart` -- 相关测试与 import 路径同步调整 - -#### 2. 已废弃 iOS 壳别名 - -- `lib/features/mobile/ios_mobile_shell.dart` - -该文件已标注: - -- `@Deprecated('Use MobileShell instead.')` - -功能上只是直接转发到 `MobileShell`,可以标记为后续兼容清理对象。 - -#### 3. 不在这两张图主链路中的 settings detail 旁路 - -以下内容不属于截图 B 的 overview 主链路,建议后续拆出: - -- `buildDetailContentInternal` -- `buildDetailIntroInternal` -- `SettingsDetailPage.*` - -对应文件: - -- `lib/features/settings/settings_page_sections.dart` - -这些应独立成 detail flow 文件,而不是继续和 overview 同居在一个大文件里。 - -#### 4. settings 目录中的大面积冗余 import - -当前以下文件头部都带有较重的 `unused_import` / 互相引用信号: - -- `lib/features/settings/settings_page_core.dart` -- `lib/features/settings/settings_page_sections.dart` -- `lib/features/settings/settings_page_widgets.dart` -- `lib/features/settings/settings_page_gateway_connection.dart` -- `lib/features/settings/settings_page_gateway_llm.dart` -- `lib/features/settings/settings_page_multi_agent.dart` -- `lib/features/settings/settings_page_presentation.dart` -- `lib/features/settings/settings_page_device.dart` - -这些不是“立即删除”对象,但可以明确标记为依赖清理范围。 - -### D. 本轮推荐执行顺序 - -在不动三栏布局骨架前提下,推荐按这个顺序执行: - -1. 合并 Desktop / Web 的 Focus Panel Core / Previews / Support -2. 抽 Settings 页的共享 section 壳层 -3. 拆 Settings detail flow,避免与 overview 混杂 -4. 清理 deprecated mobile 壳与 settings 冗余 imports - -### E. 当前基线测试记录 - -本轮开始前的最小基线如下: - -- `flutter test test/widgets/assistant_focus_panel_suite.dart` - - 结果:通过 -- `flutter test --platform chrome test/web/web_ui_browser_test.dart` - - 结果:失败 - - 当前已知失败点:测试找不到 “集成” tab - -因此后续重构验证需要区分: - -- 共享 Focus Panel 的 widget 层回归 -- Web 端已有基线失败,不能误判为本轮新引入问题 +- 文档和测试应只引用当前仍存在的 UI 文件 +- 不再记录已经删除的旧 Web Focus Panel 副本路径 diff --git a/docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md b/docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md index 00c43444..56641c39 100644 --- a/docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md +++ b/docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md @@ -1,146 +1,26 @@ -# Focus Panel Dedupe Implementation Plan +# Focus Panel Dedupe Implementation Status -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. +## 状态 -**Goal:** 在保持 Assistant 三栏布局骨架不变的前提下,收敛 Desktop / Web 重复的 Focus Panel 实现,建立共享前端组件单一来源。 +已完成。 -**Architecture:** 保留 `lib/widgets/assistant_focus_panel*.dart` 作为唯一实现,Web 端改为直接复用共享 widgets,不再维护同构副本。先处理 Focus Panel Core / Previews / Support,再调整 Web Assistant 侧的 import 和引用,最后更新测试与文档。 +## 当前事实 -**Tech Stack:** Flutter, Dart, conditional export `app_controller.dart`, widget tests, browser tests +- 共享实现唯一来源为: + - `lib/widgets/assistant_focus_panel.dart` + - `lib/widgets/assistant_focus_panel_core.dart` + - `lib/widgets/assistant_focus_panel_previews.dart` + - `lib/widgets/assistant_focus_panel_support.dart` +- Web 侧旧的 `web_focus_panel_core.dart`、`web_focus_panel_previews.dart`、`web_focus_panel_support.dart` 已不再存在。 +- 本轮进一步移除了 `lib/web/web_focus_panel.dart` 这一层兼容导出,Web Assistant 侧不再保留旧入口。 ---- +## 验收关注点 -### Task 1: 记录当前实施上下文 +- `test/widgets/assistant_focus_panel_suite.dart` +- `test/web/web_ui_browser_test.dart` +- Web Assistant 页面不再引用旧 Focus Panel 文件路径 -**Files:** -- Modify: `docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md` -- Create: `docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md` +## Residual Risks -**Step 1: 追加“可合并 / 可清理分析”** - -把本轮结论写入组件矩阵文档: - -- 可直接合并:Focus Panel Core / Previews / Support -- 可抽公共层:Settings Page Core / Sections -- 可标记清理:Web Focus Panel 副本、deprecated iOS shell、settings detail 旁路 - -**Step 2: 记录基线测试** - -记录: - -- `flutter test test/widgets/assistant_focus_panel_suite.dart` 通过 -- `flutter test --platform chrome test/web/web_ui_browser_test.dart` 当前基线失败,失败点为找不到 “集成” tab - -### Task 2: 建立共享 Focus Panel 单一实现 - -**Files:** -- Modify: `lib/widgets/assistant_focus_panel.dart` -- Modify: `lib/widgets/assistant_focus_panel_core.dart` -- Modify: `lib/widgets/assistant_focus_panel_previews.dart` -- Modify: `lib/widgets/assistant_focus_panel_support.dart` -- Modify: `lib/web/web_assistant_page_core.dart` -- Modify: `lib/web/web_assistant_page_chrome.dart` -- Modify: `lib/web/web_assistant_page_workspace.dart` -- Modify: `lib/web/web_assistant_page_helpers.dart` - -**Step 1: 让 Web 侧直接依赖共享入口** - -把 Web Assistant 页面中对 `web_focus_panel.dart` 的依赖改成共享 `../widgets/assistant_focus_panel.dart`。 - -**Step 2: 去掉 Web 专属 Focus Panel 类型耦合** - -把 `WebAssistantFocusPanel` 的使用点替换为 `AssistantFocusPanel`。 - -**Step 3: 确认共享组件继续使用条件导出的 controller** - -共享 Focus Panel 通过 `../app/app_controller.dart` 获取平台适配后的 `AppController`,不再区分 Desktop/Web 文件树。 - -### Task 3: 退役 Web Focus Panel 副本 - -**Files:** -- Delete: `lib/web/web_focus_panel_core.dart` -- Delete: `lib/web/web_focus_panel_previews.dart` -- Delete: `lib/web/web_focus_panel_support.dart` -- Modify: `lib/web/web_focus_panel.dart` - -**Step 1: 保留一个薄入口或直接删入口** - -推荐做法: - -- `lib/web/web_focus_panel.dart` 变成一行导出共享 widget 的兼容入口 - -```dart -export '../widgets/assistant_focus_panel.dart'; -``` - -**Step 2: 删除三份重复副本** - -删除: - -- `web_focus_panel_core.dart` -- `web_focus_panel_previews.dart` -- `web_focus_panel_support.dart` - -### Task 4: 更新测试与守护规则 - -**Files:** -- Modify: `test/widgets/assistant_focus_panel_suite.dart` -- Verify: `test/web/web_ui_browser_test.dart` - -**Step 1: 更新文件存在性 / 行数守护** - -将原来对 Web 重复文件的守护改成对共享实现的守护,避免测试继续依赖已删除文件路径。 - -**Step 2: 跑 widget 测试** - -Run: - -```bash -flutter test test/widgets/assistant_focus_panel_suite.dart -``` - -Expected: - -- PASS - -**Step 3: 跑 browser 测试并记录结果** - -Run: - -```bash -flutter test --platform chrome test/web/web_ui_browser_test.dart -``` - -Expected: - -- 如果仍失败,需要确认是否仍是既有 “集成” tab 失败 -- 如果失败点变化,说明本轮重构影响了 Web 链路,需要回退排查 - -### Task 5: 回归与提交 - -**Files:** -- Verify only - -**Step 1: 检查 git diff** - -确认本轮只涉及: - -- 文档 -- Focus Panel 共享化 -- 测试更新 - -**Step 2: 记录 residual risks** - -记录: - -- `SettingsPage` / `WebSettingsPage` 尚未统一 -- `settings detail flow` 仍在 Desktop overview 体系里 -- `ios_mobile_shell.dart` 仍未清理 - -**Step 3: 提交** - -建议提交信息: - -```bash -git commit -m "refactor: dedupe assistant focus panel across desktop and web" -``` +- `SettingsPage` / `WebSettingsPage` 仍然是双容器实现,但公共壳层已共享 +- Web Assistant 页面内部仍保留自己的页面分层,后续可继续评估是否值得继续收口 diff --git a/docs/plans/2026-03-30-settings-section-shell-implementation-plan.md b/docs/plans/2026-03-30-settings-section-shell-implementation-plan.md index d9e7749d..d5f57c4b 100644 --- a/docs/plans/2026-03-30-settings-section-shell-implementation-plan.md +++ b/docs/plans/2026-03-30-settings-section-shell-implementation-plan.md @@ -1,121 +1,35 @@ -# Settings Section Shell Implementation Plan +# Settings Section Shell Implementation Status -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. +## 状态 -**Goal:** Extract a shared Settings page shell so Desktop and Web reuse the same top-level layout, ordered section composition, and global apply bar behavior without changing the three-column workspace skeleton. +已完成公共壳层收口。 -**Architecture:** Introduce a small shared shell widget layer under `lib/widgets/` that owns the common settings-page frame and ordered section assembly. Keep Desktop and Web-specific controllers, gateway sub-tabs, and section content builders in their existing feature modules. +## 当前共享层 -**Tech Stack:** Flutter, Dart, existing `TopBar`/`SurfaceCard` widgets, Desktop/Web app controllers. +Desktop 与 Web 设置页当前共用以下结构层: ---- +- `lib/widgets/settings_page_shell.dart` + - `SettingsPageBodyShell` + - `SettingsGlobalApplyCard` + - `buildOrderedSettingsSections` -### Task 1: Add a shared settings page shell module +这意味着两端已经统一: -**Files:** -- Create: `lib/widgets/settings_page_shell.dart` +- 顶部 `TopBar` 承载方式 +- 全局 apply bar 结构 +- overview section 的排序装配方式 -**Step 1: Add a shared apply-bar widget** +## 当前仍保留的平台差异 -- Implement a widget that renders: - - title `设置提交流程 / Settings Submission` - - resolved draft/apply status copy - - `settings-global-apply-button` -- Pass behavior through parameters instead of depending on a specific controller type. +- Desktop:`lib/features/settings/settings_page_core.dart` + - 持有 detail flow、navigation context、gateway profile hints +- Web:`lib/web/web_settings_page_core.dart` + - 持有浏览器 persistence、Web gateway 子页和 Web 专属 copy -**Step 2: Add a shared page body shell** +## 结论 -- Implement a widget that renders: - - `TopBar` - - optional shared apply bar - - page body children -- Keep paddings configurable so Desktop and Web can preserve their current spacing. +第二批不再需要重复执行“抽共享壳层”本身。后续如继续清理,应只处理: -**Step 3: Add a shared ordered-section helper** - -- Implement a helper that: - - takes `availableTabs`, `currentTab` - - asks a callback for each tab’s content - - interleaves `SizedBox(height: 24)` between non-empty sections - -### Task 2: Move Desktop Settings page onto the shared shell - -**Files:** -- Modify: `lib/features/settings/settings_page_core.dart` -- Modify: `lib/features/settings/settings_page_sections.dart` - -**Step 1: Replace duplicated page frame markup** - -- Swap the current top-level `SingleChildScrollView -> Column -> TopBar -> apply bar -> body` block to the shared shell widget. - -**Step 2: Replace duplicated ordered overview assembly** - -- Route overview ordering through the shared helper instead of local inline assembly. - -**Step 3: Keep detail-mode behavior unchanged** - -- Ensure the existing desktop-only detail flow still owns: - - breadcrumbs - - back button - - detail intro cards - - gateway navigation hints - -### Task 3: Move Web Settings page onto the shared shell - -**Files:** -- Modify: `lib/web/web_settings_page_core.dart` -- Modify: `lib/web/web_settings_page_sections.dart` - -**Step 1: Reuse the shared page frame** - -- Keep `DesktopWorkspaceScaffold` in Web. -- Replace the inner duplicated page body with the shared shell widget. - -**Step 2: Reuse the ordered-section helper where still needed** - -- Keep Web tab availability constraints intact. -- Use the same helper for any ordered overview logic that remains. - -**Step 3: Preserve Web-specific gateway behavior** - -- Keep: - - web search field key - - browser persistence copy - - ACP-specific apply-bar gating - -### Task 4: Verify the refactor - -**Files:** -- Modify as needed: `test/features/settings_page_suite.dart` -- Modify as needed: `test/web/web_ui_browser_test.dart` - -**Step 1: Run static analysis** - -Run: - -```bash -flutter analyze lib/widgets/settings_page_shell.dart lib/features/settings/settings_page_core.dart lib/features/settings/settings_page_sections.dart lib/web/web_settings_page_core.dart lib/web/web_settings_page_sections.dart test/features/settings_page_suite.dart test/web/web_ui_browser_test.dart -``` - -**Step 2: Run targeted Desktop settings tests** - -Run: - -```bash -flutter test test/features/settings_page_suite.dart -``` - -**Step 3: Run targeted Web browser regression** - -Run: - -```bash -flutter test --platform chrome test/web/web_ui_browser_test.dart -``` - -**Step 4: Record residual risk** - -- Note whether any remaining Desktop/Web duplication still lives in: - - gateway sub-tab section builders - - detail-only desktop flows - - web-only persistence cards +- Web / Desktop 剩余的业务 section 重复 +- 已无价值的旧路径引用 +- 测试和文档守护的一致性 diff --git a/lib/features/mobile/ios_mobile_shell.dart b/lib/features/mobile/ios_mobile_shell.dart deleted file mode 100644 index 5295be35..00000000 --- a/lib/features/mobile/ios_mobile_shell.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../app/app_controller.dart'; -import 'mobile_shell.dart'; - -@Deprecated('Use MobileShell instead.') -class IosMobileShell extends StatelessWidget { - const IosMobileShell({super.key, required this.controller}); - - final AppController controller; - - @override - Widget build(BuildContext context) { - return MobileShell(controller: controller); - } -} diff --git a/lib/web/web_assistant_page_chrome.dart b/lib/web/web_assistant_page_chrome.dart index 858c9ddc..3927fc91 100644 --- a/lib/web/web_assistant_page_chrome.dart +++ b/lib/web/web_assistant_page_chrome.dart @@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart'; import '../widgets/desktop_workspace_scaffold.dart'; import '../widgets/pane_resize_handle.dart'; import '../widgets/surface_card.dart'; -import 'web_focus_panel.dart'; import 'web_assistant_page_core.dart'; import 'web_assistant_page_workspace.dart'; import 'web_assistant_page_helpers.dart'; diff --git a/lib/web/web_assistant_page_core.dart b/lib/web/web_assistant_page_core.dart index 4d6eab25..03f634ce 100644 --- a/lib/web/web_assistant_page_core.dart +++ b/lib/web/web_assistant_page_core.dart @@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart'; import '../widgets/desktop_workspace_scaffold.dart'; import '../widgets/pane_resize_handle.dart'; import '../widgets/surface_card.dart'; -import 'web_focus_panel.dart'; import 'web_assistant_page_chrome.dart'; import 'web_assistant_page_workspace.dart'; import 'web_assistant_page_helpers.dart'; diff --git a/lib/web/web_assistant_page_helpers.dart b/lib/web/web_assistant_page_helpers.dart index e2023b9b..0f924097 100644 --- a/lib/web/web_assistant_page_helpers.dart +++ b/lib/web/web_assistant_page_helpers.dart @@ -15,7 +15,6 @@ import '../widgets/assistant_artifact_sidebar.dart'; import '../widgets/desktop_workspace_scaffold.dart'; import '../widgets/pane_resize_handle.dart'; import '../widgets/surface_card.dart'; -import 'web_focus_panel.dart'; import 'web_assistant_page_core.dart'; import 'web_assistant_page_chrome.dart'; import 'web_assistant_page_workspace.dart'; diff --git a/lib/web/web_assistant_page_workspace.dart b/lib/web/web_assistant_page_workspace.dart index 2aa84dda..c528b693 100644 --- a/lib/web/web_assistant_page_workspace.dart +++ b/lib/web/web_assistant_page_workspace.dart @@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart'; import '../widgets/desktop_workspace_scaffold.dart'; import '../widgets/pane_resize_handle.dart'; import '../widgets/surface_card.dart'; -import 'web_focus_panel.dart'; import 'web_assistant_page_core.dart'; import 'web_assistant_page_chrome.dart'; import 'web_assistant_page_helpers.dart'; diff --git a/lib/web/web_focus_panel.dart b/lib/web/web_focus_panel.dart deleted file mode 100644 index 0a654afc..00000000 --- a/lib/web/web_focus_panel.dart +++ /dev/null @@ -1 +0,0 @@ -export '../widgets/assistant_focus_panel.dart'; diff --git a/test/features/mobile/ios_mobile_shell_suite.dart b/test/features/mobile/mobile_shell_suite.dart similarity index 100% rename from test/features/mobile/ios_mobile_shell_suite.dart rename to test/features/mobile/mobile_shell_suite.dart diff --git a/test/features/mobile/ios_mobile_shell_test.dart b/test/features/mobile/mobile_shell_test.dart similarity index 60% rename from test/features/mobile/ios_mobile_shell_test.dart rename to test/features/mobile/mobile_shell_test.dart index 29032910..d5f35443 100644 --- a/test/features/mobile/ios_mobile_shell_test.dart +++ b/test/features/mobile/mobile_shell_test.dart @@ -1,5 +1,5 @@ import '../../test_suite_stub.dart' - if (dart.library.io) 'ios_mobile_shell_suite.dart' + if (dart.library.io) 'mobile_shell_suite.dart' as suite; void main() {