tui: fix model selection dialog to properly replace current dialog instead of creating nested dialogs

This commit is contained in:
Dax Raad 2025-12-15 18:14:30 -05:00
parent efac8cebb3
commit dbbcf0b8d0
3 changed files with 41 additions and 34 deletions

View file

@ -864,7 +864,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
as="div"
variant="ghost"
onClick={() =>
dialog.push(() => (providers.paid().length > 0 ? <DialogSelectModel /> : <DialogSelectModelUnpaid />))
dialog.replace(() =>
providers.paid().length > 0 ? <DialogSelectModel /> : <DialogSelectModelUnpaid />,
)
}
>
{local.model.current()?.name ?? "Select model"}

View file

@ -58,6 +58,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
time: Date.now(),
viewed: false,
}
console.log(event)
switch (event.type) {
case "session.idle": {
const sessionID = event.properties.sessionID

View file

@ -1,7 +1,9 @@
import {
createContext,
createEffect,
createMemo,
createSignal,
For,
getOwner,
Owner,
ParentProps,
@ -11,6 +13,7 @@ import {
type JSX,
} from "solid-js"
import { Dialog as Kobalte } from "@kobalte/core/dialog"
import { iife } from "@opencode-ai/util/iife"
type DialogElement = () => JSX.Element
@ -25,23 +28,49 @@ function init() {
}[]
>([])
return {
const result = {
get stack() {
return store()
},
push(element: DialogElement, owner: Owner, onClose?: () => void) {
setStore((s) => [...s, { element, onClose, owner }])
},
pop() {
const current = store().at(-1)
if (!current) return
current?.onClose?.()
setStore((stack) => stack.slice(0, -1))
setStore((stack) => {
stack.pop()
return [...stack]
})
},
replace(element: DialogElement, owner: Owner, onClose?: () => void) {
for (const item of store()) {
item.onClose?.()
}
setStore([{ element, onClose, owner }])
setStore([
{
element: () =>
runWithOwner(owner, () => (
<Show when={result.stack.at(-1)?.owner === owner}>
<Kobalte
modal
defaultOpen
onOpenChange={(open) => {
if (!open) {
onClose?.()
result.pop()
}
}}
>
<Kobalte.Portal>
<Kobalte.Overlay data-component="dialog-overlay" />
{element()}
</Kobalte.Portal>
</Kobalte>
</Show>
)),
onClose,
owner,
},
])
},
clear() {
for (const item of store()) {
@ -50,38 +79,16 @@ function init() {
setStore([])
},
}
return result
}
export function DialogProvider(props: ParentProps) {
const ctx = init()
const last = createMemo(() => ctx.stack.at(-1))
return (
<Context.Provider value={ctx}>
{props.children}
<div data-component="dialog-stack">
<Show when={last()}>
{(item) =>
runWithOwner(item().owner, () => {
return (
<Kobalte
modal
defaultOpen
onOpenChange={(open) => {
if (!open) {
item().onClose?.()
ctx.pop()
}
}}
>
<Kobalte.Portal>
<Kobalte.Overlay data-component="dialog-overlay" />
{item().element()}
</Kobalte.Portal>
</Kobalte>
)
})
}
</Show>
<For each={ctx.stack}>{(item) => <>{item.element()}</>}</For>
</div>
</Context.Provider>
)
@ -103,9 +110,6 @@ export function useDialog() {
replace(element: DialogElement, onClose?: () => void) {
ctx.replace(element, owner, onClose)
},
push(element: DialogElement, onClose?: () => void) {
ctx.push(element, owner, onClose)
},
pop() {
ctx.pop()
},