From caf7060ec571039102acd7b4fd73008fdecbe8a9 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sun, 20 Sep 2026 16:55:12 +0900 Subject: feat(workspaces): archive option + archived-workspaces view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consume the backend's archive contract (feature/archive-workspaces): - adapter/http: archive(id)/unarchive(id) (PUT/DELETE /workspaces/:id/archive); list(archived?) passes the ?archived= query - logic/view-model: pure applyArchived(list, id, archived) - store.svelte: setArchived(id, archived) (optimistic + revert-on-error + reconciling refresh); archivedList + refreshArchived() for the archived view - ui/TileActionBar: new Archive action (the right-click→select action bar) - ui/HomeHeader: new Archived button opens the archived view - ui/ArchivedWorkspaces (new): modal listing archived workspaces with Unarchive + View (navigates to /) - ui/WorkspacesHome: wire the Archive action + the Archived modal - .dispatch/wire.reference.md + backend-handoff.md: record the contract delta --- .../workspaces/ui/ArchivedWorkspaces.svelte | 119 +++++++++++++++++++++ src/features/workspaces/ui/HomeHeader.svelte | 19 ++++ src/features/workspaces/ui/HomeHeader.test.ts | 1 + src/features/workspaces/ui/HomeTileGrid.test.ts | 1 + src/features/workspaces/ui/TileActionBar.svelte | 4 + src/features/workspaces/ui/TileActionBar.test.ts | 5 + .../workspaces/ui/WorkspaceDetails.test.ts | 1 + src/features/workspaces/ui/WorkspaceTile.test.ts | 1 + src/features/workspaces/ui/WorkspacesHome.svelte | 22 ++++ src/features/workspaces/ui/WorkspacesHome.test.ts | 1 + 10 files changed, 174 insertions(+) create mode 100644 src/features/workspaces/ui/ArchivedWorkspaces.svelte (limited to 'src/features/workspaces/ui') diff --git a/src/features/workspaces/ui/ArchivedWorkspaces.svelte b/src/features/workspaces/ui/ArchivedWorkspaces.svelte new file mode 100644 index 0000000..584fd68 --- /dev/null +++ b/src/features/workspaces/ui/ArchivedWorkspaces.svelte @@ -0,0 +1,119 @@ + + + diff --git a/src/features/workspaces/ui/HomeHeader.svelte b/src/features/workspaces/ui/HomeHeader.svelte index fb0be0a..9d26306 100644 --- a/src/features/workspaces/ui/HomeHeader.svelte +++ b/src/features/workspaces/ui/HomeHeader.svelte @@ -11,6 +11,7 @@ onCreate, onOpenPlugins, onSort, + onOpenArchived, }: { /** Tall geometry: the controls collapse to compact icon buttons and the * new-workspace popover becomes a bottom sheet. */ @@ -24,6 +25,8 @@ onCreate: (slug: string) => Promise; onOpenPlugins: () => void; onSort: () => void; + /** Open the archived-workspaces view. */ + onOpenArchived: () => void; } = $props(); // ── New workspace popover (today's inline form logic, preserved) ────────── @@ -119,6 +122,22 @@ {/if} + + + diff --git a/src/features/workspaces/ui/HomeHeader.test.ts b/src/features/workspaces/ui/HomeHeader.test.ts index b4ef6c4..40b060f 100644 --- a/src/features/workspaces/ui/HomeHeader.test.ts +++ b/src/features/workspaces/ui/HomeHeader.test.ts @@ -8,6 +8,7 @@ function props() { onCreate: vi.fn(async (_slug: string): Promise<{ ok: true }> => ({ ok: true })), onOpenPlugins: vi.fn(), onSort: vi.fn(), + onOpenArchived: vi.fn(), }; } diff --git a/src/features/workspaces/ui/HomeTileGrid.test.ts b/src/features/workspaces/ui/HomeTileGrid.test.ts index d70c673..a8365d5 100644 --- a/src/features/workspaces/ui/HomeTileGrid.test.ts +++ b/src/features/workspaces/ui/HomeTileGrid.test.ts @@ -14,6 +14,7 @@ function ws(overrides: Partial = {}): WorkspaceEntry { defaultCwd: null, defaultComputerId: null, starred: false, + archived: false, createdAt: 1, lastActivityAt: 2, conversationCount: 1, diff --git a/src/features/workspaces/ui/TileActionBar.svelte b/src/features/workspaces/ui/TileActionBar.svelte index 0d8bef5..ffb8f1d 100644 --- a/src/features/workspaces/ui/TileActionBar.svelte +++ b/src/features/workspaces/ui/TileActionBar.svelte @@ -11,6 +11,7 @@ onToggleStar, onDetails, onPlugins, + onArchive, onDelete, onClose, }: { @@ -24,6 +25,8 @@ /** The details flyout (default cwd + default computer). */ onDetails: () => void; onPlugins: () => void; + /** Archive the workspace (hide from the home grid; reversible). */ + onArchive: () => void; onDelete: () => void; onClose: () => void; } = $props(); @@ -53,6 +56,7 @@ {#if withPlugins} {/if} +