Skip to content

♻️ 新 UI 重写:shadcn/ui + Tailwind v4 + React 19 全面重构表现层#1514

Open
CodFrm wants to merge 191 commits into
mainfrom
develop/new-ui
Open

♻️ 新 UI 重写:shadcn/ui + Tailwind v4 + React 19 全面重构表现层#1514
CodFrm wants to merge 191 commits into
mainfrom
develop/new-ui

Conversation

@CodFrm

@CodFrm CodFrm commented Jun 17, 2026

Copy link
Copy Markdown
Member

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试(单元测试已覆盖,真机可视化验收进行中)

设计稿.pen.zip

Description / 描述

🚧 草稿 PR:整个新 UI 重写的集成 PR,合并目标为 main。目前仍在做各页面的真机可视化验收,完成后再转为正式 PR。

使用 shadcn/ui + Tailwind CSS v4 + React 19src/pages/ 表现层进行从零重写,替换原有的 Arco Design + UnoCSS 技术栈。设计系统(颜色令牌、组件、布局/动效/状态规范)统一沉淀在 docs/DESIGN.md,所有页面同时适配亮色/暗色主题(Tailwind dark: 变体 + src/index.css 设计令牌)。

已完成页面

核心管理页

  • 脚本列表(ScriptList,含表格/卡片、过滤侧栏、批量操作、移动端)
  • 订阅列表(SubscribeList)
  • 脚本编辑器(ScriptEditor,Monaco + 多标签 + 代码/资源/设置/存储面板)
  • 日志(Logger)、设置(Setting)、工具(Tools)
  • 弹出层(popup)

独立页面

  • 安装页(install,身份→权限→代码 信任优先布局,脚本/订阅/Skill 安装、本地文件监听、移动端)
  • 数据导入页(import,数据导入/备份恢复)
  • 授权确认页(confirm,时长选择 + 允许/拒绝)
  • 批量更新页(batchupdate,表格勾选 + 风险标签 + 已忽略分组)

Agent 套件(7 页)

  • 会话(AgentChat,三栏可折叠 + 流式 + thinking/工具调用/任务列表/ask_user/附件富块 + 移动导航抽屉)
  • 模型服务(AgentProvider)、Skills、MCP、定时任务(AgentTasks)、OPFS 文件浏览器、设置(AgentSettings)

其它

  • i18n:7 种语言(zh-CN / zh-TW / en-US / ja-JP / de-DE / ru-RU / vi-VN)同步更新
  • 测试:遵循 TDD,使用 vitest + Testing Library,新页面均有单元/组件测试覆盖
  • 文档:新增 docs/DESIGN.md,更新 docs/DEVELOP.md / docs/README.md 等贡献者文档

待办(转正式 PR 前)

  • 各页面真机可视化验收(亮色/暗色 + 桌面/移动)
  • 页内功能与旧版逐项对账复核

Screenshots / 截图

CodFrm added 30 commits April 6, 2026 00:14
移除基于 Arco Design + UnoCSS 的旧 UI 层与相关依赖,为下一版
基于 Tailwind CSS + shadcn/ui 的 UI 重构做准备。

- 删除 6 个页面(options/popup/install/confirm/import/batchupdate)、所有 UI 组件、HTML 模板和 CSS
- 卸载 16 个 UI 相关依赖(@arco-design/web-react、unocss、@dnd-kit/*、react-dropzone、react-joyride、react-router-dom、react-icons、react-i18next、@playwright/test 等)
- 删除 e2e 测试目录与 Playwright 配置
- 更新 rspack.config.ts 移除 UI entry 和 HtmlRspackPlugin
- 更新技术栈文档(CLAUDE.md、copilot-instructions、CONTRIBUTING)

保留:非 UI 入口(service_worker/content/inject/offscreen/sandbox)、
monaco-editor、i18next、pages/store/{global,favicons,features/script}.ts
- 使用 Tailwind CSS + shadcn/ui 重构 popup 页面
- 实现完整业务逻辑:脚本列表、启用/禁用、删除、排除、GM 菜单等
- 添加 usePopupData hook 对接 service worker 后端 API 和实时订阅
- 新增 Popconfirm 组件用于删除确认
- 配置设计系统色彩令牌(品牌蓝、状态色、暗色模式)
- 搭建 options 页面入口(骨架)
- 新增 Sidebar 组件:导航、帮助中心菜单(hover触发)、主题切换、折叠
- 使用 HashRouter 配置路由(脚本列表/订阅/日志/工具/设置/编辑器)
- 提取 GithubIcon 组件替代 popup 和 sidebar 中的 inline SVG
- i18n 使用已有翻译 key,与 release/v1.4 保持一致
- 将 translation.json 拆分为 11 个命名空间(common/agent/script/editor/settings/install/popup/logs/guide/tools/permission)
- 升级 React 18→19、i18next 23→26,引入 react-i18next
- 还原 SW 层 popup 逻辑至 v1.5(不在 SW 中处理 i18n)
- 删除 Crowdin 配置、伪语言 ach-UG 及相关文档引用
- 修复 React 19 类型兼容(useRef、cloneElement)
# Conflicts:
#	package.json
#	pnpm-lock.yaml
#	src/app/service/service_worker/gm_api/gm_api.ts
#	src/app/service/service_worker/index.ts
#	src/locales/ach-UG/translation.json
#	src/locales/de-DE/translation.json
#	src/locales/en-US/translation.json
#	src/locales/ja-JP/translation.json
#	src/locales/ru-RU/translation.json
#	src/locales/vi-VN/translation.json
#	src/locales/zh-CN/translation.json
#	src/locales/zh-TW/translation.json
#	src/pages/components/CodeEditor/index.tsx
#	src/pages/components/UserConfigPanel/index.tsx
#	src/pages/components/layout/MainLayout.tsx
#	src/pages/install/App.tsx
#	src/pages/options/index.css
#	src/pages/options/routes/Logger.tsx
#	src/pages/options/routes/Setting.tsx
#	src/pages/options/routes/script/ScriptEditor.tsx
#	src/pages/popup/App.tsx
# Conflicts:
#	CONTRIBUTING.md
#	README.md
#	docs/CONTRIBUTING_EN.md
#	docs/CONTRIBUTING_RU.md
#	docs/README_RU.md
#	docs/README_ja.md
#	docs/README_zh-CN.md
#	docs/README_zh-TW.md
#	e2e/install.spec.ts
#	e2e/popup.spec.ts
#	e2e/script-editor.spec.ts
#	e2e/script-management.spec.ts
#	e2e/settings.spec.ts
#	e2e/vscode-connect.spec.ts
#	package.json
#	playwright.config.ts
#	pnpm-lock.yaml
#	src/app/service/content/scripting.ts
#	src/app/service/service_worker/gm_api/gm_api.ts
#	src/app/service/service_worker/index.ts
#	src/index.css
#	src/locales/README.md
#	src/locales/de-DE/translation.json
#	src/locales/en-US/translation.json
#	src/locales/ja-JP/translation.json
#	src/locales/locales.ts
#	src/locales/ru-RU/translation.json
#	src/locales/vi-VN/translation.json
#	src/locales/zh-CN/translation.json
#	src/locales/zh-TW/translation.json
#	src/manifest.json
#	src/pages/components/CodeEditor/index.tsx
#	src/pages/components/ScriptMenuList/index.tsx
#	src/pages/components/layout/MainLayout.tsx
#	src/pages/components/layout/Sider.tsx
#	src/pages/components/layout/SiderGuide.tsx
#	src/pages/confirm/App.tsx
#	src/pages/install/App.tsx
#	src/pages/install/hooks.tsx
#	src/pages/install/utils.ts
#	src/pages/options.html
#	src/pages/options/routes/AgentChat/ChatArea.tsx
#	src/pages/options/routes/AgentMcp.tsx
#	src/pages/options/routes/AgentOPFS.tsx
#	src/pages/options/routes/AgentProvider.tsx
#	src/pages/options/routes/AgentSettings.tsx
#	src/pages/options/routes/AgentSkills.tsx
#	src/pages/options/routes/AgentTasks.tsx
#	src/pages/options/routes/ScriptList/components.tsx
#	src/pages/options/routes/ScriptList/index.tsx
#	src/pages/options/routes/Setting.tsx
#	src/pages/options/routes/SubscribeList.tsx
#	src/pages/options/routes/Tools.tsx
#	src/pages/options/routes/script/ScriptEditor.tsx
#	src/pages/options/routes/script/index.css
#	src/pages/popup.html
#	src/pages/popup/App.tsx
#	src/pages/template.html
#	tests/pages/options/MainLayout.test.tsx
@cyfung1031

Copy link
Copy Markdown
Collaborator

「脚本垃圾回收站功能」不在这一版做吗

@CodFrm

CodFrm commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

「脚本垃圾回收站功能」不在这一版做吗

做 合并了这个再处理

CodFrm added 3 commits June 24, 2026 20:12
为 new-ui options 页实现「首次自动 + 可手动重看」的新手引导:
- 控制器 OnboardingProvider + useOnboarding,首次(非隐身、onboarding_done=false、非全屏编辑器)自动弹欢迎;标志存 SystemConfig.onboarding_done(chrome.storage.local,按设备)
- 欢迎弹窗(桌面 Dialog / 移动 Sheet),真实 logo
- 巡览:桌面 6 步 / 移动 3 步 Coachmark,data-tour 锚点定位;自研聚光灯遮罩 + 自定位步骤卡;Esc 退出与焦点管理;observeTarget 保证跨路由目标定位
- 巡览时在脚本列表注入演示脚本(表现层、不落库、结束即恢复;整屏遮罩拦截点击避免误触发真实动作)
- 入口位于帮助中心(侧栏 hover 二级菜单 + 移动抽屉),名为「新手引导」
- 步骤关联文档站(市场/后台/UserConfig/备份/迁移/同步/订阅),en 用 /en/docs 其余 /docs
- 明暗双主题;guide 命名空间文案 7 语言
- 新手引导首次进入标志由 SystemConfig(onboarding_done) 改为 localStorage(firstUse),
  移除相关 config 读写与 STORAGE_LOCAL_KEYS 常量
- 清理 7 个语言包中未使用的翻译键;修复 cron.ts 缺失的 script: 命名空间前缀
  (此前 nextTimeDisplay 渲染的是未翻译的 key)
- 安装页后台/定时/反特性标签补充 title 提示;脚本列表新增定时脚本下次运行时间展示
@CodFrm

CodFrm commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

整理了一轮与本次 UI/UX 重构分支直接相关的 open issues。这里的“是否可以关闭”按 issue 原始诉求判断;有相关 UI 改善但没覆盖核心诉求的,先标 ❌。

已对照 develop/new-ui 当前代码复核(2026-06-26):仅保留与本次 UI/UX 重构直接相关,或能由新 UI 明确判断是否覆盖的 issue。纯新功能、运行时能力、后台逻辑、特定浏览器兼容问题不放在此表。

Issue 结论 是否可以关闭 代码判断依据
#1496 脚本列表与 Popup 的脚本名本地化已覆盖。 脚本列表表格/卡片使用 i18nName(script);Popup 返回前通过 applyScriptDisplayInfo() 补本地化名称和图标。见 src/pages/options/routes/ScriptList/ScriptTable.tsxsrc/pages/options/routes/ScriptList/ScriptCardGrid.tsxsrc/app/service/service_worker/popup_scriptmenu.ts
#1482 备份目标类型和当前目标参数切换后会立即写入 systemConfig.backup,不再必须点击“备份”才保存配置。 CloudBackupSection 新增 saveDraft(),文件系统类型与参数变更均调用保存;覆盖测试见 src/pages/options/routes/Tools/sections/CloudBackupSection.test.tsx。见 src/pages/options/routes/Tools/sections/CloudBackupSection.tsx
#1456 脚本设置中的 @match / @exclude 与授权添加已支持多行批量粘贴,保存前会 trim、跳过空行和重复项,并提供解析预览。 SettingsPane 新增批量解析/预览和批量提交;覆盖测试见 src/pages/options/routes/ScriptEditor/tabs/SettingsPane.test.tsx。见 src/pages/options/routes/ScriptEditor/tabs/SettingsPane.tsx
#1447 移动端主界面、已安装脚本页和 Popup 留白问题已完成修复。 新增移动端 Header、底部 Tab、移动端脚本列表;Popup 改成单滚动区和 w-full,并在 popup.html 增加 @media (min-width:365px){html,body{width:100%;max-height:none}},使移动端 popup 撑满外层容器、消除右侧/下侧留白(commit fa024d06 / PR #1507,close #686)。见 src/pages/popup.htmlsrc/pages/options/layout/MobileHeader.tsxsrc/pages/options/layout/BottomTabBar.tsxsrc/pages/options/routes/ScriptList/ScriptListMobile.tsxsrc/pages/popup/App.tsx
#1399 Popup 宽度/完整脚本名提示未满足。 Popup 脚本名仍 truncatetitle 当前用于运行次数提示,不是完整脚本名;也未见显式扩大 popup 宽度。见 src/pages/popup/App.tsx
#1363 “设置 - 开发工具”里的 ESLint 规则、编辑器配置、类型定义已改为 Monaco 编辑器,并按标签页组织。 DeveloperSection 接入 DeveloperMonacoEditor;覆盖测试见 src/pages/options/routes/Setting/sections/DeveloperSection.test.tsxsrc/pages/options/routes/Setting/sections/DeveloperMonacoEditor.test.tsx。见 src/pages/options/routes/Setting/sections/DeveloperSection.tsxsrc/pages/options/routes/Setting/sections/DeveloperMonacoEditor.tsx
#1321 日志时间范围变更后会自动重新加载,不再必须手点查询。 useLogger()range 变化时自动 fetchLogs(range.start, range.end);日志页还提供自动刷新间隔。见 src/pages/options/routes/Logger/hooks.tssrc/pages/options/routes/Logger/index.tsx
#1108 手机端界面适配已系统性重做。 新 UI 有移动端主导航、底部导航、脚本列表、日志页、编辑器等专门实现。见 src/pages/options/layout/MobileHeader.tsxsrc/pages/options/layout/BottomTabBar.tsxsrc/pages/options/routes/ScriptList/ScriptListMobile.tsxsrc/pages/options/routes/Logger/index.tsxsrc/pages/options/routes/ScriptEditor/MobileEditor.tsx
#913 Popup 操作入口已完成;新 UI 采用点击脚本行展开操作区的交互,不再按原 hover inline tools 方案实现。 Popup 点击脚本行展开操作区,含编辑、排除、删除,符合新 UI 交互取舍。见 src/pages/popup/App.tsx
#633 手机端脚本文本编辑已实现。 移动端 ScriptEditorMobileEditor,提供代码/存储/资源/设置子标签,以及保存、运行、撤销、重做、查找。见 src/pages/options/routes/ScriptEditor/MobileEditor.tsx
#961 日志页默认自动查询,打开页面不需要先点查询。 useLogger() 默认 24h 预设并在挂载/range 变化时自动加载日志。见 src/pages/options/routes/Logger/hooks.ts
#814 最后一个编辑器 Tab 关闭后的行为已明确实现。 closeTab() 判断 wasLast,关闭最后一个 Tab 后调用 openScript(undefined, ...) 打开空脚本。见 src/pages/options/routes/ScriptEditor/index.tsx
#576 脚本列表现在会持久化视图模式、搜索、筛选和列排序状态;旧版 script-list-view-mode 仍兼容读取。 新增 ScriptList/preferences.tsScriptList 将 filter/search/sort/view 写入 localStorage;覆盖测试见 preferences.test.tsindex.test.tsxScriptTable.test.tsx。见 src/pages/options/routes/ScriptList/preferences.tssrc/pages/options/routes/ScriptList/index.tsxsrc/pages/options/routes/ScriptList/ScriptTable.tsx

汇总:当前可以直接关闭的是 #1496#1482#1456#1447#1363#1321#1108#913#633#961#814#576#1399 仍未完整覆盖。已从本表移除纯新功能/运行时能力/后台逻辑/特定浏览器兼容类 issue:#1495#1453#1351#1063#992#991#941#907#864#830#684

把 main 的 SC_DISABLE_AGENT / EnableAgent 屏蔽机制(2a83fd2)落到新 UI:
- 版本冲突保留 develop 的 1.5.0-beta / 1.5.0.1100
- script.ts 保留 develop 仅 .cat.md 的 Web 安装规则,并按 EnableAgent 收敛
- 新 UI 入口按 EnableAgent 屏蔽:侧栏/移动抽屉 agent 菜单、/agent 路由、
  安装页 ?skill= 与 .cat.md 入口、导入 .zip Skill 包
- 删除被新 UI 重构替换的旧文件(Sider/MainLayout/install hooks/utils)
Comment thread rspack.config.ts
@cyfung1031

Copy link
Copy Markdown
Collaborator

翻译的部份,合并前要用AI跟现时版本和 terminology 一起对比一下。
新版的翻译质素好像有点下滑了 (应该说之前的版本都是各语言母语者贡献过)

@CodFrm CodFrm mentioned this pull request Jul 2, 2026
@CodFrm

CodFrm commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

翻译的部份,合并前要用AI跟现时版本和 terminology 一起对比一下。 新版的翻译质素好像有点下滑了 (应该说之前的版本都是各语言母语者贡献过)

根据文档处理过,有没有具体的地方?

@CodFrm CodFrm marked this pull request as ready for review July 2, 2026 05:55
@CodFrm CodFrm requested review from Copilot and cyfung1031 July 2, 2026 06:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@CodFrm CodFrm changed the base branch from release/v1.4-agent to main July 2, 2026 06:24
@CodFrm

CodFrm commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

代码审查(对比 main,本地多代理分区审查)

规模 709 文件(+56,653 / −30,442)。按 git diff main...HEAD 分区并行审查,外加合并检查。

合并 main 检查:通过

  • GitHub 状态 MERGEABLE / CLEAN;git merge-tree 干跑零冲突。
  • main 领先合并基仅 2 个非源码提交(issue 模板 + validate:yaml 脚本),与本 PR 源码无重叠;package.json 两侧改动区域不相交,合并后同时保留双方(main 的 validate:yaml + new-ui 的 Arco 移除)。合入不会产生冲突或语义丢失。

需修复(1 项,已在本地完成修复 + 回归测试,通过 typecheck/lint/测试,待提交)

日志「删除/清空」永远抛错,成功提示不触发 + 产生未处理的 Promise rejection

LogClient.deleteLogs / clearLogs 使用 doThrow,但服务端处理器返回 void:

deleteLogs(ids: number[]): Promise<void> {
return this.doThrow("deleteLogs", ids);
}
clearLogs(): Promise<void> {
return this.doThrow("clearLogs");
}

doThrow 对任何 falsy 返回值一律抛错:

async doThrow<T = any>(action: string, params?: any): Promise<T> {
const ret = await sendMessage<T>(this.msgSender, `${this.prefix}${action}`, params);
if (!ret) {
throw new Error(`doThrow: ${this.prefix}${action}`);
}

DB 删除/清空其实已在 SW 端成功,但客户端随后抛错;调用处 void deleteLogs(...).then(...).catch(),导致成功 toast 永不显示并每次产生未处理 rejection:

if (!ids.length) return;
void deleteLogs(ids).then(() => notify.success(t("logs:delete_completed")));
};
const handleClear = () => {
void clearLogs().then(() => notify.success(t("logs:clear_completed")));
};

修法:两个 void 方法改用 do(与本 PR 中 getDefaultModelId 因同样「返回值可为空」原因从 doThrowdo 一致)。

建议关注(低优先,非阻断)

  • ScriptList 列宽自定义功能缺失:旧版支持列宽 auto/隐藏/自定义并持久化到 systemConfig,新表格未实现,script_list_column_width 配置键已成孤儿。是否补回请自行决定。
  • transferSyncToLocal 未复用 version 守卫_get 迁移 sync→local 时存在极窄的并发写覆盖窗口,下次 SystemConfigChange 广播会自愈(置信度低)。
    private async transferSyncToLocal<T>(
    key: SystemConfigKey,
    defaultValue: WithAsyncValue<Exclude<T, undefined>>
    ): Promise<T> {
    const syncVal = await this.syncStorage.get(key);
    if (syncVal === undefined) {
    const entry = this.cacheEntry(key);
    entry.hasValue = true;
    entry.value = undefined;
    return this.resolveDefault<T>(defaultValue);
    }
    // 迁移到 local storage 并从 sync 中删除
    await this.syncStorage.remove(key); // 先删除
    await this.localStorage.set(key, syncVal); // 删除成功后储回本地
    const entry = this.cacheEntry(key);
    entry.hasValue = true;
    entry.value = syncVal;
    return syncVal as T;
    }
  • 两处 as any(已在本地收紧:改为 src/types/main.d.ts 全局类型声明,去掉强转)
    // Chrome 专有:取 FileSystemFileHandle 以支持本地文件监听;Firefox/Safari 无此 API,回退 getAsFile
    const h = await (it as any).getAsFileSystemHandle().catch(() => null);
    if (h && h.kind === "file") handle = h as FileSystemFileHandle;
    try {
    const handles: FileSystemFileHandle[] = await (window as any).showOpenFilePicker({ multiple: true, types });
    return await Promise.all(handles.map(async (handle) => ({ file: await handle.getFile(), handle })));
  • manifest.json 末尾缺换行(JSON 合法,.json 不在 prettier glob 内,不影响 CI):
    ]
    }
    ]
    }

已复核干净

  • 业务逻辑无回归:content / offscreen / sandbox / agent 改动为等价 as 断言或真 bug 修复(cron i18n 命名空间修正、offscreen findInfo 空安全、tool-call 状态持久化修复)。
  • UI 功能对账:ScriptList / ScriptEditor / popup / install / confirm 五页逐动作核对服务调用,忠实移植,除列宽外无功能丢失(confirm 页 wildcard 门控收紧为有意改进,非回归)。
  • 工程规范 6 项全部干净as any/@ts-ignore/吞异常/死代码、i18n defaultValue/tk 包装器、裸色值 className@radix-ui/* 单包/sonner toast/forwardRef
  • 构建/依赖:移除依赖(arco、dayjs、react-icons 等)全仓库零引用;rspack / postcss / tailwind v4 / eslint 规则 / vitest 分组接线一致。

🤖 Generated with Claude Code

CodFrm added 2 commits July 2, 2026 14:54
LogClient.deleteLogs/clearLogs 服务端返回 void,doThrow 对空返回值一律抛错,
导致删除/清空虽已成功但客户端抛错、成功提示不显示且产生未处理 rejection。
改用 do;补 LogClient 经消息通道的端到端回归测试。
在 src/types/main.d.ts 声明 Window.showOpenFilePicker 与
DataTransferItem.getAsFileSystemHandle,去掉调用处两处 as any 强转。
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.

3 participants