fix(app): preserve provider dialog backdrop (#35370)
Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: Brendan Allan <git@brendonovich.dev>
This commit is contained in:
co-authored by
Jay
Brendan Allan
parent
e12cb7fb6b
commit
14df88eab5
@@ -17,19 +17,17 @@ import { useServerSync } from "@/context/server-sync"
|
|||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { useProviders } from "@/hooks/use-providers"
|
import { useProviders } from "@/hooks/use-providers"
|
||||||
|
|
||||||
export function DialogConnectProvider(props: { provider: string; directory?: Accessor<string | undefined> }) {
|
export function DialogConnectProvider(props: {
|
||||||
|
provider: string
|
||||||
|
directory?: Accessor<string | undefined>
|
||||||
|
onBack: () => void
|
||||||
|
}) {
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
const serverSync = useServerSync()
|
const serverSync = useServerSync()
|
||||||
const serverSDK = useServerSDK()
|
const serverSDK = useServerSDK()
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const providers = useProviders(props.directory)
|
const providers = useProviders(props.directory)
|
||||||
|
|
||||||
const all = () => {
|
|
||||||
void import("./dialog-select-provider").then((x) => {
|
|
||||||
dialog.show(() => <x.DialogSelectProvider directory={props.directory} />)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const alive = { value: true }
|
const alive = { value: true }
|
||||||
const timer = { current: undefined as ReturnType<typeof setTimeout> | undefined }
|
const timer = { current: undefined as ReturnType<typeof setTimeout> | undefined }
|
||||||
|
|
||||||
@@ -364,19 +362,11 @@ export function DialogConnectProvider(props: { provider: string; directory?: Acc
|
|||||||
}
|
}
|
||||||
|
|
||||||
function goBack() {
|
function goBack() {
|
||||||
if (methods().length === 1) {
|
if (methods().length > 1 && store.methodIndex !== undefined) {
|
||||||
all()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (store.authorization) {
|
|
||||||
dispatch({ type: "method.reset" })
|
dispatch({ type: "method.reset" })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (store.methodIndex !== undefined) {
|
props.onBack()
|
||||||
dispatch({ type: "method.reset" })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
all()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function MethodSelection() {
|
function MethodSelection() {
|
||||||
@@ -600,6 +590,7 @@ export function DialogConnectProvider(props: { provider: string; directory?: Acc
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
|
class="h-full"
|
||||||
title={
|
title={
|
||||||
<IconButton
|
<IconButton
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
@@ -609,6 +600,7 @@ export function DialogConnectProvider(props: { provider: string; directory?: Acc
|
|||||||
aria-label={language.t("common.goBack")}
|
aria-label={language.t("common.goBack")}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
transition
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-6 px-2.5 pb-3">
|
<div class="flex flex-col gap-6 px-2.5 pb-3">
|
||||||
<div class="px-2.5 flex gap-4 items-center">
|
<div class="px-2.5 flex gap-4 items-center">
|
||||||
|
|||||||
@@ -6,18 +6,16 @@ import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
|
|||||||
import { useMutation } from "@tanstack/solid-query"
|
import { useMutation } from "@tanstack/solid-query"
|
||||||
import { TextField } from "@opencode-ai/ui/text-field"
|
import { TextField } from "@opencode-ai/ui/text-field"
|
||||||
import { showToast } from "@/utils/toast"
|
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 { createStore, produce } from "solid-js/store"
|
||||||
import { Link } from "@/components/link"
|
import { Link } from "@/components/link"
|
||||||
import { useServerSDK } from "@/context/server-sdk"
|
import { useServerSDK } from "@/context/server-sdk"
|
||||||
import { useServerSync } from "@/context/server-sync"
|
import { useServerSync } from "@/context/server-sync"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { type FormState, headerRow, modelRow, validateCustomProvider } from "./dialog-custom-provider-form"
|
import { type FormState, headerRow, modelRow, validateCustomProvider } from "./dialog-custom-provider-form"
|
||||||
import { DialogSelectProvider } from "./dialog-select-provider"
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
back?: "providers" | "close"
|
onBack: () => void
|
||||||
directory?: Accessor<string | undefined>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DialogCustomProvider(props: Props) {
|
export function DialogCustomProvider(props: Props) {
|
||||||
@@ -36,14 +34,6 @@ export function DialogCustomProvider(props: Props) {
|
|||||||
err: {},
|
err: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
const goBack = () => {
|
|
||||||
if (props.back === "close") {
|
|
||||||
dialog.close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dialog.show(() => <DialogSelectProvider directory={props.directory} />)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addModel = () => {
|
const addModel = () => {
|
||||||
setForm(
|
setForm(
|
||||||
"models",
|
"models",
|
||||||
@@ -164,12 +154,13 @@ export function DialogCustomProvider(props: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
|
class="h-full"
|
||||||
title={
|
title={
|
||||||
<IconButton
|
<IconButton
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
icon="arrow-left"
|
icon="arrow-left"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={goBack}
|
onClick={props.onBack}
|
||||||
aria-label={language.t("common.goBack")}
|
aria-label={language.t("common.goBack")}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props
|
|||||||
|
|
||||||
const connect = (provider: string) => {
|
const connect = (provider: string) => {
|
||||||
void import("./dialog-connect-provider").then((x) => {
|
void import("./dialog-connect-provider").then((x) => {
|
||||||
dialog.show(() => <x.DialogConnectProvider provider={provider} directory={directory} />)
|
dialog.show(() => <x.DialogConnectProvider provider={provider} directory={directory} onBack={all} />)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { type Accessor, Component, Show } from "solid-js"
|
import { type Accessor, Component, Match, Show, Switch } from "solid-js"
|
||||||
import { useDialog } from "@opencode-ai/ui/context/dialog"
|
import { createStore } from "solid-js/store"
|
||||||
import { popularProviders, useProviders } from "@/hooks/use-providers"
|
import { popularProviders, useProviders } from "@/hooks/use-providers"
|
||||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||||
import { List } from "@opencode-ai/ui/list"
|
import { List } from "@opencode-ai/ui/list"
|
||||||
@@ -12,9 +12,13 @@ import { DialogCustomProvider } from "./dialog-custom-provider"
|
|||||||
const CUSTOM_ID = "_custom"
|
const CUSTOM_ID = "_custom"
|
||||||
|
|
||||||
export const DialogSelectProvider: Component<{ directory?: Accessor<string | undefined> }> = (props) => {
|
export const DialogSelectProvider: Component<{ directory?: Accessor<string | undefined> }> = (props) => {
|
||||||
const dialog = useDialog()
|
|
||||||
const providers = useProviders(props.directory)
|
const providers = useProviders(props.directory)
|
||||||
const language = useLanguage()
|
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 popularGroup = () => language.t("dialog.provider.group.popular")
|
||||||
const otherGroup = () => language.t("dialog.provider.group.other")
|
const otherGroup = () => language.t("dialog.provider.group.other")
|
||||||
@@ -27,7 +31,15 @@ export const DialogSelectProvider: Component<{ directory?: Accessor<string | und
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog title={language.t("command.provider.connect")} transition>
|
<Switch>
|
||||||
|
<Match when={store.selected === CUSTOM_ID}>
|
||||||
|
<DialogCustomProvider onBack={showPicker} />
|
||||||
|
</Match>
|
||||||
|
<Match when={store.selected && store.selected !== CUSTOM_ID ? store.selected : undefined}>
|
||||||
|
{(provider) => <DialogConnectProvider provider={provider()} directory={props.directory} onBack={showPicker} />}
|
||||||
|
</Match>
|
||||||
|
<Match when={true}>
|
||||||
|
<Dialog class="h-full" transition title={language.t("command.provider.connect")}>
|
||||||
<List
|
<List
|
||||||
class="px-3"
|
class="px-3"
|
||||||
search={{ placeholder: language.t("dialog.provider.search.placeholder"), autofocus: true }}
|
search={{ placeholder: language.t("dialog.provider.search.placeholder"), autofocus: true }}
|
||||||
@@ -55,11 +67,7 @@ export const DialogSelectProvider: Component<{ directory?: Accessor<string | und
|
|||||||
}}
|
}}
|
||||||
onSelect={(x) => {
|
onSelect={(x) => {
|
||||||
if (!x) return
|
if (!x) return
|
||||||
if (x.id === CUSTOM_ID) {
|
setStore("selected", x.id)
|
||||||
dialog.show(() => <DialogCustomProvider back="providers" directory={props.directory} />)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dialog.show(() => <DialogConnectProvider provider={x.id} directory={props.directory} />)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(i) => (
|
{(i) => (
|
||||||
@@ -83,5 +91,7 @@ export const DialogSelectProvider: Component<{ directory?: Accessor<string | und
|
|||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,12 @@ const SettingsProvidersContent: Component = () => {
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus-small"
|
icon="plus-small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.show(() => <DialogConnectProvider provider={item.id} />)
|
dialog.show(() => (
|
||||||
|
<DialogConnectProvider
|
||||||
|
provider={item.id}
|
||||||
|
onBack={() => dialog.show(() => <DialogSelectProvider />)}
|
||||||
|
/>
|
||||||
|
))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{language.t("common.connect")}
|
{language.t("common.connect")}
|
||||||
@@ -239,7 +244,7 @@ const SettingsProvidersContent: Component = () => {
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus-small"
|
icon="plus-small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.show(() => <DialogCustomProvider back="close" />)
|
dialog.show(() => <DialogCustomProvider onBack={dialog.close} />)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{language.t("common.connect")}
|
{language.t("common.connect")}
|
||||||
|
|||||||
@@ -211,7 +211,12 @@ export const SettingsProvidersV2: Component = () => {
|
|||||||
variant="neutral"
|
variant="neutral"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.show(() => <DialogConnectProvider provider={item.id} />)
|
dialog.show(() => (
|
||||||
|
<DialogConnectProvider
|
||||||
|
provider={item.id}
|
||||||
|
onBack={() => dialog.show(() => <DialogSelectProvider />)}
|
||||||
|
/>
|
||||||
|
))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{language.t("common.connect")}
|
{language.t("common.connect")}
|
||||||
@@ -241,7 +246,7 @@ export const SettingsProvidersV2: Component = () => {
|
|||||||
variant="neutral"
|
variant="neutral"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.show(() => <DialogCustomProvider back="close" />)
|
dialog.show(() => <DialogCustomProvider onBack={dialog.close} />)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{language.t("common.connect")}
|
{language.t("common.connect")}
|
||||||
|
|||||||
@@ -77,7 +77,16 @@ export function useUsageExceededDialogs() {
|
|||||||
if (dontShowAgain) setGoUpsellState(keys.dontShow, Date.now())
|
if (dontShowAgain) setGoUpsellState(keys.dontShow, Date.now())
|
||||||
else {
|
else {
|
||||||
void import("../../components/dialog-connect-provider").then((x) =>
|
void import("../../components/dialog-connect-provider").then((x) =>
|
||||||
dialog.show(() => <x.DialogConnectProvider provider="opencode-go" />),
|
dialog.show(() => (
|
||||||
|
<x.DialogConnectProvider
|
||||||
|
provider="opencode-go"
|
||||||
|
onBack={() => {
|
||||||
|
void import("../../components/dialog-select-provider").then((provider) => {
|
||||||
|
dialog.show(() => <provider.DialogSelectProvider />)
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user