From 0d3bef3f1c6ed458a31c4ef6e32e4d873ce4b4b1 Mon Sep 17 00:00:00 2001 From: can1357 Date: Wed, 28 Jan 2026 17:09:11 +0100 Subject: [PATCH] refactor(coding-agent/modes): restructured hook selector and input overlay management to use TUI overlay API - Refactored hook selector and input overlay management to use TUI overlay API instead of manual container manipulation. - Extracted dialog overlay options into a reusable constant with consistent styling (bottom-center anchor, 80% width, 70% max height). - Added overlay handle tracking to properly manage overlay lifecycle and prevent duplicate overlays. --- .../controllers/extension-ui-controller.ts | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/coding-agent/src/modes/controllers/extension-ui-controller.ts b/packages/coding-agent/src/modes/controllers/extension-ui-controller.ts index ac70f1e8e..df2c89d10 100644 --- a/packages/coding-agent/src/modes/controllers/extension-ui-controller.ts +++ b/packages/coding-agent/src/modes/controllers/extension-ui-controller.ts @@ -1,4 +1,4 @@ -import type { Component, TUI } from "@oh-my-pi/pi-tui"; +import type { Component, OverlayHandle, TUI } from "@oh-my-pi/pi-tui"; import { Spacer, Text } from "@oh-my-pi/pi-tui"; import { logger } from "@oh-my-pi/pi-utils"; import { KeybindingsManager } from "../../config/keybindings"; @@ -18,6 +18,17 @@ import type { InteractiveModeContext } from "../../modes/types"; import { setTerminalTitle } from "../../utils/title-generator"; export class ExtensionUiController { + private hookSelectorOverlay: OverlayHandle | undefined; + private hookInputOverlay: OverlayHandle | undefined; + + private readonly dialogOverlayOptions = { + anchor: "bottom-center", + width: "80%", + minWidth: 40, + maxHeight: "70%", + margin: 1, + } as const; + constructor(private ctx: InteractiveModeContext) {} /** @@ -491,6 +502,8 @@ export class ExtensionUiController { dialogOptions?: ExtensionUIDialogOptions, ): Promise { const { promise, resolve } = Promise.withResolvers(); + this.hookSelectorOverlay?.hide(); + this.hookSelectorOverlay = undefined; this.ctx.hookSelector = new HookSelectorComponent( title, options, @@ -504,11 +517,7 @@ export class ExtensionUiController { }, { initialIndex: dialogOptions?.initialIndex, timeout: dialogOptions?.timeout, tui: this.ctx.ui }, ); - - this.ctx.editorContainer.clear(); - this.ctx.editorContainer.addChild(this.ctx.hookSelector); - this.ctx.ui.setFocus(this.ctx.hookSelector); - this.ctx.ui.requestRender(); + this.hookSelectorOverlay = this.ctx.ui.showOverlay(this.ctx.hookSelector, this.dialogOverlayOptions); return promise; } @@ -517,8 +526,8 @@ export class ExtensionUiController { */ hideHookSelector(): void { this.ctx.hookSelector?.dispose(); - this.ctx.editorContainer.clear(); - this.ctx.editorContainer.addChild(this.ctx.editor); + this.hookSelectorOverlay?.hide(); + this.hookSelectorOverlay = undefined; this.ctx.hookSelector = undefined; this.ctx.ui.setFocus(this.ctx.editor); this.ctx.ui.requestRender(); @@ -537,6 +546,8 @@ export class ExtensionUiController { */ showHookInput(title: string, placeholder?: string): Promise { const { promise, resolve } = Promise.withResolvers(); + this.hookInputOverlay?.hide(); + this.hookInputOverlay = undefined; this.ctx.hookInput = new HookInputComponent( title, placeholder, @@ -549,11 +560,7 @@ export class ExtensionUiController { resolve(undefined); }, ); - - this.ctx.editorContainer.clear(); - this.ctx.editorContainer.addChild(this.ctx.hookInput); - this.ctx.ui.setFocus(this.ctx.hookInput); - this.ctx.ui.requestRender(); + this.hookInputOverlay = this.ctx.ui.showOverlay(this.ctx.hookInput, this.dialogOverlayOptions); return promise; } @@ -562,8 +569,8 @@ export class ExtensionUiController { */ hideHookInput(): void { this.ctx.hookInput?.dispose(); - this.ctx.editorContainer.clear(); - this.ctx.editorContainer.addChild(this.ctx.editor); + this.hookInputOverlay?.hide(); + this.hookInputOverlay = undefined; this.ctx.hookInput = undefined; this.ctx.ui.setFocus(this.ctx.editor); this.ctx.ui.requestRender();