🤖 feat: show "Archiving..." from every archive entry point while the request is in flight - #4068
Conversation
…request is in flight Archiving a workspace can take tens of seconds server-side (snapshot + worktree removal). The sidebar row already showed an inline "Archiving..." status, but only when the archive was started from that row: the state lived in ProjectSidebar, and the workspace menu bar's archive action kept an isArchiving flag purely as a re-entrancy guard with nothing rendered. Archiving from the header therefore gave no feedback until the workspace disappeared. Lift the pending set into WorkspaceContext (archivingWorkspaceIds), marked inside preflightArchiveWorkspace/archiveWorkspace so it lights up from the moment of the click regardless of caller and clears on success or error. The sidebar reads it from context (local state removed) and the menu bar now renders a matching "Archiving..." status next to the title. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `xhigh` • Cost: `$21.13`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=xhigh costs=21.13 -->
This comment has been minimized.
This comment has been minimized.
|
@codex review |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 351fdfc602
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Ref-count overlapping archive requests per workspace so the first one to settle does not clear the indicator while another is still running, and guard the sidebar keyboard shortcut like the menu bar already does. - Replace the manual useCallback helper with a module-level function (React Compiler handles memoization). - Add a pinned phone story for the archiving header state with a play contract asserting the status and right-side controls stay in the bar. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `xhigh` • Cost: `$21.13`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=xhigh costs=21.13 -->
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
This comment has been minimized.
This comment has been minimized.
- workspaceService flat-reorder mock (#3994) sets getSessionDir on Partial<Config>, which the split Config (#4017) no longer has; the test only needs sessionsDir - ProjectSidebar flat-list mocks (#3994) lack archivingWorkspaceIds (#4068) - MCP prompt snapshot test asserts the cancelSignal argument this PR removed
Summary
Archiving a workspace can take 15 to 25 seconds server-side, and if you started it from the workspace menu bar there was no feedback at all until the row vanished. The archive-in-progress state now lives in
WorkspaceContext, so both the sidebar row and the workspace menu bar show an "Archiving..." status from the moment of the click, whichever surface started it.Background
The sidebar row already rendered an inline "Archiving..." status, but the set driving it was
ProjectSidebar's ownuseState, populated only by the row's archive button.WorkspaceMenuBarkept a separateisArchivingboolean purely as a re-entrancy guard and rendered nothing for it. Archiving from the header (the common path when the workspace is selected) therefore looked like a hang, and a slow archive was indistinguishable from a broken connection.Server-side, the time goes to the archive snapshot (
git format-patchovermerge-base(trunk, HEAD)..HEAD), which is large when the local trunk is far behind its remote. That is a separate inefficiency and is not changed here; this PR only makes the wait visible.Implementation
WorkspaceContextgainsarchivingWorkspaceIds: ReadonlySet<string>. BothpreflightArchiveWorkspaceandarchiveWorkspacewrap their RPC in a small helper that adds the id before the call and removes it infinally, so a rejected request (for example a dropped WebSocket) clears the indicator instead of leaving the row stuck.ProjectSidebarreads the set from context; its local copy and the surroundingtry/finallyare removed (most of that file's diff is the resulting de-indent; view with whitespace ignored).WorkspaceMenuBarreads the same set for its re-entrancy guard and renders arole="status""Archiving..." span with the archive icon next to the title. It isshrink-0beside themin-w-0 truncatetitle, so it stays visible at phone widths.The set is placed in the actions context (alongside selection and drafts) rather than the metadata context: the two consumers already subscribe there, and archive is rare enough that two extra context updates per archive are negligible.
Validation
archiveWorkspaceandpreflightArchiveWorkspaceagainst deferred promises and asserts the id is present only while each is outstanding, including the rejection path.falsefails the second.Risks
Low. UI-only, no IPC or persistence changes. The sidebar row now also enters its archiving presentation during the preflight call (previously only during the archive call itself), which is the intended behaviour and lasts well under a second.
Generated with
xum• Model:anthropic:claude-fable-5-1• Thinking:xhigh• Cost:$21.13