Przeglądaj źródła

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

Dax Raad 2 miesięcy temu
rodzic
commit
dbbcf0b8d0

+ 3 - 1
packages/desktop/src/components/prompt-input.tsx

@@ -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"}

+ 1 - 0
packages/desktop/src/context/notification.tsx

@@ -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

+ 37 - 33
packages/ui/src/context/dialog.tsx

@@ -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()
     },