feat(app): default servers on web
This commit is contained in:
@@ -14,7 +14,7 @@ import { GlobalSyncProvider } from "@/context/global-sync"
|
|||||||
import { PermissionProvider } from "@/context/permission"
|
import { PermissionProvider } from "@/context/permission"
|
||||||
import { LayoutProvider } from "@/context/layout"
|
import { LayoutProvider } from "@/context/layout"
|
||||||
import { GlobalSDKProvider } from "@/context/global-sdk"
|
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 { SettingsProvider } from "@/context/settings"
|
||||||
import { TerminalProvider } from "@/context/terminal"
|
import { TerminalProvider } from "@/context/terminal"
|
||||||
import { PromptProvider } from "@/context/prompt"
|
import { PromptProvider } from "@/context/prompt"
|
||||||
@@ -85,8 +85,19 @@ function ServerKey(props: ParentProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function AppInterface(props: { defaultUrl?: string }) {
|
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 = () => {
|
const defaultServerUrl = () => {
|
||||||
if (props.defaultUrl) return props.defaultUrl
|
if (props.defaultUrl) return props.defaultUrl
|
||||||
|
if (stored) return stored
|
||||||
if (location.hostname.includes("opencode.ai")) return "http://localhost:4096"
|
if (location.hostname.includes("opencode.ai")) return "http://localhost:4096"
|
||||||
if (import.meta.env.DEV)
|
if (import.meta.env.DEV)
|
||||||
return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
|
return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export function DialogSelectServer() {
|
|||||||
},
|
},
|
||||||
{ initialValue: null },
|
{ initialValue: null },
|
||||||
)
|
)
|
||||||
const isDesktop = platform.platform === "desktop"
|
const canDefault = createMemo(() => !!platform.getDefaultServerUrl && !!platform.setDefaultServerUrl)
|
||||||
|
|
||||||
const looksComplete = (value: string) => {
|
const looksComplete = (value: string) => {
|
||||||
const normalized = normalizeServerUrl(value)
|
const normalized = normalizeServerUrl(value)
|
||||||
@@ -505,7 +505,7 @@ export function DialogSelectServer() {
|
|||||||
>
|
>
|
||||||
<DropdownMenu.ItemLabel>{language.t("dialog.server.menu.edit")}</DropdownMenu.ItemLabel>
|
<DropdownMenu.ItemLabel>{language.t("dialog.server.menu.edit")}</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<Show when={isDesktop && defaultUrl() !== i}>
|
<Show when={canDefault() && defaultUrl() !== i}>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
onSelect={async () => {
|
onSelect={async () => {
|
||||||
await platform.setDefaultServerUrl?.(i)
|
await platform.setDefaultServerUrl?.(i)
|
||||||
@@ -517,7 +517,7 @@ export function DialogSelectServer() {
|
|||||||
</DropdownMenu.ItemLabel>
|
</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={isDesktop && defaultUrl() === i}>
|
<Show when={canDefault() && defaultUrl() === i}>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
onSelect={async () => {
|
onSelect={async () => {
|
||||||
await platform.setDefaultServerUrl?.(null)
|
await platform.setDefaultServerUrl?.(null)
|
||||||
|
|||||||
@@ -125,13 +125,21 @@ export function StatusPopover() {
|
|||||||
|
|
||||||
const [defaultServerUrl, setDefaultServerUrl] = createSignal<string | undefined>()
|
const [defaultServerUrl, setDefaultServerUrl] = createSignal<string | undefined>()
|
||||||
|
|
||||||
createEffect(() => {
|
const refreshDefaultServerUrl = () => {
|
||||||
const result = platform.getDefaultServerUrl?.()
|
const result = platform.getDefaultServerUrl?.()
|
||||||
|
if (!result) {
|
||||||
|
setDefaultServerUrl(undefined)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (result instanceof Promise) {
|
if (result instanceof Promise) {
|
||||||
result.then((url) => setDefaultServerUrl(url ? normalizeServerUrl(url) : undefined))
|
result.then((url) => setDefaultServerUrl(url ? normalizeServerUrl(url) : undefined))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (result) setDefaultServerUrl(normalizeServerUrl(result))
|
setDefaultServerUrl(normalizeServerUrl(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
refreshDefaultServerUrl()
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -294,7 +302,7 @@ export function StatusPopover() {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="mt-3 self-start h-8 px-3 py-1.5"
|
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")}
|
{language.t("status.popover.action.manageServers")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ export type Platform = {
|
|||||||
/** Fetch override */
|
/** Fetch override */
|
||||||
fetch?: typeof fetch
|
fetch?: typeof fetch
|
||||||
|
|
||||||
/** Get the configured default server URL (desktop only) */
|
/** Get the configured default server URL (platform-specific) */
|
||||||
getDefaultServerUrl?(): Promise<string | null>
|
getDefaultServerUrl?(): Promise<string | null> | string | null
|
||||||
|
|
||||||
/** Set the default server URL to use on app startup (desktop only) */
|
/** Set the default server URL to use on app startup (platform-specific) */
|
||||||
setDefaultServerUrl?(url: string | null): Promise<void>
|
setDefaultServerUrl?(url: string | null): Promise<void> | void
|
||||||
|
|
||||||
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
|
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
|
||||||
parseMarkdown?(markdown: string): Promise<string>
|
parseMarkdown?(markdown: string): Promise<string>
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { dict as en } from "@/i18n/en"
|
|||||||
import { dict as zh } from "@/i18n/zh"
|
import { dict as zh } from "@/i18n/zh"
|
||||||
import pkg from "../package.json"
|
import pkg from "../package.json"
|
||||||
|
|
||||||
|
const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"
|
||||||
|
|
||||||
const root = document.getElementById("root")
|
const root = document.getElementById("root")
|
||||||
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
||||||
const locale = (() => {
|
const locale = (() => {
|
||||||
@@ -62,6 +64,26 @@ const platform: Platform = {
|
|||||||
})
|
})
|
||||||
.catch(() => undefined)
|
.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(
|
render(
|
||||||
|
|||||||
Reference in New Issue
Block a user