From b76ead3fe80a6159fdbfcc9b82c7c6318be68e7f Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Thu, 12 Mar 2026 16:10:52 +0800 Subject: refactor(desktop): rework default server initialization and connection handling (#16965) --- packages/desktop/src/bindings.ts | 1 - packages/desktop/src/index.tsx | 102 +++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 59 deletions(-) (limited to 'packages/desktop/src') diff --git a/packages/desktop/src/bindings.ts b/packages/desktop/src/bindings.ts index 80548173e..d434d3b35 100644 --- a/packages/desktop/src/bindings.ts +++ b/packages/desktop/src/bindings.ts @@ -38,7 +38,6 @@ export type ServerReadyData = { url: string, username: string | null, password: string | null, - is_sidecar: boolean, }; export type SqliteMigrationProgress = { type: "InProgress"; value: number } | { type: "Done" }; diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 9afabe918..65149f34b 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -9,7 +9,6 @@ import { ServerConnection, useCommand, } from "@opencode-ai/app" -import { Splash } from "@opencode-ai/ui/logo" import type { AsyncStorage } from "@solid-primitives/storage" import { getCurrentWindow } from "@tauri-apps/api/window" import { readImage } from "@tauri-apps/plugin-clipboard-manager" @@ -22,7 +21,7 @@ import { relaunch } from "@tauri-apps/plugin-process" import { open as shellOpen } from "@tauri-apps/plugin-shell" import { Store } from "@tauri-apps/plugin-store" import { check, type Update } from "@tauri-apps/plugin-updater" -import { createResource, type JSX, onCleanup, onMount, Show } from "solid-js" +import { createResource, onCleanup, onMount, Show } from "solid-js" import { render } from "solid-js/web" import pkg from "../package.json" import { initI18n, t } from "./i18n" @@ -30,7 +29,7 @@ import { UPDATER_ENABLED } from "./updater" import { webviewZoom } from "./webview-zoom" import "./styles.css" import { Channel } from "@tauri-apps/api/core" -import { commands, ServerReadyData, type InitStep } from "./bindings" +import { commands, type InitStep } from "./bindings" import { createMenu } from "./menu" const root = document.getElementById("root") @@ -348,12 +347,13 @@ const createPlatform = (): Platform => { await commands.setWslConfig({ enabled }) }, - getDefaultServerUrl: async () => { - const result = await commands.getDefaultServerUrl().catch(() => null) - return result + getDefaultServer: async () => { + const url = await commands.getDefaultServerUrl().catch(() => null) + if (!url) return null + return ServerConnection.Key.make(url) }, - setDefaultServerUrl: async (url: string | null) => { + setDefaultServer: async (url: string | null) => { await commands.setDefaultServerUrl(url) }, @@ -412,12 +412,33 @@ void listenForDeepLinks() render(() => { const platform = createPlatform() + // Fetch sidecar credentials from Rust (available immediately, before health check) + const [sidecar] = createResource(() => commands.awaitInitialization(new Channel() as any)) + const [defaultServer] = createResource(() => - platform.getDefaultServerUrl?.().then((url) => { + platform.getDefaultServer?.().then((url) => { if (url) return ServerConnection.key({ type: "http", http: { url } }) }), ) + // Build the sidecar server connection once credentials arrive + const servers = () => { + const data = sidecar() + if (!data) return [] + const http = { + url: data.url, + username: data.username ?? undefined, + password: data.password ?? undefined, + } + const server: ServerConnection.Sidecar = { + displayName: t("desktop.server.local"), + type: "sidecar", + variant: "base", + http, + } + return [server] as ServerConnection.Any[] + } + function handleClick(e: MouseEvent) { const link = (e.target as HTMLElement).closest("a.external-link") as HTMLAnchorElement | null if (link?.href) { @@ -426,6 +447,12 @@ render(() => { } } + function Inner() { + const cmd = useCommand() + menuTrigger = (id) => cmd.trigger(id) + return null + } + onMount(() => { document.addEventListener("click", handleClick) onCleanup(() => { @@ -436,60 +463,19 @@ render(() => { return ( - - {(data) => { - const http = { - url: data.url, - username: data.username ?? undefined, - password: data.password ?? undefined, - } - const server: ServerConnection.Any = data.is_sidecar - ? { - displayName: t("desktop.server.local"), - type: "sidecar", - variant: "base", - http, - } - : { type: "http", http } - - function Inner() { - const cmd = useCommand() - - menuTrigger = (id) => cmd.trigger(id) - - return null - } - + + {(_) => { return ( - - - - - + + + ) }} - + ) }, root!) - -// Gate component that waits for the server to be ready -function ServerGate(props: { children: (data: ServerReadyData) => JSX.Element }) { - const [serverData] = createResource(() => commands.awaitInitialization(new Channel() as any)) - if (serverData.state === "errored") throw serverData.error - - return ( - - -
-
- } - > - {(data) => props.children(data())} -
- ) -} -- cgit v1.2.3