Преглед изворни кода

feat(app): toggle all provider models

Adam пре 6 месеци
родитељ
комит
fb7b2f6b4d

+ 31 - 1
packages/app/src/components/dialog-manage-models.tsx

@@ -1,6 +1,7 @@
 import { Dialog } from "@opencode-ai/ui/dialog"
 import { List } from "@opencode-ai/ui/list"
 import { Switch } from "@opencode-ai/ui/switch"
+import { Tooltip } from "@opencode-ai/ui/tooltip"
 import { Button } from "@opencode-ai/ui/button"
 import type { Component } from "solid-js"
 import { useLocal } from "@/context/local"
@@ -18,6 +19,14 @@ export const DialogManageModels: Component = () => {
     dialog.show(() => <DialogSelectProvider />)
   }
   const providerRank = (id: string) => popularProviders.indexOf(id)
+  const providerList = (providerID: string) => local.model.list().filter((x) => x.provider.id === providerID)
+  const providerVisible = (providerID: string) =>
+    providerList(providerID).every((x) => local.model.visible({ modelID: x.id, providerID: x.provider.id }))
+  const setProviderVisibility = (providerID: string, checked: boolean) => {
+    providerList(providerID).forEach((x) => {
+      local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, checked)
+    })
+  }
 
   return (
     <Dialog
@@ -36,7 +45,28 @@ export const DialogManageModels: Component = () => {
         items={local.model.list()}
         filterKeys={["provider.name", "name", "id"]}
         sortBy={(a, b) => a.name.localeCompare(b.name)}
-        groupBy={(x) => x.provider.name}
+        groupBy={(x) => x.provider.id}
+        groupHeader={(group) => {
+          const provider = group.items[0].provider
+          return (
+            <>
+              <span>{provider.name}</span>
+              <Tooltip
+                placement="top"
+                value={language.t("dialog.model.manage.provider.toggle", { provider: provider.name })}
+              >
+                <Switch
+                  class="-mr-1"
+                  checked={providerVisible(provider.id)}
+                  onChange={(checked) => setProviderVisibility(provider.id, checked)}
+                  hideLabel
+                >
+                  {provider.name}
+                </Switch>
+              </Tooltip>
+            </>
+          )
+        }}
         sortGroupsBy={(a, b) => {
           const aRank = providerRank(a.items[0].provider.id)
           const bRank = providerRank(b.items[0].provider.id)

+ 1 - 0
packages/app/src/i18n/en.ts

@@ -109,6 +109,7 @@ export const dict = {
   "dialog.model.empty": "No model results",
   "dialog.model.manage": "Manage models",
   "dialog.model.manage.description": "Customize which models appear in the model selector.",
+  "dialog.model.manage.provider.toggle": "Toggle all {{provider}} models",
 
   "dialog.model.unpaid.freeModels.title": "Free models provided by OpenCode",
   "dialog.model.unpaid.addMore.title": "Add more models from popular providers",

+ 4 - 3
packages/ui/src/components/list.tsx

@@ -45,6 +45,7 @@ export interface ListProps<T> extends FilteredListProps<T> {
   itemWrapper?: (item: T, node: JSX.Element) => JSX.Element
   divider?: boolean
   add?: ListAddProps
+  groupHeader?: (group: { category: string; items: T[] }) => JSX.Element
 }
 
 export interface ListRef {
@@ -206,7 +207,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
     )
   }
 
-  function GroupHeader(groupProps: { category: string }): JSX.Element {
+  function GroupHeader(groupProps: { group: { category: string; items: T[] } }): JSX.Element {
     const [stuck, setStuck] = createSignal(false)
     const [header, setHeader] = createSignal<HTMLDivElement | undefined>(undefined)
 
@@ -228,7 +229,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
 
     return (
       <div data-slot="list-header" data-stuck={stuck()} ref={setHeader}>
-        {groupProps.category}
+        {props.groupHeader?.(groupProps.group) ?? groupProps.group.category}
       </div>
     )
   }
@@ -323,7 +324,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
               return (
                 <div data-slot="list-group">
                   <Show when={group.category}>
-                    <GroupHeader category={group.category} />
+                    <GroupHeader group={group} />
                   </Show>
                   <div data-slot="list-items">
                     <For each={group.items}>

+ 1 - 1
packages/ui/src/components/switch.tsx

@@ -10,7 +10,7 @@ export interface SwitchProps extends ParentProps<ComponentProps<typeof Kobalte>>
 export function Switch(props: SwitchProps) {
   const [local, others] = splitProps(props, ["children", "class", "hideLabel", "description"])
   return (
-    <Kobalte {...others} data-component="switch">
+    <Kobalte {...others} class={local.class} data-component="switch">
       <Kobalte.Input data-slot="switch-input" />
       <Show when={local.children}>
         <Kobalte.Label data-slot="switch-label" classList={{ "sr-only": local.hideLabel }}>