fix(tui): restore composer focus after runtime controls

This commit is contained in:
Xubin Ren
2026-08-17 20:56:10 +08:00
parent cd6a11b3c5
commit c5d2e0ddf1
3 changed files with 14 additions and 4 deletions
+7
View File
@@ -650,6 +650,7 @@ describe("NanobotTui layout", () => {
visible: boolean
menuRoot: { getChildren(): unknown[] }
}
composer: TextareaRenderable
titleText: TextRenderable
status: TextRenderable
meta: TextRenderable
@@ -680,8 +681,11 @@ describe("NanobotTui layout", () => {
expect(modelRows.every((row) => !row.selectable)).toBe(true)
const fast = modelRows.find((row) => row.plainText.includes("fast"))
if (!fast) throw new Error("fast model row was not rendered")
ui.composer.blur()
expect(ui.composer.focused).toBe(false)
await setup.mockMouse.click(fast.x + 2, fast.y)
await waitUntil(() => sent.includes("/model fast"))
expect(ui.composer.focused).toBe(true)
await setup.mockMouse.click(
ui.runtimeControls.accessText.x + 2,
@@ -692,7 +696,10 @@ describe("NanobotTui layout", () => {
const accessRows = ui.runtimeControls.menuRoot.getChildren() as TextRenderable[]
const full = accessRows.find((row) => row.plainText.includes("Full access"))
if (!full) throw new Error("full access row was not rendered")
ui.composer.blur()
expect(ui.composer.focused).toBe(false)
await setup.mockMouse.click(full.x + 2, full.y)
expect(ui.composer.focused).toBe(true)
expect(scopes).toEqual([{
project_path: "/tmp/nanobot-workspace",
+4 -1
View File
@@ -531,7 +531,10 @@ export class NanobotTui {
}
},
onStatus: (message) => { this.status.content = message },
onVisibilityChange: () => this.updateMeta(),
onVisibilityChange: (visible) => {
this.updateMeta()
if (!visible) this.composer.focus()
},
},
)
this.title.add(this.titleText)
+3 -3
View File
@@ -33,7 +33,7 @@ interface RuntimeControlsOptions {
onModel: (name: string) => void
onAccess: (scope: WorkspaceScopePayload) => void
onStatus: (message: string) => void
onVisibilityChange: () => void
onVisibilityChange: (visible: boolean) => void
}
/** Model and workspace policy controls expose one small, mouse-optional interface. */
@@ -139,7 +139,7 @@ export class RuntimeControls {
this.kind = null
this.menu.hide()
this.renderColors()
this.options.onVisibilityChange()
this.options.onVisibilityChange(false)
}
setTheme(theme: RuntimeControlsTheme): void {
@@ -261,7 +261,7 @@ export class RuntimeControls {
private opened(): void {
this.renderColors()
this.options.onVisibilityChange()
this.options.onVisibilityChange(true)
}
private apply(choice: Choice): void {