Просмотр исходного кода

fix(tui): manage focus in devtools panels (#38555)

Co-authored-by: James Long <17031+jlongster@users.noreply.github.com>
opencode-agent[bot] 3 недель назад
Родитель
Сommit
2a9f8e3a2c
1 измененных файлов с 21 добавлено и 4 удалено
  1. 21 4
      packages/tui/src/component/devtools-bar.tsx

+ 21 - 4
packages/tui/src/component/devtools-bar.tsx

@@ -1,4 +1,4 @@
-import { TextAttributes } from "@opentui/core"
+import { TextAttributes, type Renderable } from "@opentui/core"
 import { TimeToFirstDraw, useRenderer, useTerminalDimensions } from "@opentui/solid"
 import { open } from "node:fs/promises"
 import { tmpdir } from "node:os"
@@ -33,6 +33,7 @@ export function DevToolsBar() {
   const plugins = usePlugin()
   const theme = useTheme()
   const keymap = Keymap.use()
+  const renderer = useRenderer()
   const dimensions = useTerminalDimensions()
   const { themeV2, mode, supports, setMode } = theme
   const elevatedTheme = theme.contextual("elevated").themeV2
@@ -41,6 +42,7 @@ export function DevToolsBar() {
   const [dumpPath, setDumpPath] = createSignal<string>()
   const [dumpError, setDumpError] = createSignal<string>()
   const [frontendSamples, setFrontendSamples] = createSignal<readonly ProcessSample[]>([])
+  let focus: Renderable | null
   const connected = createMemo(() => client.connection.status() === "connected")
   const serverIndicator = createMemo(() => connectionIndicator(client.connection.status(), client.connection.attempt()))
   const themePerformance = createMemo(
@@ -54,7 +56,22 @@ export function DevToolsBar() {
       address: info.urls[0] ? new URL(info.urls[0]).host : "Unknown",
     }
   })
-  const toggle = (next: Panel) => setPanel((current) => (current === next ? undefined : next))
+  const close = () => {
+    setPanel()
+    setTimeout(() => {
+      if (panel() || !focus || focus.isDestroyed) return
+      focus.focus()
+      focus = null
+    }, 1)
+  }
+  const toggle = (next: Panel) => {
+    if (panel() === next) return close()
+    if (!panel()) {
+      focus = renderer.currentFocusedRenderable
+      focus?.blur()
+    }
+    setPanel(next)
+  }
   const nextMode = () => (mode() === "dark" ? "light" : "dark")
   const canSwitchMode = () => supports(nextMode())
   const runtime = createMemo(() => runtimeStatus(frontendSamples()))
@@ -67,7 +84,7 @@ export function DevToolsBar() {
       if (!panel() || event.name !== "escape") return
       event.preventDefault()
       event.stopPropagation()
-      setPanel()
+      close()
     },
     { priority: 10 },
   )
@@ -205,7 +222,7 @@ export function DevToolsBar() {
           width={dimensions().width}
           height={Math.max(0, dimensions().height - 1)}
           backgroundColor="transparent"
-          onMouseUp={() => setPanel()}
+          onMouseUp={close}
         />
       </Show>
       <BarItem active={panel() === "server"} onClick={() => toggle("server")}>