diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index 3a57769b5a68..c94cca505351 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -17,19 +17,17 @@ import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { useProviders } from "@/hooks/use-providers" -export function DialogConnectProvider(props: { provider: string; directory?: Accessor }) { +export function DialogConnectProvider(props: { + provider: string + directory?: Accessor + onBack: () => void +}) { const dialog = useDialog() const serverSync = useServerSync() const serverSDK = useServerSDK() const language = useLanguage() const providers = useProviders(props.directory) - const all = () => { - void import("./dialog-select-provider").then((x) => { - dialog.show(() => ) - }) - } - const alive = { value: true } const timer = { current: undefined as ReturnType | undefined } @@ -364,19 +362,11 @@ export function DialogConnectProvider(props: { provider: string; directory?: Acc } function goBack() { - if (methods().length === 1) { - all() - return - } - if (store.authorization) { - dispatch({ type: "method.reset" }) - return - } - if (store.methodIndex !== undefined) { + if (methods().length > 1 && store.methodIndex !== undefined) { dispatch({ type: "method.reset" }) return } - all() + props.onBack() } function MethodSelection() { @@ -600,6 +590,7 @@ export function DialogConnectProvider(props: { provider: string; directory?: Acc return ( } + transition >
diff --git a/packages/app/src/components/dialog-custom-provider.tsx b/packages/app/src/components/dialog-custom-provider.tsx index 647e5002a297..e8cae859e06a 100644 --- a/packages/app/src/components/dialog-custom-provider.tsx +++ b/packages/app/src/components/dialog-custom-provider.tsx @@ -6,18 +6,16 @@ import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { useMutation } from "@tanstack/solid-query" import { TextField } from "@opencode-ai/ui/text-field" import { showToast } from "@/utils/toast" -import { type Accessor, batch, For } from "solid-js" +import { batch, For } from "solid-js" import { createStore, produce } from "solid-js/store" import { Link } from "@/components/link" import { useServerSDK } from "@/context/server-sdk" import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { type FormState, headerRow, modelRow, validateCustomProvider } from "./dialog-custom-provider-form" -import { DialogSelectProvider } from "./dialog-select-provider" type Props = { - back?: "providers" | "close" - directory?: Accessor + onBack: () => void } export function DialogCustomProvider(props: Props) { @@ -36,14 +34,6 @@ export function DialogCustomProvider(props: Props) { err: {}, }) - const goBack = () => { - if (props.back === "close") { - dialog.close() - return - } - dialog.show(() => ) - } - const addModel = () => { setForm( "models", @@ -164,12 +154,13 @@ export function DialogCustomProvider(props: Props) { return ( } diff --git a/packages/app/src/components/dialog-select-model-unpaid.tsx b/packages/app/src/components/dialog-select-model-unpaid.tsx index bcb4a2fbcbf4..0a32ad48b36d 100644 --- a/packages/app/src/components/dialog-select-model-unpaid.tsx +++ b/packages/app/src/components/dialog-select-model-unpaid.tsx @@ -24,7 +24,7 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props const connect = (provider: string) => { void import("./dialog-connect-provider").then((x) => { - dialog.show(() => ) + dialog.show(() => ) }) } diff --git a/packages/app/src/components/dialog-select-provider.tsx b/packages/app/src/components/dialog-select-provider.tsx index ff0ab5d2bf0c..e1facf48219a 100644 --- a/packages/app/src/components/dialog-select-provider.tsx +++ b/packages/app/src/components/dialog-select-provider.tsx @@ -1,5 +1,5 @@ -import { type Accessor, Component, Show } from "solid-js" -import { useDialog } from "@opencode-ai/ui/context/dialog" +import { type Accessor, Component, Match, Show, Switch } from "solid-js" +import { createStore } from "solid-js/store" import { popularProviders, useProviders } from "@/hooks/use-providers" import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" @@ -12,9 +12,13 @@ import { DialogCustomProvider } from "./dialog-custom-provider" const CUSTOM_ID = "_custom" export const DialogSelectProvider: Component<{ directory?: Accessor }> = (props) => { - const dialog = useDialog() const providers = useProviders(props.directory) const language = useLanguage() + const [store, setStore] = createStore({ selected: undefined as string | undefined }) + + function showPicker() { + setStore("selected", undefined) + } const popularGroup = () => language.t("dialog.provider.group.popular") const otherGroup = () => language.t("dialog.provider.group.other") @@ -27,61 +31,67 @@ export const DialogSelectProvider: Component<{ directory?: Accessor - x?.id} - items={() => { - language.locale() - return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all().values()] - }} - filterKeys={["id", "name"]} - groupBy={(x) => (popularProviders.includes(x.id) ? popularGroup() : otherGroup())} - sortBy={(a, b) => { - if (a.id === CUSTOM_ID) return -1 - if (b.id === CUSTOM_ID) return 1 - if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) - return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) - return a.name.localeCompare(b.name) - }} - sortGroupsBy={(a, b) => { - const popular = popularGroup() - if (a.category === popular && b.category !== popular) return -1 - if (b.category === popular && a.category !== popular) return 1 - return 0 - }} - onSelect={(x) => { - if (!x) return - if (x.id === CUSTOM_ID) { - dialog.show(() => ) - return - } - dialog.show(() => ) - }} - > - {(i) => ( -
- - {i.name} - -
{language.t("dialog.provider.opencode.tagline")}
-
- - {language.t("settings.providers.tag.custom")} - - - {language.t("dialog.provider.tag.recommended")} - - {(value) =>
{value()}
}
- - {language.t("dialog.provider.tag.recommended")} - -
- )} -
-
+ + + + + + {(provider) => } + + + + x?.id} + items={() => { + language.locale() + return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all().values()] + }} + filterKeys={["id", "name"]} + groupBy={(x) => (popularProviders.includes(x.id) ? popularGroup() : otherGroup())} + sortBy={(a, b) => { + if (a.id === CUSTOM_ID) return -1 + if (b.id === CUSTOM_ID) return 1 + if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) + return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) + return a.name.localeCompare(b.name) + }} + sortGroupsBy={(a, b) => { + const popular = popularGroup() + if (a.category === popular && b.category !== popular) return -1 + if (b.category === popular && a.category !== popular) return 1 + return 0 + }} + onSelect={(x) => { + if (!x) return + setStore("selected", x.id) + }} + > + {(i) => ( +
+ + {i.name} + +
{language.t("dialog.provider.opencode.tagline")}
+
+ + {language.t("settings.providers.tag.custom")} + + + {language.t("dialog.provider.tag.recommended")} + + {(value) =>
{value()}
}
+ + {language.t("dialog.provider.tag.recommended")} + +
+ )} +
+
+
+
) } diff --git a/packages/app/src/components/settings-providers.tsx b/packages/app/src/components/settings-providers.tsx index 24e7a60104ae..9791fc21fcae 100644 --- a/packages/app/src/components/settings-providers.tsx +++ b/packages/app/src/components/settings-providers.tsx @@ -211,7 +211,12 @@ const SettingsProvidersContent: Component = () => { variant="secondary" icon="plus-small" onClick={() => { - dialog.show(() => ) + dialog.show(() => ( + dialog.show(() => )} + /> + )) }} > {language.t("common.connect")} @@ -239,7 +244,7 @@ const SettingsProvidersContent: Component = () => { variant="secondary" icon="plus-small" onClick={() => { - dialog.show(() => ) + dialog.show(() => ) }} > {language.t("common.connect")} diff --git a/packages/app/src/components/settings-v2/providers.tsx b/packages/app/src/components/settings-v2/providers.tsx index cd24bbd4558c..99a4101f9a35 100644 --- a/packages/app/src/components/settings-v2/providers.tsx +++ b/packages/app/src/components/settings-v2/providers.tsx @@ -211,7 +211,12 @@ export const SettingsProvidersV2: Component = () => { variant="neutral" icon="plus" onClick={() => { - dialog.show(() => ) + dialog.show(() => ( + dialog.show(() => )} + /> + )) }} > {language.t("common.connect")} @@ -241,7 +246,7 @@ export const SettingsProvidersV2: Component = () => { variant="neutral" icon="plus" onClick={() => { - dialog.show(() => ) + dialog.show(() => ) }} > {language.t("common.connect")} diff --git a/packages/app/src/pages/session/usage-exceeded-dialogs.tsx b/packages/app/src/pages/session/usage-exceeded-dialogs.tsx index 935eed7e6969..5c77e7bcecc0 100644 --- a/packages/app/src/pages/session/usage-exceeded-dialogs.tsx +++ b/packages/app/src/pages/session/usage-exceeded-dialogs.tsx @@ -77,7 +77,16 @@ export function useUsageExceededDialogs() { if (dontShowAgain) setGoUpsellState(keys.dontShow, Date.now()) else { void import("../../components/dialog-connect-provider").then((x) => - dialog.show(() => ), + dialog.show(() => ( + { + void import("../../components/dialog-select-provider").then((provider) => { + dialog.show(() => ) + }) + }} + /> + )), ) } }}