diff --git a/apps/desktop/app/(app)/settings/page.tsx b/apps/desktop/app/(app)/settings/page.tsx index 71e3cc53..80239289 100644 --- a/apps/desktop/app/(app)/settings/page.tsx +++ b/apps/desktop/app/(app)/settings/page.tsx @@ -9,6 +9,7 @@ import { CardTitle, } from "@ui/components/card" import { Button } from "@ui/components/button" +import { cn } from "@lib/utils" import Link from "next/link" import { useRouter } from "next/navigation" import { useCallback, useEffect, useState } from "react" @@ -38,10 +39,14 @@ import { disconnectDesktopTool, type DesktopToolId, type DesktopToolPreview, - type DesktopToolStatus, previewConnectDesktopTool, previewDisconnectDesktopTool, } from "@/lib/tools" +import { + sortDesktopToolCards, + toDesktopToolCard, + type DesktopToolCard, +} from "@/lib/tool-catalog" type AppInfo = { name: string @@ -62,7 +67,7 @@ export default function SettingsPage() { const [smfsBusy, setSmfsBusy] = useState(null) const [smfsLogs, setSmfsLogs] = useState(null) const [smfsProfile, setSmfsProfile] = useState(null) - const [tools, setTools] = useState([]) + const [tools, setTools] = useState([]) const [toolsError, setToolsError] = useState(null) const [toolsBusy, setToolsBusy] = useState(null) const [toolPreview, setToolPreview] = useState( @@ -81,7 +86,8 @@ export default function SettingsPage() { const refreshTools = useCallback(async () => { setToolsError(null) try { - setTools(await detectDesktopTools()) + const statuses = await detectDesktopTools() + setTools(sortDesktopToolCards(statuses.map(toDesktopToolCard))) } catch (err) { setToolsError(formatError(err, "Could not detect tools")) } @@ -474,54 +480,17 @@ export default function SettingsPage() { Refresh -
+
{tools.map((tool) => ( -
-
-
-
-

{tool.name}

- - {tool.connected - ? "Connected" - : tool.detected - ? "Detected" - : "Not detected"} - -
-

- {tool.detail} -

-

- {tool.configPath} -

-
-
- - -
-
-
+ tool={tool} + busy={toolsBusy !== null} + onPreviewConnect={() => previewToolAction(tool.id, "connect")} + onPreviewDisconnect={() => + previewToolAction(tool.id, "disconnect") + } + /> ))}
{toolsError ? ( @@ -600,6 +569,82 @@ const SHORTCUT_OPTIONS = [ { label: "⌘ ⌥ M", accelerator: "CommandOrControl+Option+M" }, ] as const +function SettingsToolCard({ + tool, + busy, + onPreviewConnect, + onPreviewDisconnect, +}: { + tool: DesktopToolCard + busy: boolean + onPreviewConnect: () => void + onPreviewDisconnect: () => void +}) { + const Icon = tool.icon + return ( +
+ + + + + + +

{tool.name}

+

+ {tool.description} +

+
+

+ {tool.configPath} +

+

{tool.detail}

+
+
+ + +
+
+ ) +} + +function SettingsToolStatusPill({ tool }: { tool: DesktopToolCard }) { + if (tool.connected) { + return ( + + Connected + + ) + } + return ( + + {tool.detected ? "Detected" : "Not detected"} + + ) +} + function Row({ label, value }: { label: string; value: string }) { return (
diff --git a/apps/desktop/app/onboarding/page.tsx b/apps/desktop/app/onboarding/page.tsx index d1c464a0..8364fb7d 100644 --- a/apps/desktop/app/onboarding/page.tsx +++ b/apps/desktop/app/onboarding/page.tsx @@ -502,27 +502,25 @@ function ToolCard({ onPreview: () => void }) { const Icon = tool.icon + const canPreview = !busy && !tool.connected return ( -
-
-
- - - -
-

{tool.name}

-

{toolStatusLabel(tool)}

-
-
- {tool.connected ? ( - - - Active - - ) : null} -
-

- {tool.tagline} + -

+ + + ) +} + +function ToolStatusPill({ tool }: { tool: DesktopToolCard }) { + if (tool.connected) { + return ( + + Connected + + ) + } + return ( + + {tool.detected ? "Detected" : "Not detected"} + ) } @@ -775,12 +783,6 @@ function NovaBackground() { ) } -function toolStatusLabel(tool: DesktopToolCard) { - if (tool.connected) return "Connected" - if (tool.detected) return "Detected" - return "Not detected" -} - function formatSmfsState(state?: SmfsStatus["state"]) { switch (state) { case "degraded":