diff options
| author | Adam <[email protected]> | 2026-02-12 20:19:14 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-02-12 20:19:26 -0600 |
| commit | fb7b2f6b4d66d14177b5c0168049863842665925 (patch) | |
| tree | 403262dbfbcd85b44c491a24b5eb06c7ac8125b1 | |
| parent | e0f1c3c20efb60f19f36e2c8df87dfd30fd2523e (diff) | |
| download | opencode-fb7b2f6b4d66d14177b5c0168049863842665925.tar.gz opencode-fb7b2f6b4d66d14177b5c0168049863842665925.zip | |
feat(app): toggle all provider models
| -rw-r--r-- | packages/app/src/components/dialog-manage-models.tsx | 32 | ||||
| -rw-r--r-- | packages/app/src/i18n/en.ts | 1 | ||||
| -rw-r--r-- | packages/ui/src/components/list.tsx | 7 | ||||
| -rw-r--r-- | packages/ui/src/components/switch.tsx | 2 |
4 files changed, 37 insertions, 5 deletions
diff --git a/packages/app/src/components/dialog-manage-models.tsx b/packages/app/src/components/dialog-manage-models.tsx index d4d4af0f1..ace79e38a 100644 --- a/packages/app/src/components/dialog-manage-models.tsx +++ b/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) diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index c138c7b61..99513edaa 100644 --- a/packages/app/src/i18n/en.ts +++ b/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", diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index abd557220..aa2347037 100644 --- a/packages/ui/src/components/list.tsx +++ b/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}> diff --git a/packages/ui/src/components/switch.tsx b/packages/ui/src/components/switch.tsx index a8600aef4..f4f95baf5 100644 --- a/packages/ui/src/components/switch.tsx +++ b/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 }}> |
