Buckets:
| import { useFilteredList } from "@opencode-ai/ui/hooks" | |
| import { ProviderIcon } from "@opencode-ai/ui/provider-icon" | |
| import { Switch } from "@opencode-ai/ui/v2/switch-v2" | |
| import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon" | |
| import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2" | |
| import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2" | |
| import { type Component, For, Show } from "solid-js" | |
| import { useLanguage } from "@/context/language" | |
| import { useModels } from "@/context/models" | |
| import { popularProviders } from "@/hooks/use-providers" | |
| import { SettingsListV2 } from "./parts/list" | |
| import { SettingsRowV2 } from "./parts/row" | |
| import "./settings-v2.css" | |
| type ModelItem = ReturnType<ReturnType<typeof useModels>["list"]>[number] | |
| const PROVIDER_ICON_SIZE = 16 | |
| export const SettingsModelsV2: Component = () => { | |
| const language = useLanguage() | |
| const models = useModels() | |
| const list = useFilteredList<ModelItem>({ | |
| items: (_filter) => models.list(), | |
| key: (x) => `${x.provider.id}:${x.id}`, | |
| filterKeys: ["provider.name", "name", "id"], | |
| sortBy: (a, b) => a.name.localeCompare(b.name), | |
| groupBy: (x) => x.provider.id, | |
| sortGroupsBy: (a, b) => { | |
| const aIndex = popularProviders.indexOf(a.category) | |
| const bIndex = popularProviders.indexOf(b.category) | |
| const aPopular = aIndex >= 0 | |
| const bPopular = bIndex >= 0 | |
| if (aPopular && !bPopular) return -1 | |
| if (!aPopular && bPopular) return 1 | |
| if (aPopular && bPopular) return aIndex - bIndex | |
| const aName = a.items[0].provider.name | |
| const bName = b.items[0].provider.name | |
| return aName.localeCompare(bName) | |
| }, | |
| }) | |
| return ( | |
| <> | |
| <div class="settings-v2-tab-header settings-v2-tab-header--stacked"> | |
| <h2 class="settings-v2-tab-title">{language.t("settings.models.title")}</h2> | |
| <div class="settings-v2-tab-search"> | |
| <TextInputV2 | |
| type="search" | |
| appearance="base" | |
| value={list.filter()} | |
| onInput={(event) => list.onInput(event.currentTarget.value)} | |
| placeholder={language.t("dialog.model.search.placeholder")} | |
| spellcheck={false} | |
| autocorrect="off" | |
| autocomplete="off" | |
| autocapitalize="off" | |
| aria-label={language.t("dialog.model.search.placeholder")} | |
| /> | |
| <Show when={list.filter()}> | |
| <IconButtonV2 | |
| type="button" | |
| variant="ghost-muted" | |
| size="small" | |
| class="settings-v2-tab-search-clear" | |
| icon={<IconV2 name="close" size="large" class="text-v2-icon-icon-muted" />} | |
| onClick={() => list.clear()} | |
| /> | |
| </Show> | |
| </div> | |
| </div> | |
| <div class="settings-v2-tab-body settings-v2-models"> | |
| <Show | |
| when={!list.grouped.loading} | |
| fallback={ | |
| <div class="settings-v2-models-status"> | |
| {language.t("common.loading")} | |
| {language.t("common.loading.ellipsis")} | |
| </div> | |
| } | |
| > | |
| <Show | |
| when={list.flat().length > 0} | |
| fallback={ | |
| <div class="settings-v2-models-status"> | |
| <span>{language.t("dialog.model.empty")}</span> | |
| <Show when={list.filter()}> | |
| <span class="settings-v2-models-status-filter">"{list.filter()}"</span> | |
| </Show> | |
| </div> | |
| } | |
| > | |
| <For each={list.grouped.latest}> | |
| {(group) => ( | |
| <div class="settings-v2-section" data-component="settings-models-provider"> | |
| <div class="settings-v2-models-group-header"> | |
| <ProviderIcon | |
| id={group.category} | |
| width={PROVIDER_ICON_SIZE} | |
| height={PROVIDER_ICON_SIZE} | |
| class="settings-v2-models-provider-icon shrink-0" | |
| /> | |
| <h3 class="settings-v2-section-title">{group.items[0].provider.name}</h3> | |
| </div> | |
| <SettingsListV2> | |
| <For each={group.items}> | |
| {(item) => { | |
| const key = { providerID: item.provider.id, modelID: item.id } | |
| return ( | |
| <SettingsRowV2 title={item.name} description=""> | |
| <div> | |
| <Switch | |
| checked={models.visible(key)} | |
| onChange={(checked) => { | |
| models.setVisibility(key, checked) | |
| }} | |
| hideLabel | |
| > | |
| {item.name} | |
| </Switch> | |
| </div> | |
| </SettingsRowV2> | |
| ) | |
| }} | |
| </For> | |
| </SettingsListV2> | |
| </div> | |
| )} | |
| </For> | |
| </Show> | |
| </Show> | |
| </div> | |
| </> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 5.19 kB
- Xet hash:
- 9ff580eb5026efa1989e2cfa5e565f26c44386a6a2ee289aa786634fe55dfad2
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.