From dab16f75d1e188440362627717b5facfa58f53c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Haris=20Gu=C5=A1i=C4=87?= Date: Fri, 31 Oct 2025 19:56:05 +0100 Subject: [PATCH] opentui: fix: Deleting current session from TUI (#3617) --- packages/opencode/src/cli/cmd/tui/app.tsx | 11 +++++++++++ packages/opencode/src/cli/cmd/tui/routes/home.tsx | 15 ++++++++++++--- .../src/cli/cmd/tui/routes/session/index.tsx | 6 ++++++ packages/opencode/src/cli/cmd/tui/ui/dialog.tsx | 13 ++++++++++++- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index b5f51de9d..75ea3fb25 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -25,6 +25,7 @@ import { DialogAlert } from "./ui/dialog-alert" import { ToastProvider, useToast } from "./ui/toast" import { ExitProvider } from "./context/exit" import type { SessionRoute } from "./context/route" +import { Session as SessionApi } from "@/session" import { TuiEvent } from "./event" export function tui(input: { @@ -245,6 +246,16 @@ function App() { }) }) + event.on(SessionApi.Event.Deleted.type, (evt) => { + if (route.data.type === "session" && route.data.sessionID === evt.properties.info.id) { + route.navigate({ type: "home" }) + toast.show({ + variant: "info", + message: "The current session was deleted", + }) + } + }) + return ( { return Object.values(sync.data.mcp).some((x) => x.status === "failed") }) + let promptRef: PromptRef | undefined = undefined + + createEffect(() => { + dialog.allClosedEvent.listen(() => { + promptRef?.focus() + }) + }) const Hint = ( 0}> @@ -55,7 +64,7 @@ export function Home() { Switch agent - + (promptRef = r)} /> diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index d85b633cc..baa63d370 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -105,6 +105,12 @@ export function Session() { let prompt: PromptRef const keybind = useKeybind() + createEffect(() => { + dialog.allClosedEvent.listen(() => { + prompt.focus() + }) + }) + useKeyboard((evt) => { if (dialog.stack.length > 0) return diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx index 71e270261..ec2233c69 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx @@ -1,8 +1,9 @@ import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid" -import { batch, createContext, Show, useContext, type JSX, type ParentProps } from "solid-js" +import { batch, createContext, createEffect, Show, useContext, type JSX, type ParentProps } from "solid-js" import { useTheme } from "@tui/context/theme" import { Renderable, RGBA } from "@opentui/core" import { createStore } from "solid-js/store" +import { createEventBus } from "@solid-primitives/event-bus" const Border = { topLeft: "┃", @@ -65,6 +66,7 @@ function init() { }[], size: "medium" as "medium" | "large", }) + const allClosedEvent = createEventBus() useKeyboard((evt) => { if (evt.name === "escape" && store.stack.length > 0) { @@ -95,6 +97,12 @@ function init() { }, 1) } + createEffect(() => { + if (store.stack.length === 0) { + allClosedEvent.emit() + } + }) + return { clear() { for (const item of store.stack) { @@ -128,6 +136,9 @@ function init() { setSize(size: "medium" | "large") { setStore("size", size) }, + get allClosedEvent() { + return allClosedEvent + } } }