diff options
| author | Adam <[email protected]> | 2026-03-24 18:36:37 -0500 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-03-24 18:36:37 -0500 |
| commit | a379eb38673aad097e1f178307865ec40a5ac3ea (patch) | |
| tree | 5df060e30638eefb2d95f1d8c1abbd6066922df8 /packages/app/src/components | |
| parent | cbe1337f2401066cf33eb9009b597eafb49123ba (diff) | |
| download | opencode-a379eb38673aad097e1f178307865ec40a5ac3ea.tar.gz opencode-a379eb38673aad097e1f178307865ec40a5ac3ea.zip | |
Revert "fix(app): startup efficiency (#18854)"
This reverts commit 546748a461539ca63e188ee07ab2b143c5ac2c83.
Diffstat (limited to 'packages/app/src/components')
| -rw-r--r-- | packages/app/src/components/dialog-connect-provider.tsx | 50 | ||||
| -rw-r--r-- | packages/app/src/components/settings-general.tsx | 50 | ||||
| -rw-r--r-- | packages/app/src/components/status-popover.tsx | 23 | ||||
| -rw-r--r-- | packages/app/src/components/terminal.tsx | 5 | ||||
| -rw-r--r-- | packages/app/src/components/titlebar.tsx | 2 |
5 files changed, 30 insertions, 100 deletions
diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index e7eaa1fb2..734958dd5 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -1,4 +1,4 @@ -import type { ProviderAuthAuthorization, ProviderAuthMethod } from "@opencode-ai/sdk/v2/client" +import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2/client" import { Button } from "@opencode-ai/ui/button" import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" @@ -9,7 +9,7 @@ import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Spinner } from "@opencode-ai/ui/spinner" import { TextField } from "@opencode-ai/ui/text-field" import { showToast } from "@opencode-ai/ui/toast" -import { createEffect, createMemo, createResource, Match, onCleanup, onMount, Switch } from "solid-js" +import { createMemo, Match, onCleanup, onMount, Switch } from "solid-js" import { createStore, produce } from "solid-js/store" import { Link } from "@/components/link" import { useGlobalSDK } from "@/context/global-sdk" @@ -34,25 +34,15 @@ export function DialogConnectProvider(props: { provider: string }) { }) const provider = createMemo(() => globalSync.data.provider.all.find((x) => x.id === props.provider)!) - const fallback = createMemo<ProviderAuthMethod[]>(() => [ - { - type: "api" as const, - label: language.t("provider.connect.method.apiKey"), - }, - ]) - const [auth] = createResource( - () => props.provider, - async () => { - const cached = globalSync.data.provider_auth[props.provider] - if (cached) return cached - const res = await globalSDK.client.provider.auth() - if (!alive.value) return fallback() - globalSync.set("provider_auth", res.data ?? {}) - return res.data?.[props.provider] ?? fallback() - }, + const methods = createMemo( + () => + globalSync.data.provider_auth[props.provider] ?? [ + { + type: "api", + label: language.t("provider.connect.method.apiKey"), + }, + ], ) - const loading = createMemo(() => auth.loading && !globalSync.data.provider_auth[props.provider]) - const methods = createMemo(() => auth.latest ?? globalSync.data.provider_auth[props.provider] ?? fallback()) const [store, setStore] = createStore({ methodIndex: undefined as undefined | number, authorization: undefined as undefined | ProviderAuthAuthorization, @@ -187,11 +177,7 @@ export function DialogConnectProvider(props: { provider: string }) { index: 0, }) - const prompts = createMemo<NonNullable<ProviderAuthMethod["prompts"]>>(() => { - const value = method() - if (value?.type !== "oauth") return [] - return value.prompts ?? [] - }) + const prompts = createMemo(() => method()?.prompts ?? []) const matches = (prompt: NonNullable<ReturnType<typeof prompts>[number]>, value: Record<string, string>) => { if (!prompt.when) return true const actual = value[prompt.when.key] @@ -310,12 +296,8 @@ export function DialogConnectProvider(props: { provider: string }) { listRef?.onKeyDown(e) } - let auto = false - createEffect(() => { - if (auto) return - if (loading()) return + onMount(() => { if (methods().length === 1) { - auto = true selectMethod(0) } }) @@ -591,14 +573,6 @@ export function DialogConnectProvider(props: { provider: string }) { <div class="px-2.5 pb-10 flex flex-col gap-6"> <div onKeyDown={handleKey} tabIndex={0} autofocus={store.methodIndex === undefined ? true : undefined}> <Switch> - <Match when={loading()}> - <div class="text-14-regular text-text-base"> - <div class="flex items-center gap-x-2"> - <Spinner /> - <span>{language.t("provider.connect.status.inProgress")}</span> - </div> - </div> - </Match> <Match when={store.methodIndex === undefined}> <MethodSelection /> </Match> diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index f4b8198e7..b768bafcc 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -1,41 +1,27 @@ -import { Component, Show, createMemo, createResource, onMount, type JSX } from "solid-js" +import { Component, Show, createMemo, createResource, type JSX } from "solid-js" import { createStore } from "solid-js/store" import { Button } from "@opencode-ai/ui/button" import { Icon } from "@opencode-ai/ui/icon" import { Select } from "@opencode-ai/ui/select" import { Switch } from "@opencode-ai/ui/switch" import { Tooltip } from "@opencode-ai/ui/tooltip" -import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme/context" +import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme" import { showToast } from "@opencode-ai/ui/toast" import { useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" import { useSettings, monoFontFamily } from "@/context/settings" -import { playSoundById, SOUND_OPTIONS } from "@/utils/sound" +import { playSound, SOUND_OPTIONS } from "@/utils/sound" import { Link } from "./link" import { SettingsList } from "./settings-list" let demoSoundState = { cleanup: undefined as (() => void) | undefined, timeout: undefined as NodeJS.Timeout | undefined, - run: 0, -} - -type ThemeOption = { - id: string - name: string -} - -let font: Promise<typeof import("@opencode-ai/ui/font-loader")> | undefined - -function loadFont() { - font ??= import("@opencode-ai/ui/font-loader") - return font } // To prevent audio from overlapping/playing very quickly when navigating the settings menus, // delay the playback by 100ms during quick selection changes and pause existing sounds. const stopDemoSound = () => { - demoSoundState.run += 1 if (demoSoundState.cleanup) { demoSoundState.cleanup() } @@ -43,19 +29,12 @@ const stopDemoSound = () => { demoSoundState.cleanup = undefined } -const playDemoSound = (id: string | undefined) => { +const playDemoSound = (src: string | undefined) => { stopDemoSound() - if (!id) return + if (!src) return - const run = ++demoSoundState.run demoSoundState.timeout = setTimeout(() => { - void playSoundById(id).then((cleanup) => { - if (demoSoundState.run !== run) { - cleanup?.() - return - } - demoSoundState.cleanup = cleanup - }) + demoSoundState.cleanup = playSound(src) }, 100) } @@ -65,10 +44,6 @@ export const SettingsGeneral: Component = () => { const platform = usePlatform() const settings = useSettings() - onMount(() => { - void theme.loadThemes() - }) - const [store, setStore] = createStore({ checking: false, }) @@ -129,7 +104,9 @@ export const SettingsGeneral: Component = () => { .finally(() => setStore("checking", false)) } - const themeOptions = createMemo<ThemeOption[]>(() => theme.ids().map((id) => ({ id, name: theme.name(id) }))) + const themeOptions = createMemo(() => + Object.entries(theme.themes()).map(([id, def]) => ({ id, name: def.name ?? id })), + ) const colorSchemeOptions = createMemo((): { value: ColorScheme; label: string }[] => [ { value: "system", label: language.t("theme.scheme.system") }, @@ -166,7 +143,7 @@ export const SettingsGeneral: Component = () => { ] as const const fontOptionsList = [...fontOptions] - const noneSound = { id: "none", label: "sound.option.none" } as const + const noneSound = { id: "none", label: "sound.option.none", src: undefined } as const const soundOptions = [noneSound, ...SOUND_OPTIONS] const soundSelectProps = ( @@ -181,7 +158,7 @@ export const SettingsGeneral: Component = () => { label: (o: (typeof soundOptions)[number]) => language.t(o.label), onHighlight: (option: (typeof soundOptions)[number] | undefined) => { if (!option) return - playDemoSound(option.id === "none" ? undefined : option.id) + playDemoSound(option.src) }, onSelect: (option: (typeof soundOptions)[number] | undefined) => { if (!option) return @@ -192,7 +169,7 @@ export const SettingsGeneral: Component = () => { } setEnabled(true) set(option.id) - playDemoSound(option.id) + playDemoSound(option.src) }, variant: "secondary" as const, size: "small" as const, @@ -344,9 +321,6 @@ export const SettingsGeneral: Component = () => { current={fontOptionsList.find((o) => o.value === settings.appearance.font())} value={(o) => o.value} label={(o) => language.t(o.label)} - onHighlight={(option) => { - void loadFont().then((x) => x.ensureMonoFont(option?.value)) - }} onSelect={(option) => option && settings.appearance.setFont(option.value)} variant="secondary" size="small" diff --git a/packages/app/src/components/status-popover.tsx b/packages/app/src/components/status-popover.tsx index 8d5ecac39..464522443 100644 --- a/packages/app/src/components/status-popover.tsx +++ b/packages/app/src/components/status-popover.tsx @@ -16,6 +16,7 @@ import { useSDK } from "@/context/sdk" import { normalizeServerUrl, ServerConnection, useServer } from "@/context/server" import { useSync } from "@/context/sync" import { useCheckServerHealth, type ServerHealth } from "@/utils/server-health" +import { DialogSelectServer } from "./dialog-select-server" const pollMs = 10_000 @@ -53,15 +54,11 @@ const listServersByHealth = ( }) } -const useServerHealth = (servers: Accessor<ServerConnection.Any[]>, enabled: Accessor<boolean>) => { +const useServerHealth = (servers: Accessor<ServerConnection.Any[]>) => { const checkServerHealth = useCheckServerHealth() const [status, setStatus] = createStore({} as Record<ServerConnection.Key, ServerHealth | undefined>) createEffect(() => { - if (!enabled()) { - setStatus(reconcile({})) - return - } const list = servers() let dead = false @@ -165,12 +162,6 @@ export function StatusPopover() { const navigate = useNavigate() const [shown, setShown] = createSignal(false) - let dialogRun = 0 - let dialogDead = false - onCleanup(() => { - dialogDead = true - dialogRun += 1 - }) const servers = createMemo(() => { const current = server.current const list = server.list @@ -178,7 +169,7 @@ export function StatusPopover() { if (list.every((item) => ServerConnection.key(item) !== ServerConnection.key(current))) return [current, ...list] return [current, ...list.filter((item) => ServerConnection.key(item) !== ServerConnection.key(current))] }) - const health = useServerHealth(servers, shown) + const health = useServerHealth(servers) const sortedServers = createMemo(() => listServersByHealth(servers(), server.key, health)) const toggleMcp = useMcpToggleMutation() const defaultServer = useDefaultServerKey(platform.getDefaultServer) @@ -309,13 +300,7 @@ export function StatusPopover() { <Button variant="secondary" class="mt-3 self-start h-8 px-3 py-1.5" - onClick={() => { - const run = ++dialogRun - void import("./dialog-select-server").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show(() => <x.DialogSelectServer />, defaultServer.refresh) - }) - }} + onClick={() => dialog.show(() => <DialogSelectServer />, defaultServer.refresh)} > {language.t("status.popover.action.manageServers")} </Button> diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx index 0a5a7d2d3..aed46f126 100644 --- a/packages/app/src/components/terminal.tsx +++ b/packages/app/src/components/terminal.tsx @@ -1,7 +1,4 @@ -import { withAlpha } from "@opencode-ai/ui/theme/color" -import { useTheme } from "@opencode-ai/ui/theme/context" -import { resolveThemeVariant } from "@opencode-ai/ui/theme/resolve" -import type { HexColor } from "@opencode-ai/ui/theme/types" +import { type HexColor, resolveThemeVariant, useTheme, withAlpha } from "@opencode-ai/ui/theme" import { showToast } from "@opencode-ai/ui/toast" import type { FitAddon, Ghostty, Terminal as Term } from "ghostty-web" import { type ComponentProps, createEffect, createMemo, onCleanup, onMount, splitProps } from "solid-js" diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 0a41f3119..77de1a73c 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -5,7 +5,7 @@ import { IconButton } from "@opencode-ai/ui/icon-button" import { Icon } from "@opencode-ai/ui/icon" import { Button } from "@opencode-ai/ui/button" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" -import { useTheme } from "@opencode-ai/ui/theme/context" +import { useTheme } from "@opencode-ai/ui/theme" import { useLayout } from "@/context/layout" import { usePlatform } from "@/context/platform" |
