Skip to content

feat(ui): tab 横向滚动 + Ctrl+W 关 project + 新 logo (v0.2.1)#110

Merged
ACCSCI merged 13 commits into
masterfrom
feature/v0.2.1-ui-fixes
Jul 2, 2026
Merged

feat(ui): tab 横向滚动 + Ctrl+W 关 project + 新 logo (v0.2.1)#110
ACCSCI merged 13 commits into
masterfrom
feature/v0.2.1-ui-fixes

Conversation

@ACCSCI

@ACCSCI ACCSCI commented Jul 2, 2026

Copy link
Copy Markdown
Owner

概述

v0.2.1 是用户反馈驱动的 UI 修复 + logo 更新小版本。

改动

Tab 横向滚动

当打开的 project tab 超过窗口宽度时,可以横向滚动(mouse wheel / trackpad gesture / 触摸拖动都支持),不再必须关掉一些 tab。滚动条隐藏保持视觉简洁。

  • src/styles/components/tab-bar.cssoverflow-x: auto + 隐藏滚动条
  • src/components/TabBar.tsx:onWheel handler 把 deltaY 映射到 scrollLeft

Ctrl+W 关 project

Ctrl+W(macOS 上 Cmd+W)关闭当前 active project tab,符合主流 IDE 习惯。在 input / textarea / contenteditable 中不触发,避免终端/编辑器打字时被误关。

  • src/components/TabBar.tsx:useEffect 注册全局 keydown listener

新 logo

build/icon.ico 用 ImageMagick 重新生成多尺寸(16/32/48/64/128/256)从新的 logo 设计。源 PNG build/agentdock.png 同时入仓作为参考。electron-builder 自动识别 build/icon.ico,无需改代码。

安装包不打包用户数据

electron-builder.ymlfiles 字段是白名单,本来就不会打用户数据。但显式排除 .agentdock/**data/db.sqlite*global/projects.db* 作为防御,让审计者一眼看清"打包产物里不会有项目数据"。

验证

  • npx electron-vite build 通过
  • npx electron-vite preview 启动后手动确认 tab 滚动 + Ctrl+W 工作
  • electron-builder --win 跑一次,确认 exe 体积没有异常变化、不包含 userData

发布计划

合并后 → bump 0.2.0 → 0.2.1 → tag → release workflow 自动出 AgentDock-Setup-0.2.1.exe

Marco Taylor and others added 12 commits June 30, 2026 21:49
…ain-process refactor

- fix(lifecycle): return backgroundHookPromise=undefined in sync-hook mode
  so the complete event is sent via process.nextTick; previously sync
  hooks never triggered onBackgroundHookComplete, leaving
  createSession.isPending stuck true and the '+' button spinning after
  the session card had already gone active.
- refactor(ui): remove DaemonStatusBar component + styles + testids;
  single-instance architecture has no separate daemon process, so the
  bar was a static 'Running' label with no information value.
- test: drop 4 v2-daemon specs that asserted on the now-removed bar and
  on architecture that no longer exists (status-and-fencing, v2-architecture,
  v2-flow, reconnection).
- test(e2e): add scripts/e2e-bun-start-stepwise.ts that simulates
  bun start → open Copilot-Switch → create session → delete session
  with real UI clicks; includes a regression guard for the
  plus-button-spins bug and uses the inner .session-card class for
  state checks (the testid lives on the wrapper).
- chore: bundle miscellaneous in-progress main-process refactor, new
  e2e specs (agent-e2e-raw, cold-start-race, session-create-progress-
  persistence, etc.), acceptance scripts, screenshots, and minor
  formatting touches across many files.
- port-pool: serialize allocate() through a promise chain and reserve
  picked ports inside the serialized block to prevent two concurrent
  create-session calls from racing past the bind-probe and grabbing the
  same ports.
- ipc/sessions: add null guard for sessionManager in sessions:delete
  (matches the existing guards in sessions:create and sessions:reassignPorts).
- global-settings: route setPortPoolStart/setPortPoolEnd through
  updateSettings with strict 1024..65534/1025..65535 clamps and
  start<end invariant, fixing the 65535→65635 and 1024→1024 edge cases.
- instance-lock: mkdirSync the .agentdock parent directory before
  acquiring the lock, so a fresh userData dir no longer crashes startup
  with ENOENT.
- settings: split handlePortPoolChange (local state) from saveSettings
  (IPC + disk write); the IPC call now fires on input blur instead of
  on every keystroke.
- ipc/db: wrap JSON.parse(s.steps) in try/catch so a corrupted row
  doesn't brick the entire db:projects:list handler.
- package.json: restore the build:daemon script that CI's
  'bun run build:daemon' step still depends on.
Single-instance architecture no longer has a separate daemon process to
build. The 'Build daemon JS' step in .github/workflows/build.yml ran
build:daemon twice (once standalone, once inside dist:win). Both the
script reference and the CI step are removed.
- src/routes/app.$projectId.tsx:22 — change `project?.sessions.find` to
  `project?.sessions?.find`. The original parses as `(project?.sessions).find`,
  which crashes with 'Cannot read properties of undefined (reading find)'
  when useOpenProject inserts a freshly-created project into the React Query
  cache without a `sessions` field.
- src/hooks/useOpenProject.ts:insertOrReplaceProject — normalize the inserted
  project so `sessions` defaults to [] when missing. The row returned by
  `db:projects:create` only has {id, name, path, createdAt}; consumers like
  ProjectWorkspace assume the full ProjectData shape.

Verified with e2e/bun-start-simulation.spec.ts — 'Project loaded (no
Project not found)' step now passes (previously triggered the ErrorBoundary
at app.$projectId.tsx:22).

Also includes:

- AGENTS.md rewritten in Chinese to match the single-instance architecture,
  testing isolation pipeline (CI does NOT run e2e; parallel tests must use
  --user-data-dir + AGENTDOCK_DEV_INSTANCE=1), and the user-agent testing
  approach via .flue/. Old link to docs/新架构.md removed (v2 daemon
  architecture no longer in use).
- Remove obsolete v2-daemon docs: 新架构.md, v1-deprecation.md,
  new-arch-progress.md, main-alignment-audit.md, post-fix-iterations.md,
  sse-race-debug.md.
- .flue/ skeleton (agents/user-agent.ts, app.ts, tools/launch-electron.ts)
  + flue.config.ts — initial scaffolding for user-agent testing. The agent
  successfully runs end-to-end (Claude Sonnet 4.6 via the project's
  Anthropic-compatible gateway) and produced a UX bug report on first run.
  The launcher itself hits a Playwright / Node v24 inspector handshake bug
  tracked separately; user-agent findings were validated against
  e2e/bun-start-simulation.spec.ts instead.
- .gitignore: e2e-report-html/ → e2e/report-html/ (typo: underscore vs slash).
0.2.0 marks the completion of the v2-daemon deprecation arc:
- DaemonStatusBar component removed (UI no longer pretends to track a
  non-existent daemon process)
- Single-instance architecture fully documented in AGENTS.md
- Project DB + global DB isolation (--user-data-dir + AGENTDOCK_DEV_INSTANCE)
  replaces what used to be a shared ~/.agentdock/projects.db
- 6 obsolete v2-daemon design docs removed (新架构.md, v1-deprecation.md,
  new-arch-progress.md, main-alignment-audit.md, post-fix-iterations.md,
  sse-race-debug.md)
- project?.sessions.find optional-chain bug fixed; useOpenProject now
  normalizes inserted projects before writing to the React Query cache

See PR #108 for the full diff.
The @flue/cli and @flue/runtime packages were added to package.json but
bun.lock was not regenerated. CI's 'bun install --frozen-lockfile' step
failed with 'lockfile had changes' — running 'bun install' locally now
to capture the resolved package versions.
The 'Build daemon JS' step ran `bun run build:daemon`, which we removed
in PR #108 because the v2-daemon architecture is gone and there's nothing
to build. The release workflow also had `bun run build:daemon` chained
into the final publish step — same removal.

After this lands, retag v0.2.0 against master HEAD so the release
workflow fires correctly.
…arse

Address review comments from gemini-code-assist on PR #108 (now merged
into master). Four real bugs fixed:

1. port-pool: serialize allocation via a chain, but a thrown error
   (e.g. PortPoolExhaustedError) used to poison the queue forever —
   every subsequent allocate() would reject. Now the queue absorbs the
   rejection while the original error still propagates to the caller.
2. db:projects:list: per-project DB can be null if db:init hasn't run;
   return empty session list instead of crashing the renderer.
3. db:projects:delete: same — guard against null per-project DB.
4. ipc/sessions:steps callback: wrap JSON.parse(row.steps) in try/catch
   to match the defensive parsing in db.ts:322. A corrupted steps blob
   no longer kills the step-update loop.

The 'projectPath is not defined' thread was a false positive — the
variable is declared at the top of sessions:create (line 74). The two
'hardcoded local paths' threads (test scripts) are pre-existing
technical debt out of scope for this PR.
Conflict resolution: kept the HEAD-side fixes (port-pool queue
absorption + sessions.ts defensive JSON.parse) and let the post-#108
master changes (e4ffc60) land alongside.
UI quality-of-life improvements for v0.2.1:

- TabBar: enable horizontal scroll. When the tab strip exceeds the
  window width, the user can now scroll horizontally via trackpad
  gesture, mouse-wheel (deltaY → scrollLeft), or touch drag. Scrollbar
  is hidden for visual cleanliness.

- TabBar: Ctrl+W / Cmd+W closes the active project tab, matching the
  common IDE convention. Skipped when an input/textarea/contenteditable
  has focus so users typing in the terminal or editor aren't surprised.

- build/icon.ico: regenerated multi-size ICO (16/32/48/64/128/256) from
  the new logo design. New agentdock.png is the source raster.
  electron-builder picks up build/icon.ico automatically — no code
  references needed.

- electron-builder.yml: explicit defensive exclusion of user-data paths
  (.agentdock/, data/db.sqlite*, global/projects.db*) in the files
  whitelist. The whitelist was already restrictive enough, but spelling
  these out makes intent obvious to anyone auditing the installer — the
  shipped AgentDock-Setup.exe contains only the app bundle, never
  baked-in user data.
Copilot AI review requested due to automatic review settings July 2, 2026 02:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces horizontal scrolling for the project tab bar, adds a Ctrl+W / Cmd+W keyboard shortcut to close the active tab, and adds defensive exclusions in electron-builder.yml to prevent user data directories from being packaged. The reviewer provided several critical pieces of feedback: first, using a global wildcard like !**/data/** in the electron builder configuration risks excluding required runtime assets, so relative paths should be used instead; second, Ctrl+W / Cmd+W shortcuts in Electron are typically intercepted by the main process and will close the window, requiring IPC handling; third, React's onWheel is passive by default, meaning e.preventDefault() will fail and throw warnings, so a manual non-passive event listener via useRef is recommended; and finally, handleRemoveProject should be wrapped in useCallback and added to the useEffect dependency array to prevent potential stale closures.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread electron-builder.yml Outdated
Comment thread src/components/TabBar.tsx
Comment thread src/components/TabBar.tsx Outdated
Comment thread src/components/TabBar.tsx Outdated
Four issues from gemini-code-assist:

1. electron-builder.yml — replace `**/data/**` style global globs with
   repo-root-relative patterns (`data/**`, `.agentdock/**`, etc.) so we
   don't accidentally exclude runtime resources like `out/renderer/data`
   that may legitimately exist inside bundled deps.

2. Ctrl+W shortcut — Electron's default application menu (notably macOS
   "Close Window") consumes Ctrl/Cmd+W before the renderer's keydown
   fires. Add a before-input-event listener in electron/main/window.ts
   that calls event.preventDefault() for Ctrl/Cmd+W so the renderer
   handler can take over and close the active project tab.

3. TabBar wheel listener — React's onWheel={...} registers a passive
   listener, so e.preventDefault() inside it is silently ignored. Move
   to a ref + useEffect pattern that adds the wheel listener with
   `{ passive: false }` so we can suppress default vertical scroll.

4. TabBar handleRemoveProject — wrap in useCallback with explicit deps
   and add to the Ctrl+W useEffect's dep array, removing the stale
   closure risk flagged by the exhaustive-deps lint rule.
@ACCSCI ACCSCI merged commit d5aa084 into master Jul 2, 2026
1 check passed
@ACCSCI ACCSCI deleted the feature/v0.2.1-ui-fixes branch July 2, 2026 05: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.

2 participants