Buckets:
| import { Button } from "@opencode-ai/ui/button" | |
| import { useDialog } from "@opencode-ai/ui/context/dialog" | |
| import { Dialog } from "@opencode-ai/ui/dialog" | |
| import { List, type ListRef } from "@opencode-ai/ui/list" | |
| import { ProviderIcon } from "@opencode-ai/ui/provider-icon" | |
| import { Tag } from "@opencode-ai/ui/tag" | |
| import { Tooltip } from "@opencode-ai/ui/tooltip" | |
| import { type Component, Show } from "solid-js" | |
| import { useLocal } from "@/context/local" | |
| import { popularProviders, useProviders } from "@/hooks/use-providers" | |
| import { ModelTooltip } from "./model-tooltip" | |
| import { useLanguage } from "@/context/language" | |
| type ModelState = ReturnType<typeof useLocal>["model"] | |
| export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props) => { | |
| const model = props.model ?? useLocal().model | |
| const dialog = useDialog() | |
| const providers = useProviders() | |
| const language = useLanguage() | |
| const connect = (provider: string) => { | |
| void import("./dialog-connect-provider").then((x) => { | |
| dialog.show(() => <x.DialogConnectProvider provider={provider} />) | |
| }) | |
| } | |
| const all = () => { | |
| void import("./dialog-select-provider").then((x) => { | |
| dialog.show(() => <x.DialogSelectProvider />) | |
| }) | |
| } | |
| let listRef: ListRef | undefined | |
| const handleKeyDown = (e: KeyboardEvent) => { | |
| if (e.key === "Escape") return | |
| listRef?.onKeyDown(e) | |
| } | |
| return ( | |
| <Dialog | |
| title={language.t("dialog.model.select.title")} | |
| class="overflow-y-auto [&_[data-slot=dialog-body]]:overflow-visible [&_[data-slot=dialog-body]]:flex-none" | |
| > | |
| <div class="flex flex-col gap-3 px-2.5" onKeyDown={handleKeyDown}> | |
| <div class="text-14-medium text-text-base px-2.5">{language.t("dialog.model.unpaid.freeModels.title")}</div> | |
| <List | |
| class="px-3 [&_[data-slot=list-scroll]]:overflow-visible" | |
| ref={(ref) => (listRef = ref)} | |
| items={model.list} | |
| current={model.current()} | |
| key={(x) => `${x.provider.id}:${x.id}`} | |
| itemWrapper={(item, node) => ( | |
| <Tooltip | |
| class="w-full" | |
| placement="right-start" | |
| gutter={12} | |
| value={ | |
| <ModelTooltip | |
| model={item} | |
| latest={item.latest} | |
| free={item.provider.id === "opencode" && (!item.cost || item.cost.input === 0)} | |
| /> | |
| } | |
| > | |
| {node} | |
| </Tooltip> | |
| )} | |
| onSelect={(x) => { | |
| model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined, { | |
| recent: true, | |
| }) | |
| dialog.close() | |
| }} | |
| > | |
| {(i) => ( | |
| <div class="w-full flex items-center gap-x-2.5"> | |
| <span>{i.name}</span> | |
| <Tag>{language.t("model.tag.free")}</Tag> | |
| <Show when={i.latest}> | |
| <Tag>{language.t("model.tag.latest")}</Tag> | |
| </Show> | |
| </div> | |
| )} | |
| </List> | |
| </div> | |
| <div class="px-1.5 pb-1.5"> | |
| <div class="w-full rounded-sm border border-border-weak-base bg-surface-raised-base"> | |
| <div class="w-full flex flex-col items-start gap-4 px-1.5 pt-4 pb-4"> | |
| <div class="px-2 text-14-medium text-text-base">{language.t("dialog.model.unpaid.addMore.title")}</div> | |
| <div class="w-full"> | |
| <List | |
| class="w-full px-3" | |
| key={(p) => p.id} | |
| items={providers.popular} | |
| activeIcon="plus-small" | |
| sortBy={(a, b) => { | |
| if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) | |
| return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) | |
| return a.name.localeCompare(b.name) | |
| }} | |
| onSelect={(x) => { | |
| if (!x) return | |
| connect(x.id) | |
| }} | |
| > | |
| {(i) => ( | |
| <div class="w-full flex items-center gap-x-3"> | |
| <ProviderIcon data-slot="list-item-extra-icon" id={i.id} /> | |
| <span>{i.name}</span> | |
| <Show when={i.id === "opencode"}> | |
| <div class="text-14-regular text-text-weak">{language.t("dialog.provider.opencode.tagline")}</div> | |
| </Show> | |
| <Show when={i.id === "opencode"}> | |
| <Tag>{language.t("dialog.provider.tag.recommended")}</Tag> | |
| </Show> | |
| <Show when={i.id === "opencode-go"}> | |
| <> | |
| <div class="text-14-regular text-text-weak"> | |
| {language.t("dialog.provider.opencodeGo.tagline")} | |
| </div> | |
| <Tag>{language.t("dialog.provider.tag.recommended")}</Tag> | |
| </> | |
| </Show> | |
| <Show when={i.id === "anthropic"}> | |
| <div class="text-14-regular text-text-weak">{language.t("dialog.provider.anthropic.note")}</div> | |
| </Show> | |
| </div> | |
| )} | |
| </List> | |
| <Button | |
| variant="ghost" | |
| class="w-full justify-start px-[11px] py-3.5 gap-4.5 text-14-medium" | |
| icon="dot-grid" | |
| onClick={all} | |
| > | |
| {language.t("dialog.provider.viewAll")} | |
| </Button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </Dialog> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 5.64 kB
- Xet hash:
- 9c2ae78c51488da3ffbf1ad4e99da4ff96631f7fbc049316c28c73d4639cc10d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.