diff options
| author | adamelmore <[email protected]> | 2026-01-26 06:38:20 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-26 08:15:00 -0600 |
| commit | 0d651eab3b1c3ce8b55fe5d70f1e348c4b9753df (patch) | |
| tree | 05981459091af3d132f4c03f955d315899a34afb | |
| parent | 0edd304f4219da30c37e58eea0165ca0d675ac4c (diff) | |
| download | opencode-0d651eab3b1c3ce8b55fe5d70f1e348c4b9753df.tar.gz opencode-0d651eab3b1c3ce8b55fe5d70f1e348c4b9753df.zip | |
feat(app): default servers on web
| -rw-r--r-- | packages/app/src/app.tsx | 13 | ||||
| -rw-r--r-- | packages/app/src/components/dialog-select-server.tsx | 6 | ||||
| -rw-r--r-- | packages/app/src/components/status-popover.tsx | 14 | ||||
| -rw-r--r-- | packages/app/src/context/platform.tsx | 8 | ||||
| -rw-r--r-- | packages/app/src/entry.tsx | 22 |
5 files changed, 52 insertions, 11 deletions
diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index d5009c8d1..6b9f887fa 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -14,7 +14,7 @@ import { GlobalSyncProvider } from "@/context/global-sync" import { PermissionProvider } from "@/context/permission" import { LayoutProvider } from "@/context/layout" import { GlobalSDKProvider } from "@/context/global-sdk" -import { ServerProvider, useServer } from "@/context/server" +import { normalizeServerUrl, ServerProvider, useServer } from "@/context/server" import { SettingsProvider } from "@/context/settings" import { TerminalProvider } from "@/context/terminal" import { PromptProvider } from "@/context/prompt" @@ -85,8 +85,19 @@ function ServerKey(props: ParentProps) { } export function AppInterface(props: { defaultUrl?: string }) { + const platform = usePlatform() + + const stored = (() => { + if (platform.platform !== "web") return + const result = platform.getDefaultServerUrl?.() + if (result instanceof Promise) return + if (!result) return + return normalizeServerUrl(result) + })() + const defaultServerUrl = () => { if (props.defaultUrl) return props.defaultUrl + if (stored) return stored if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" if (import.meta.env.DEV) return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}` diff --git a/packages/app/src/components/dialog-select-server.tsx b/packages/app/src/components/dialog-select-server.tsx index 2206e4a48..774ad51cc 100644 --- a/packages/app/src/components/dialog-select-server.tsx +++ b/packages/app/src/components/dialog-select-server.tsx @@ -155,7 +155,7 @@ export function DialogSelectServer() { }, { initialValue: null }, ) - const isDesktop = platform.platform === "desktop" + const canDefault = createMemo(() => !!platform.getDefaultServerUrl && !!platform.setDefaultServerUrl) const looksComplete = (value: string) => { const normalized = normalizeServerUrl(value) @@ -505,7 +505,7 @@ export function DialogSelectServer() { > <DropdownMenu.ItemLabel>{language.t("dialog.server.menu.edit")}</DropdownMenu.ItemLabel> </DropdownMenu.Item> - <Show when={isDesktop && defaultUrl() !== i}> + <Show when={canDefault() && defaultUrl() !== i}> <DropdownMenu.Item onSelect={async () => { await platform.setDefaultServerUrl?.(i) @@ -517,7 +517,7 @@ export function DialogSelectServer() { </DropdownMenu.ItemLabel> </DropdownMenu.Item> </Show> - <Show when={isDesktop && defaultUrl() === i}> + <Show when={canDefault() && defaultUrl() === i}> <DropdownMenu.Item onSelect={async () => { await platform.setDefaultServerUrl?.(null) diff --git a/packages/app/src/components/status-popover.tsx b/packages/app/src/components/status-popover.tsx index 3963a54f3..cb45c3689 100644 --- a/packages/app/src/components/status-popover.tsx +++ b/packages/app/src/components/status-popover.tsx @@ -125,13 +125,21 @@ export function StatusPopover() { const [defaultServerUrl, setDefaultServerUrl] = createSignal<string | undefined>() - createEffect(() => { + const refreshDefaultServerUrl = () => { const result = platform.getDefaultServerUrl?.() + if (!result) { + setDefaultServerUrl(undefined) + return + } if (result instanceof Promise) { result.then((url) => setDefaultServerUrl(url ? normalizeServerUrl(url) : undefined)) return } - if (result) setDefaultServerUrl(normalizeServerUrl(result)) + setDefaultServerUrl(normalizeServerUrl(result)) + } + + createEffect(() => { + refreshDefaultServerUrl() }) return ( @@ -294,7 +302,7 @@ export function StatusPopover() { <Button variant="secondary" class="mt-3 self-start h-8 px-3 py-1.5" - onClick={() => dialog.show(() => <DialogSelectServer />)} + onClick={() => dialog.show(() => <DialogSelectServer />, refreshDefaultServerUrl)} > {language.t("status.popover.action.manageServers")} </Button> diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx index 89056b2c8..b97f70fea 100644 --- a/packages/app/src/context/platform.tsx +++ b/packages/app/src/context/platform.tsx @@ -41,11 +41,11 @@ export type Platform = { /** Fetch override */ fetch?: typeof fetch - /** Get the configured default server URL (desktop only) */ - getDefaultServerUrl?(): Promise<string | null> + /** Get the configured default server URL (platform-specific) */ + getDefaultServerUrl?(): Promise<string | null> | string | null - /** Set the default server URL to use on app startup (desktop only) */ - setDefaultServerUrl?(url: string | null): Promise<void> + /** Set the default server URL to use on app startup (platform-specific) */ + setDefaultServerUrl?(url: string | null): Promise<void> | void /** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */ parseMarkdown?(markdown: string): Promise<string> diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index df8547636..7fe03bb6a 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -6,6 +6,8 @@ import { dict as en } from "@/i18n/en" import { dict as zh } from "@/i18n/zh" import pkg from "../package.json" +const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl" + const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { const locale = (() => { @@ -62,6 +64,26 @@ const platform: Platform = { }) .catch(() => undefined) }, + getDefaultServerUrl: () => { + if (typeof localStorage === "undefined") return null + try { + return localStorage.getItem(DEFAULT_SERVER_URL_KEY) + } catch { + return null + } + }, + setDefaultServerUrl: (url) => { + if (typeof localStorage === "undefined") return + try { + if (url) { + localStorage.setItem(DEFAULT_SERVER_URL_KEY, url) + return + } + localStorage.removeItem(DEFAULT_SERVER_URL_KEY) + } catch { + return + } + }, } render( |
