ソースを参照

wip(desktop): progress

Adam 2 ヶ月 前
コミット
ba16bfdf3d

+ 10 - 7
packages/desktop/src/components/dialog-manage-models.tsx

@@ -27,18 +27,21 @@ export const DialogManageModels: Component = () => {
         }}
         onSelect={(x) => {
           if (!x) return
-          local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, !x.visible)
+          const visible = local.model.visible({ modelID: x.id, providerID: x.provider.id })
+          local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, !visible)
         }}
       >
         {(i) => (
           <div class="w-full flex items-center justify-between gap-x-2.5">
             <span>{i.name}</span>
-            <Switch
-              checked={!!i.visible}
-              onChange={(checked) => {
-                local.model.setVisibility({ modelID: i.id, providerID: i.provider.id }, checked)
-              }}
-            />
+            <div onClick={(e) => e.stopPropagation()}>
+              <Switch
+                checked={!!local.model.visible({ modelID: i.id, providerID: i.provider.id })}
+                onChange={(checked) => {
+                  local.model.setVisibility({ modelID: i.id, providerID: i.provider.id }, checked)
+                }}
+              />
+            </div>
           </div>
         )}
       </List>

+ 2 - 3
packages/desktop/src/components/dialog-select-model.tsx

@@ -13,11 +13,10 @@ export const DialogSelectModel: Component<{ provider?: string }> = (props) => {
   const local = useLocal()
   const dialog = useDialog()
 
-  let closeButton!: HTMLButtonElement
   const models = createMemo(() =>
     local.model
       .list()
-      .filter((m) => m.visible)
+      .filter((m) => local.model.visible({ modelID: m.id, providerID: m.provider.id }))
       .filter((m) => (props.provider ? m.provider.id === props.provider : true)),
   )
 
@@ -58,7 +57,7 @@ export const DialogSelectModel: Component<{ provider?: string }> = (props) => {
           local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined, {
             recent: true,
           })
-          closeButton.click()
+          dialog.clear()
         }}
       >
         {(i) => (

+ 9 - 11
packages/desktop/src/context/local.tsx

@@ -132,10 +132,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
           Object.values(p.models).map((m) => ({
             ...m,
             provider: p,
-            user: store.user.find((x) => x.modelID === m.id && x.providerID === p.id),
           })),
         ),
       )
+
       const latest = createMemo(() =>
         pipe(
           available(),
@@ -163,10 +163,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
           ...m,
           name: m.name.replace("(latest)", "").trim(),
           latest: m.name.includes("(latest)"),
-          visible:
-            m.user?.visibility !== "hide" &&
-            (latest().find((x) => x.modelID === m.id && x.providerID === m.provider.id) ||
-              store.user.find((x) => x.modelID === m.id && x.providerID === m.provider.id)?.visibility === "show"),
         })),
       )
 
@@ -241,7 +237,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
         if (index >= 0) {
           setStore("user", index, { visibility })
         } else {
-          setStore("user", (prev) => [...prev, { ...model, visibility }])
+          setStore("user", store.user.length, { ...model, visibility })
         }
       }
 
@@ -260,11 +256,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
             }
           })
         },
-        show(model: ModelKey) {
-          updateVisibility(model, "show")
-        },
-        hide(model: ModelKey) {
-          updateVisibility(model, "hide")
+        visible(model: ModelKey) {
+          const user = store.user.find((x) => x.modelID === model.modelID && x.providerID === model.providerID)
+          return (
+            user?.visibility !== "hide" &&
+            (latest().find((x) => x.modelID === model.modelID && x.providerID === model.providerID) ||
+              user?.visibility === "show")
+          )
         },
         setVisibility(model: ModelKey, visible: boolean) {
           updateVisibility(model, visible ? "show" : "hide")

+ 21 - 11
packages/ui/src/components/list.tsx

@@ -1,4 +1,4 @@
-import { createEffect, Show, For, type JSX, createSignal } from "solid-js"
+import { createEffect, on, Show, For, type JSX, createSignal } from "solid-js"
 import { createStore } from "solid-js/store"
 import { FilteredListProps, useFilteredList } from "@opencode-ai/ui/hooks"
 import { Icon, IconProps } from "./icon"
@@ -32,24 +32,34 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
     mouseActive: false,
   })
 
-  const { filter, grouped, flat, reset, active, setActive, onKeyDown, onInput } = useFilteredList<T>(props)
+  const { filter, grouped, flat, active, setActive, onKeyDown, onInput } = useFilteredList<T>(props)
 
   const searchProps = () => (typeof props.search === "object" ? props.search : {})
-  const hasSearch = () => !!props.search
 
   createEffect(() => {
     if (props.filter !== undefined) {
       onInput(props.filter)
-    } else if (hasSearch()) {
-      onInput(internalFilter())
     }
   })
 
-  createEffect(() => {
-    filter()
-    scrollRef()?.scrollTo(0, 0)
-    reset()
-  })
+  createEffect((prev) => {
+    if (!props.search) return
+    const current = internalFilter()
+    if (prev !== current) {
+      onInput(current)
+    }
+    return current
+  }, "")
+
+  createEffect(
+    on(
+      filter,
+      () => {
+        scrollRef()?.scrollTo(0, 0)
+      },
+      { defer: true },
+    ),
+  )
 
   createEffect(() => {
     if (!scrollRef()) return
@@ -100,7 +110,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
 
   return (
     <div data-component="list" classList={{ [props.class ?? ""]: !!props.class }}>
-      <Show when={hasSearch()}>
+      <Show when={!!props.search}>
         <div data-slot="list-search">
           <div data-slot="list-search-container">
             <Icon name="magnifying-glass" />