Skip to content

Commit 9791850

Browse files
authored
app: start migrating bootstrap data fetching to TanStack Query (#22756)
1 parent e2c0803 commit 9791850

10 files changed

Lines changed: 355 additions & 271 deletions

File tree

bun.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/app/src/app.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ function SessionProviders(props: ParentProps) {
121121
function RouterRoot(props: ParentProps<{ appChildren?: JSX.Element }>) {
122122
return (
123123
<AppShellProviders>
124-
<Suspense fallback={<Loading />}>
125-
{props.appChildren}
126-
{props.children}
127-
</Suspense>
124+
{/*<Suspense fallback={<Loading />}>*/}
125+
{props.appChildren}
126+
{props.children}
127+
{/*</Suspense>*/}
128128
</AppShellProviders>
129129
)
130130
}
@@ -184,14 +184,22 @@ function ConnectionGate(props: ParentProps<{ disableHealthCheck?: boolean }>) {
184184
)
185185

186186
return (
187-
<Show
188-
when={checkMode() === "blocking" ? !startupHealthCheck.loading : startupHealthCheck.state !== "pending"}
187+
<Suspense
189188
fallback={
190189
<div class="h-dvh w-screen flex flex-col items-center justify-center bg-background-base">
191190
<Splash class="w-16 h-20 opacity-50 animate-pulse" />
192191
</div>
193192
}
194193
>
194+
{/*<Show
195+
when={checkMode() === "blocking" ? !startupHealthCheck.loading : startupHealthCheck.state !== "pending"}
196+
fallback={
197+
<div class="h-dvh w-screen flex flex-col items-center justify-center bg-background-base">
198+
<Splash class="w-16 h-20 opacity-50 animate-pulse" />
199+
</div>
200+
}
201+
>*/}
202+
{checkMode() === "blocking" ? startupHealthCheck() : startupHealthCheck.latest}
195203
<Show
196204
when={startupHealthCheck()}
197205
fallback={
@@ -209,7 +217,8 @@ function ConnectionGate(props: ParentProps<{ disableHealthCheck?: boolean }>) {
209217
>
210218
{props.children}
211219
</Show>
212-
</Show>
220+
{/*</Show>*/}
221+
</Suspense>
213222
)
214223
}
215224

packages/app/src/components/prompt-input.tsx

Lines changed: 109 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ import { PromptImageAttachments } from "./prompt-input/image-attachments"
5454
import { PromptDragOverlay } from "./prompt-input/drag-overlay"
5555
import { promptPlaceholder } from "./prompt-input/placeholder"
5656
import { ImagePreview } from "@opencode-ai/ui/image-preview"
57+
import { useQuery } from "@tanstack/solid-query"
58+
import { loadAgentsQuery, loadProvidersQuery } from "@/context/global-sync/bootstrap"
5759

5860
interface PromptInputProps {
5961
class?: string
@@ -100,6 +102,7 @@ const NON_EMPTY_TEXT = /[^\s\u200B]/
100102

101103
export const PromptInput: Component<PromptInputProps> = (props) => {
102104
const sdk = useSDK()
105+
103106
const sync = useSync()
104107
const local = useLocal()
105108
const files = useFile()
@@ -1249,6 +1252,14 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
12491252
}
12501253
}
12511254

1255+
const agentsQuery = useQuery(() => loadAgentsQuery(sdk.directory))
1256+
const agentsLoading = () => agentsQuery.isLoading
1257+
1258+
const globalProvidersQuery = useQuery(() => loadProvidersQuery(null))
1259+
const providersQuery = useQuery(() => loadProvidersQuery(sdk.directory))
1260+
1261+
const providersLoading = () => agentsLoading() || providersQuery.isLoading || globalProvidersQuery.isLoading
1262+
12521263
return (
12531264
<div class="relative size-full _max-h-[320px] flex flex-col gap-0">
12541265
<PromptPopover
@@ -1444,53 +1455,89 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
14441455
<span class="truncate text-13-medium text-text-strong">{language.t("prompt.mode.shell")}</span>
14451456
<div class="size-4 shrink-0" />
14461457
</div>
1447-
<div class="flex items-center gap-1.5 min-w-0 flex-1">
1448-
<div data-component="prompt-agent-control">
1449-
<TooltipKeybind
1450-
placement="top"
1451-
gutter={4}
1452-
title={language.t("command.agent.cycle")}
1453-
keybind={command.keybind("agent.cycle")}
1454-
>
1455-
<Select
1456-
size="normal"
1457-
options={agentNames()}
1458-
current={local.agent.current()?.name ?? ""}
1459-
onSelect={(value) => {
1460-
local.agent.set(value)
1461-
restoreFocus()
1462-
}}
1463-
class="capitalize max-w-[160px] text-text-base"
1464-
valueClass="truncate text-13-regular text-text-base"
1465-
triggerStyle={control()}
1466-
triggerProps={{ "data-action": "prompt-agent" }}
1467-
variant="ghost"
1468-
/>
1469-
</TooltipKeybind>
1470-
</div>
1471-
<Show when={store.mode !== "shell"}>
1472-
<div data-component="prompt-model-control">
1473-
<Show
1474-
when={providers.paid().length > 0}
1475-
fallback={
1458+
<div class="flex items-center gap-1.5 min-w-0 flex-1 h-7">
1459+
<Show when={!agentsLoading()}>
1460+
<div data-component="prompt-agent-control">
1461+
<TooltipKeybind
1462+
placement="top"
1463+
gutter={4}
1464+
title={language.t("command.agent.cycle")}
1465+
keybind={command.keybind("agent.cycle")}
1466+
>
1467+
<Select
1468+
size="normal"
1469+
options={agentNames()}
1470+
current={local.agent.current()?.name ?? ""}
1471+
onSelect={(value) => {
1472+
local.agent.set(value)
1473+
restoreFocus()
1474+
}}
1475+
class="capitalize max-w-[160px] text-text-base"
1476+
valueClass="truncate text-13-regular text-text-base"
1477+
triggerStyle={control()}
1478+
triggerProps={{ "data-action": "prompt-agent" }}
1479+
variant="ghost"
1480+
/>
1481+
</TooltipKeybind>
1482+
</div>
1483+
</Show>
1484+
<Show when={!providersLoading()}>
1485+
<Show when={store.mode !== "shell"}>
1486+
<div data-component="prompt-model-control">
1487+
<Show
1488+
when={providers.paid().length > 0}
1489+
fallback={
1490+
<TooltipKeybind
1491+
placement="top"
1492+
gutter={4}
1493+
title={language.t("command.model.choose")}
1494+
keybind={command.keybind("model.choose")}
1495+
>
1496+
<Button
1497+
data-action="prompt-model"
1498+
as="div"
1499+
variant="ghost"
1500+
size="normal"
1501+
class="min-w-0 max-w-[320px] text-13-regular text-text-base group"
1502+
style={control()}
1503+
onClick={() => {
1504+
void import("@/components/dialog-select-model-unpaid").then((x) => {
1505+
dialog.show(() => <x.DialogSelectModelUnpaid model={local.model} />)
1506+
})
1507+
}}
1508+
>
1509+
<Show when={local.model.current()?.provider?.id}>
1510+
<ProviderIcon
1511+
id={local.model.current()?.provider?.id ?? ""}
1512+
class="size-4 shrink-0 opacity-40 group-hover:opacity-100 transition-opacity duration-150"
1513+
style={{ "will-change": "opacity", transform: "translateZ(0)" }}
1514+
/>
1515+
</Show>
1516+
<span class="truncate">
1517+
{local.model.current()?.name ?? language.t("dialog.model.select.title")}
1518+
</span>
1519+
<Icon name="chevron-down" size="small" class="shrink-0" />
1520+
</Button>
1521+
</TooltipKeybind>
1522+
}
1523+
>
14761524
<TooltipKeybind
14771525
placement="top"
14781526
gutter={4}
14791527
title={language.t("command.model.choose")}
14801528
keybind={command.keybind("model.choose")}
14811529
>
1482-
<Button
1483-
data-action="prompt-model"
1484-
as="div"
1485-
variant="ghost"
1486-
size="normal"
1487-
class="min-w-0 max-w-[320px] text-13-regular text-text-base group"
1488-
style={control()}
1489-
onClick={() => {
1490-
void import("@/components/dialog-select-model-unpaid").then((x) => {
1491-
dialog.show(() => <x.DialogSelectModelUnpaid model={local.model} />)
1492-
})
1530+
<ModelSelectorPopover
1531+
model={local.model}
1532+
triggerAs={Button}
1533+
triggerProps={{
1534+
variant: "ghost",
1535+
size: "normal",
1536+
style: control(),
1537+
class: "min-w-0 max-w-[320px] text-13-regular text-text-base group",
1538+
"data-action": "prompt-model",
14931539
}}
1540+
onClose={restoreFocus}
14941541
>
14951542
<Show when={local.model.current()?.provider?.id}>
14961543
<ProviderIcon
@@ -1503,67 +1550,35 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
15031550
{local.model.current()?.name ?? language.t("dialog.model.select.title")}
15041551
</span>
15051552
<Icon name="chevron-down" size="small" class="shrink-0" />
1506-
</Button>
1553+
</ModelSelectorPopover>
15071554
</TooltipKeybind>
1508-
}
1509-
>
1555+
</Show>
1556+
</div>
1557+
<div data-component="prompt-variant-control">
15101558
<TooltipKeybind
15111559
placement="top"
15121560
gutter={4}
1513-
title={language.t("command.model.choose")}
1514-
keybind={command.keybind("model.choose")}
1561+
title={language.t("command.model.variant.cycle")}
1562+
keybind={command.keybind("model.variant.cycle")}
15151563
>
1516-
<ModelSelectorPopover
1517-
model={local.model}
1518-
triggerAs={Button}
1519-
triggerProps={{
1520-
variant: "ghost",
1521-
size: "normal",
1522-
style: control(),
1523-
class: "min-w-0 max-w-[320px] text-13-regular text-text-base group",
1524-
"data-action": "prompt-model",
1564+
<Select
1565+
size="normal"
1566+
options={variants()}
1567+
current={local.model.variant.current() ?? "default"}
1568+
label={(x) => (x === "default" ? language.t("common.default") : x)}
1569+
onSelect={(value) => {
1570+
local.model.variant.set(value === "default" ? undefined : value)
1571+
restoreFocus()
15251572
}}
1526-
onClose={restoreFocus}
1527-
>
1528-
<Show when={local.model.current()?.provider?.id}>
1529-
<ProviderIcon
1530-
id={local.model.current()?.provider?.id ?? ""}
1531-
class="size-4 shrink-0 opacity-40 group-hover:opacity-100 transition-opacity duration-150"
1532-
style={{ "will-change": "opacity", transform: "translateZ(0)" }}
1533-
/>
1534-
</Show>
1535-
<span class="truncate">
1536-
{local.model.current()?.name ?? language.t("dialog.model.select.title")}
1537-
</span>
1538-
<Icon name="chevron-down" size="small" class="shrink-0" />
1539-
</ModelSelectorPopover>
1573+
class="capitalize max-w-[160px] text-text-base"
1574+
valueClass="truncate text-13-regular text-text-base"
1575+
triggerStyle={control()}
1576+
triggerProps={{ "data-action": "prompt-model-variant" }}
1577+
variant="ghost"
1578+
/>
15401579
</TooltipKeybind>
1541-
</Show>
1542-
</div>
1543-
<div data-component="prompt-variant-control">
1544-
<TooltipKeybind
1545-
placement="top"
1546-
gutter={4}
1547-
title={language.t("command.model.variant.cycle")}
1548-
keybind={command.keybind("model.variant.cycle")}
1549-
>
1550-
<Select
1551-
size="normal"
1552-
options={variants()}
1553-
current={local.model.variant.current() ?? "default"}
1554-
label={(x) => (x === "default" ? language.t("common.default") : x)}
1555-
onSelect={(value) => {
1556-
local.model.variant.set(value === "default" ? undefined : value)
1557-
restoreFocus()
1558-
}}
1559-
class="capitalize max-w-[160px] text-text-base"
1560-
valueClass="truncate text-13-regular text-text-base"
1561-
triggerStyle={control()}
1562-
triggerProps={{ "data-action": "prompt-model-variant" }}
1563-
variant="ghost"
1564-
/>
1565-
</TooltipKeybind>
1566-
</div>
1580+
</div>
1581+
</Show>
15671582
</Show>
15681583
</div>
15691584
</div>

0 commit comments

Comments
 (0)