diff options
| author | Adam Malczewski <[email protected]> | 2026-06-28 15:29:55 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-28 15:29:55 +0900 |
| commit | ded7cc4ebf872556b4ab16bac81c1b551d8e44da (patch) | |
| tree | 0f5cbed2405f83a819032a551295490b70e31d1d /src/features/workspaces/ui/WorkspaceCard.svelte | |
| parent | 3899ecef48325014a3bb5d6333a7a3e1fc34296a (diff) | |
| parent | 60aa5dc48b6af502f88befd7d1517ab52cf6c60f (diff) | |
| download | dispatch-web-ded7cc4ebf872556b4ab16bac81c1b551d8e44da.tar.gz dispatch-web-ded7cc4ebf872556b4ab16bac81c1b551d8e44da.zip | |
Merge branch 'feature/workspace-star' into predev
# Conflicts:
# backend-handoff.md
# src/features/workspaces/ui/WorkspaceCard.test.ts
Diffstat (limited to 'src/features/workspaces/ui/WorkspaceCard.svelte')
| -rw-r--r-- | src/features/workspaces/ui/WorkspaceCard.svelte | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/features/workspaces/ui/WorkspaceCard.svelte b/src/features/workspaces/ui/WorkspaceCard.svelte index 1825b7d..6de4109 100644 --- a/src/features/workspaces/ui/WorkspaceCard.svelte +++ b/src/features/workspaces/ui/WorkspaceCard.svelte @@ -96,6 +96,28 @@ if (!result.ok) computerError = result.error; } + // ── Star (concurrency priority) ────────────────────────────────────────────── + let savingStar = $state(false); + let starError = $state<string | null>(null); + + async function toggleStar(): Promise<void> { + if (savingStar) return; + savingStar = true; + starError = null; + try { + // Optimistic: the store flips `starred` immediately and re-sorts; revert + // on error is handled there. We read `ws.starred` for the target value. + const result = await store.setStarred(ws.id, !ws.starred); + if (!result.ok) starError = result.error; + } catch (err) { + // A throw (e.g. a rejected effect) — surface it; the store already + // reverted the optimistic flip if it got far enough to apply it. + starError = err instanceof Error ? err.message : "Star toggle failed"; + } finally { + savingStar = false; + } + } + // ── Delete ───────────────────────────────────────────────────────────────── let deleting = $state(false); @@ -143,6 +165,25 @@ > {/if} <span class="font-mono text-xs opacity-50">/{ws.id}</span> + <button + type="button" + class="btn btn-ghost btn-xs px-1" + disabled={savingStar} + aria-pressed={ws.starred} + aria-label={ws.starred ? "Unstar workspace" : "Star workspace"} + title={ws.starred + ? "Starred — its agents get concurrency priority. Click to unstar." + : "Star this workspace to give its agents concurrency priority."} + onclick={toggleStar} + > + {#if savingStar} + <span class="loading loading-spinner loading-xs"></span> + {:else if ws.starred} + <span class="text-warning" aria-hidden="true">★</span> + {:else} + <span class="opacity-40" aria-hidden="true">☆</span> + {/if} + </button> <span class="ml-auto text-xs opacity-50"> {ws.conversationCount} {ws.conversationCount === 1 ? "conversation" : "conversations"} @@ -168,6 +209,10 @@ <p class="text-xs text-error">{titleError}</p> {/if} + {#if starError} + <p class="text-xs text-error">{starError}</p> + {/if} + <div class="flex items-center gap-2"> <span class="w-8 shrink-0 text-xs opacity-60">cwd</span> <input |
