Selaa lähdekoodia

faster preload

Brendan Allan 1 päivä sitten
vanhempi
sitoutus
888123209c

+ 8 - 9
packages/app/src/components/prompt-input.tsx

@@ -54,7 +54,7 @@ import { PromptImageAttachments } from "./prompt-input/image-attachments"
 import { PromptDragOverlay } from "./prompt-input/drag-overlay"
 import { promptPlaceholder } from "./prompt-input/placeholder"
 import { ImagePreview } from "@opencode-ai/ui/image-preview"
-import { useQuery } from "@tanstack/solid-query"
+import { useQueries, useQuery } from "@tanstack/solid-query"
 import { loadAgentsQuery, loadProvidersQuery } from "@/context/global-sync/bootstrap"
 
 interface PromptInputProps {
@@ -1252,12 +1252,11 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
     }
   }
 
-  const agentsQuery = useQuery(() => loadAgentsQuery(sdk.directory))
-  const agentsLoading = () => agentsQuery.isLoading
-
-  const globalProvidersQuery = useQuery(() => loadProvidersQuery(null))
-  const providersQuery = useQuery(() => loadProvidersQuery(sdk.directory))
+  const [agentsQuery, globalProvidersQuery, providersQuery] = useQueries(() => ({
+    queries: [loadAgentsQuery(sdk.directory), loadProvidersQuery(null), loadProvidersQuery(sdk.directory)],
+  }))
 
+  const agentsLoading = () => agentsQuery.isLoading
   const providersLoading = () => agentsLoading() || providersQuery.isLoading || globalProvidersQuery.isLoading
 
   const [promptReady] = createResource(
@@ -1461,7 +1460,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
               </div>
               <div class="flex items-center gap-1.5 min-w-0 flex-1 h-7">
                 <Show when={!agentsLoading()}>
-                  <div data-component="prompt-agent-control">
+                  <div data-component="prompt-agent-control" style={{ animation: "fade-in 0.3s" }}>
                     <TooltipKeybind
                       placement="top"
                       gutter={4}
@@ -1487,7 +1486,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
                 </Show>
                 <Show when={!providersLoading()}>
                   <Show when={store.mode !== "shell"}>
-                    <div data-component="prompt-model-control">
+                    <div data-component="prompt-model-control" style={{ animation: "fade-in 0.3s" }}>
                       <Show
                         when={providers.paid().length > 0}
                         fallback={
@@ -1558,7 +1557,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
                         </TooltipKeybind>
                       </Show>
                     </div>
-                    <div data-component="prompt-variant-control">
+                    <div data-component="prompt-variant-control" style={{ animation: "fade-in 0.3s" }}>
                       <TooltipKeybind
                         placement="top"
                         gutter={4}

+ 24 - 23
packages/app/src/context/global-sync/bootstrap.ts

@@ -255,6 +255,9 @@ export async function bootstrapDirectory(input: {
   input.setStore("lsp_ready", false)
   input.setStore("lsp", [])
   if (loading) input.setStore("status", "partial")
+
+  const rev = (providerRev.get(input.directory) ?? 0) + 1
+  providerRev.set(input.directory, rev)
   ;(async () => {
     const slow = [
       () => Promise.resolve(input.loadSessions(input.directory)),
@@ -343,6 +346,27 @@ export async function bootstrapDirectory(input: {
             input.setStore("mcp_ready", true)
           }),
         ),
+      () =>
+        input.queryClient.ensureQueryData({
+          ...loadProvidersQuery(input.directory),
+          queryFn: () =>
+            retry(() => input.sdk.provider.list())
+              .then((x) => {
+                if (providerRev.get(input.directory) !== rev) return
+                input.setStore("provider", normalizeProviderList(x.data!))
+                input.setStore("provider_ready", true)
+              })
+              .catch((err) => {
+                if (providerRev.get(input.directory) !== rev) console.error("Failed to refresh provider list", err)
+                const project = getFilename(input.directory)
+                showToast({
+                  variant: "error",
+                  title: input.translate("toast.project.reloadFailed.title", { project }),
+                  description: formatServerError(err, input.translate),
+                })
+              })
+              .then(() => null),
+        }),
     ].filter(Boolean) as (() => Promise<any>)[]
 
     await waitForPaint()
@@ -358,28 +382,5 @@ export async function bootstrapDirectory(input: {
     }
 
     if (loading && slowErrs.length === 0) input.setStore("status", "complete")
-
-    const rev = (providerRev.get(input.directory) ?? 0) + 1
-    providerRev.set(input.directory, rev)
-    void input.queryClient.ensureQueryData({
-      ...loadProvidersQuery(input.directory),
-      queryFn: () =>
-        retry(() => input.sdk.provider.list())
-          .then((x) => {
-            if (providerRev.get(input.directory) !== rev) return
-            input.setStore("provider", normalizeProviderList(x.data!))
-            input.setStore("provider_ready", true)
-          })
-          .catch((err) => {
-            if (providerRev.get(input.directory) !== rev) console.error("Failed to refresh provider list", err)
-            const project = getFilename(input.directory)
-            showToast({
-              variant: "error",
-              title: input.translate("toast.project.reloadFailed.title", { project }),
-              description: formatServerError(err, input.translate),
-            })
-          })
-          .then(() => null),
-    })
   })()
 }

+ 9 - 0
packages/app/src/index.css

@@ -66,4 +66,13 @@
       width: auto;
     }
   }
+
+  @keyframes fade-in {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
 }

+ 5 - 6
packages/app/src/pages/directory-layout.tsx

@@ -2,7 +2,7 @@ import { DataProvider } from "@opencode-ai/ui/context"
 import { showToast } from "@opencode-ai/ui/toast"
 import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { useLocation, useNavigate, useParams } from "@solidjs/router"
-import { createEffect, createMemo, type ParentProps, Show } from "solid-js"
+import { createEffect, createMemo, createResource, type ParentProps, Show } from "solid-js"
 import { useLanguage } from "@/context/language"
 import { LocalProvider } from "@/context/local"
 import { SDKProvider } from "@/context/sdk"
@@ -23,11 +23,10 @@ function DirectoryDataProvider(props: ParentProps<{ directory: string }>) {
     navigate(`/${base64Encode(next)}${path}${location.search}${location.hash}`, { replace: true })
   })
 
-  createEffect(() => {
-    const id = params.id
-    if (!id) return
-    void sync.session.sync(id)
-  })
+  createResource(
+    () => params.id,
+    (id) => sync.session.sync(id),
+  )
 
   return (
     <DataProvider