feat(workspace): 模式按钮双击收展侧栏
CI / typecheck + test + build (windows) (push) Waiting to run

图标栏的「终端工作区 / SSH 工作区」按钮新增双击手势:双击当前工作区
按钮展开/收起侧栏;单击(含双击另一个按钮)只切换工作区,侧栏不动。

判定逻辑抽成零 import 纯模块 modeRailGesture.ts,用浏览器原生
MouseEvent.detail 连击计数识别手势——detail=2 到达时 store 已被
第一击更新,故在 detail=1 时把「手势前模式」存入 ref 再比对。

新增 tests/mode-rail-gesture.mjs 表驱动测试(10 例),测试数 35→36。
This commit is contained in:
Bill committed 2026-10-20 23:59:28 +08:00
1 parent eac4704e9e
commit 7bccd5303a
6 files changed
+321 -9

No files matched your search

+2 -2
View File
@@ -7,10 +7,10 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。
- 开发:`npm run dev`(主进程改动不热重建,需重启)
- dev 实例使用独立用户数据目录 `%APPDATA%\OpenTerminal-dev` 与独立单实例锁(`src/main/index.ts` 顶部 `!app.isPackaged` 分支),窗口标题带 `(dev)`:**可与已安装的正式版同时运行,互不干扰**,也不会把测试设置/会话写进真实配置
- 类型检查:`npm run typecheck`(tsconfig.node.json + tsconfig.web.json;只看渲染层可单跑 `npx tsc --noEmit -p tsconfig.web.json`)
- 测试:`npm test`(**npm 生命周期先自动跑 `pretest` 做类型检查**,再 `node tests/build-bundles.cjs` 重建 esbuild bundle,然后依次跑可离线运行的 35 个测试:ssh-loopback、commands-store、connections-store、settings-store、local-path-grants、lock-store、lock-controller、lock-shortcuts、reserved-accelerators、terminal-title、ipc-guard、updater-fallback、log-sanitizer、app-log、sftp-timeout、hl-split-smoke、hl-rules、redos-probes、rule-validation、redos-validator、perf-diagnostics、zmodem-e2e、ssh-session-e2e、sysinfo-e2e、terminal-cwd、terminal-links、broadcast-store、write-batcher、refit-throttle、semantic-theme、theme-contrast、css-theme-vars、ot-var-names、font-stack、link-rules;真实服务器测试需 JD_* 凭据,不在此列)。其中渲染层纯函数测试(semantic-theme、theme-contrast、ot-var-names、font-stack、write-batcher、refit-throttle、perf-diagnostics、redos-probes、rule-validation、broadcast-store、terminal-cwd、terminal-links、terminal-title、hl-split-smoke、hl-rules、link-rules 等)用 Node 22.18+ 的原生 TS 类型剥离**直接 import `.ts` 源文件**(不经 esbuild bundle),Node 20/22.17 以下会 `ERR_UNKNOWN_FILE_EXTENSION`
- 测试:`npm test`(**npm 生命周期先自动跑 `pretest` 做类型检查**,再 `node tests/build-bundles.cjs` 重建 esbuild bundle,然后依次跑可离线运行的 36 个测试:ssh-loopback、commands-store、connections-store、settings-store、local-path-grants、lock-store、lock-controller、lock-shortcuts、reserved-accelerators、terminal-title、ipc-guard、updater-fallback、log-sanitizer、app-log、sftp-timeout、hl-split-smoke、hl-rules、redos-probes、rule-validation、redos-validator、perf-diagnostics、zmodem-e2e、ssh-session-e2e、sysinfo-e2e、terminal-cwd、terminal-links、broadcast-store、write-batcher、refit-throttle、semantic-theme、theme-contrast、css-theme-vars、ot-var-names、font-stack、link-rules、mode-rail-gesture;真实服务器测试需 JD_* 凭据,不在此列)。其中渲染层纯函数测试(semantic-theme、theme-contrast、ot-var-names、font-stack、write-batcher、refit-throttle、perf-diagnostics、redos-probes、rule-validation、broadcast-store、terminal-cwd、terminal-links、terminal-title、hl-split-smoke、hl-rules、link-rules、mode-rail-gesture 等)用 Node 22.18+ 的原生 TS 类型剥离**直接 import `.ts` 源文件**(不经 esbuild bundle),Node 20/22.17 以下会 `ERR_UNKNOWN_FILE_EXTENSION`
- 依赖分类规则:**只有 `src/main/`/`src/preload/` 实际 import 的包才能进 `dependencies`**(node-pty/ssh2/zmodem.js/font-list/electron-updater);纯渲染层依赖一律 devDependencies(Vite 全量打包进 out/renderer,`externalizeDepsPlugin` 不作用渲染层)——这条让 asar 从 98MB 瘦到 8.1MB,加新依赖时别放错边
- 下载量统计:`node scripts/download-stats.cjs`(Gitea + GitHub release 资产的 download_count 汇总;GitHub 优先直连、失败自动回退 `HTTPS_PROXY`/本地 7897;更新通道无计数接口不计入)
- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 35 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;`electron-vite build` 之后、electron-builder 之前会跑 `node tests/worker-artifact.mjs`——真实加载 `out/main/redosProbeWorker-*.js` 并回包,防止 `?nodeWorker` 产物静默丢失;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(exe + latest.yml + blockmap)
- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 36 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;`electron-vite build` 之后、electron-builder 之前会跑 `node tests/worker-artifact.mjs`——真实加载 `out/main/redosProbeWorker-*.js` 并回包,防止 `?nodeWorker` 产物静默丢失;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(exe + latest.yml + blockmap)
- GitHub Actions:`.github/workflows/ci.yml` 在 windows-latest + Node 22 上跑 `npm ci` / `npm test`(含 pretest typecheck)/ `npm run build`,只做验证,不打包安装器、不发布
- 国内网络需镜像:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/ npm run dist`
- 依赖一致性闸门:`predist` 开头跑 `node scripts/verify-deps.cjs`(逐条比对 `node_modules` 与 `package-lock.json` 的版本,跨平台 optional 依赖缺失跳过;不一致就 exit 1)——`npm install --package-lock-only` **只重算 lockfile、不碰 node_modules**(本版 npm 还会把 `node_modules/.package-lock.json` 一并重写成理想树,制造「已经装好了」的假象),所以**改动依赖版本后必须真实 `npm install` 或 `npm ci` 再构建**,别指望 lockfile 对齐就等于树里换了包;v1.0.21 的中文输入法回归正是这个坑(`@xterm/xterm` 锁 6.1.0-beta.304,树里还是 6.0.0,打进去的是旧代码)