From b49d6dddfb5e4ad9442407bece6bfd28702495f8 Mon Sep 17 00:00:00 2001
From: Samuel K
Date: Thu, 4 Jun 2026 17:43:25 -0500
Subject: [PATCH] fix(desktop): open provider overlay sheet from command
palette
Route /providers/:id to ProvidersPage with an auto-opened ProviderSheet
so Cmd+K navigation matches card-click behavior instead of loading a
separate full-page view. Removes the now-redundant ProviderDetailPage.
---
desktop/src/renderer/src/App.svelte | 3 +-
.../components/provider/ProviderCard.svelte | 11 +-
.../src/pages/ProviderDetailPage.svelte | 431 ------------------
.../renderer/src/pages/ProvidersPage.svelte | 30 +-
4 files changed, 35 insertions(+), 440 deletions(-)
delete mode 100644 desktop/src/renderer/src/pages/ProviderDetailPage.svelte
diff --git a/desktop/src/renderer/src/App.svelte b/desktop/src/renderer/src/App.svelte
index 9d7c7f363..043b9439c 100644
--- a/desktop/src/renderer/src/App.svelte
+++ b/desktop/src/renderer/src/App.svelte
@@ -28,7 +28,6 @@ import WorkspacesPage from "./pages/WorkspacesPage.svelte"
import WorkspaceDetailPage from "./pages/WorkspaceDetailPage.svelte"
import ProvidersPage from "./pages/ProvidersPage.svelte"
import ProviderAddPage from "./pages/ProviderAddPage.svelte"
-import ProviderDetailPage from "./pages/ProviderDetailPage.svelte"
import MachinesPage from "./pages/MachinesPage.svelte"
import MachineDetailPage from "./pages/MachineDetailPage.svelte"
import ContextsPage from "./pages/ContextsPage.svelte"
@@ -44,7 +43,7 @@ const routes = {
"/workspaces/:id": WorkspaceDetailPage,
"/providers": ProvidersPage,
"/providers/add": ProviderAddPage,
- "/providers/:id": ProviderDetailPage,
+ "/providers/:id": ProvidersPage,
"/machines": MachinesPage,
"/machines/:id": MachineDetailPage,
"/contexts": ContextsPage,
diff --git a/desktop/src/renderer/src/lib/components/provider/ProviderCard.svelte b/desktop/src/renderer/src/lib/components/provider/ProviderCard.svelte
index b2828fabc..a21ebb61b 100644
--- a/desktop/src/renderer/src/lib/components/provider/ProviderCard.svelte
+++ b/desktop/src/renderer/src/lib/components/provider/ProviderCard.svelte
@@ -2,12 +2,13 @@
import { badgeVariants } from "$lib/components/ui/badge/index.js"
import { Star } from "@lucide/svelte"
import ProviderIcon from "./ProviderIcon.svelte"
-import ProviderSheet from "./ProviderSheet.svelte"
import { providerVersions } from "$lib/stores/providerVersions.js"
import type { Provider } from "$lib/types/index.js"
-let { provider }: { provider: Provider } = $props()
-let sheetOpen = $state(false)
+let {
+ provider,
+ onopen,
+}: { provider: Provider; onopen?: () => void } = $props()
function sourceDisplay(p: Provider): string {
if (p.source?.github) return p.source.github
@@ -20,7 +21,7 @@ function sourceDisplay(p: Provider): string {
(sheetOpen = true)}
+ onclick={() => onopen?.()}
>
{#if $providerVersions.updates[provider.name]?.updateAvailable}
{sourceDisplay(provider)}
{/if}
-
-
diff --git a/desktop/src/renderer/src/pages/ProviderDetailPage.svelte b/desktop/src/renderer/src/pages/ProviderDetailPage.svelte
deleted file mode 100644
index eb7574f50..000000000
--- a/desktop/src/renderer/src/pages/ProviderDetailPage.svelte
+++ /dev/null
@@ -1,431 +0,0 @@
-
-
-
-
-
goto("/providers")}>
- ← Back
-
-
-
{id}
- {#if $providerVersions.byProvider[id] && !$providerVersions.byProvider[id].unsupported && ($providerVersions.byProvider[id].versions?.length ?? 0) > 0}
- {@const entry = $providerVersions.byProvider[id]}
- {@const currentTag = provider?.version ?? entry.versions.find((v) => v.current)?.tag ?? ""}
-
{
- if (v && v !== currentTag) openVersionSwitch(v)
- }}
- >
-
- {currentTag || "Select version"}
-
-
- {#each entry.versions as v (v.tag)}
-
- {/each}
-
-
- {:else if provider?.version}
-
{provider.version}
- {/if}
- {#if provider?.state?.initialized}
-
initialized
- {/if}
- {#if provider?.isDefault}
-
-
- Default
-
- {/if}
-
-
- {#if provider}
- {#if $providerVersions.updates[id]?.updateAvailable === true}
-
- Update available: {$providerVersions.updates[id].latest}
-
-
- Install update
-
-
-
- {/if}
-
- {#if !isInitialized}
-
- {initializing ? 'Initializing...' : 'Initialize'}
-
- {:else if !provider?.isDefault}
- Set Default
- {/if}
- Update
- { await refreshUpdates(); await loadVersionsFor(id) }}>Check for updates
- (confirmDeleteOpen = true)}>Delete
-
- {/if}
-
- {#if !provider}
-
Provider not found.
- {:else}
- {#if isSetup && !loading && hasUnfilledRequired}
-
-
Configure required options
-
- This provider needs configuration before it can be used.
- Fill in the required fields below and save.
-
-
- {:else if !isInitialized && !loading}
-
-
- Provider not initialized
-
- This provider needs to be initialized before it can create workspaces.
-
- {initializing ? 'Initializing...' : 'Initialize Provider'}
-
-
-
- {/if}
-
- {#if provider.description}
-
{provider.description}
- {/if}
-
-
-
-
-
- {isSetup ? "Configure Provider" : "Options"}
-
-
- {#if loading}
-
- {#each { length: 4 } as _}
-
-
-
-
- {/each}
-
-
- {:else if Object.keys(options).length === 0}
-
No configurable options available.
- {:else}
- {#each Object.entries(groupedOptions) as [group, entries] (group)}
- {#if group}
-
- {group}
-
- {/if}
-
-
- {#each entries as [key, opt] (key)}
-
-
- {opt.displayName ?? opt.name ?? key}
- {#if opt.required}
- *
- {/if}
-
- {#if opt.description}
-
{opt.description}
- {/if}
- {#if opt.enum && opt.enum.length > 0}
-
(optionValues[key] = v)}
- >
-
- {optionValues[key] || "-- Select --"}
-
-
- {#each opt.enum as enumVal}
-
- {/each}
-
-
- {:else}
-
(optionValues[key] = e.currentTarget.value)}
- />
- {/if}
-
- {/each}
-
- {/each}
-
-
-
- {saving ? "Saving..." : "Save"}
-
- {#if isSetup && !hasUnfilledRequired}
- goto("/providers")}>
- Skip
-
- {:else if isDirty}
- { optionValues = { ...initialValues } }}>
- Reset
-
- Unsaved changes
- {/if}
-
- {/if}
-
- {/if}
-
-
-
-
-
-
- {
- switching = true
- try {
- await providerSetVersion(id, targetTag)
- toasts.success(`Switched ${id} to ${targetTag}`)
- await loadVersionsFor(id)
- await refreshUpdates()
- } catch (err) {
- toasts.error(`Failed to switch version: ${extractErrorMessage(err)}`)
- } finally {
- switching = false
- confirmSwitchOpen = false
- }
- }}
-/>
diff --git a/desktop/src/renderer/src/pages/ProvidersPage.svelte b/desktop/src/renderer/src/pages/ProvidersPage.svelte
index edd4193eb..b087234c7 100644
--- a/desktop/src/renderer/src/pages/ProvidersPage.svelte
+++ b/desktop/src/renderer/src/pages/ProvidersPage.svelte
@@ -13,12 +13,27 @@ import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js"
import { Input } from "$lib/components/ui/input/index.js"
import CardSkeleton from "$lib/components/ui/skeleton/CardSkeleton.svelte"
import ProviderCard from "$lib/components/provider/ProviderCard.svelte"
+import ProviderSheet from "$lib/components/provider/ProviderSheet.svelte"
import { providers, providersLoading } from "$lib/stores/providers.js"
import { refreshUpdates } from "$lib/stores/providerVersions.js"
+let { params = {} }: { params?: Record } = $props()
+
let search = $state("")
let sortBy = $state<"name" | "version">("name")
+let activeId = $derived(decodeURIComponent(params.id ?? ""))
+let activeProvider = $derived($providers.find((p) => p.name === activeId))
+let sheetOpen = $derived(activeId !== "" && activeProvider !== undefined)
+
+function openProvider(name: string) {
+ goto(`/providers/${encodeURIComponent(name)}`)
+}
+
+function closeSheet() {
+ if (activeId) goto("/providers")
+}
+
onMount(() => {
refreshUpdates().catch(() => {})
})
@@ -103,8 +118,21 @@ let filtered = $derived.by(() => {
{:else}
{#each filtered as provider (provider.name)}
-
+
openProvider(provider.name)} />
{/each}
{/if}
+
+{#if activeProvider}
+ sheetOpen,
+ (v) => {
+ if (!v) closeSheet()
+ }
+ }
+ ondeleted={closeSheet}
+ />
+{/if}