mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-09 13:21:42 +00:00
opentui(ts): deferClose helper for overlay-close defers
Extract the repeated `setTimeout(() => …close…, 0)` overlay/prompt-close pattern into a single `deferClose(fn)` helper (src/logic/defer.ts) so the "why deferred" rationale (let the closing keystroke finish dispatching before the composer remounts/refocuses) lives in one place. Rewires the 5 close-defer sites: closePager/closeDashboard/closeSwitcher/ closePicker in view/App.tsx and clearSoon in view/prompts/promptOverlay.tsx. Timing is unchanged (0ms). Other setTimeout uses (quit window, flashHint, scroll re-anchor, resize debounce, transport) are NOT close-defers and are left untouched.
This commit is contained in:
parent
f4d944c49c
commit
b36001940a
3 changed files with 20 additions and 6 deletions
12
ui-tui-opentui-v2/src/logic/defer.ts
Normal file
12
ui-tui-opentui-v2/src/logic/defer.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* deferClose — defer an overlay/prompt close by one tick.
|
||||
*
|
||||
* Overlays REPLACE the composer (a `<Switch>`), so when one closes the composer
|
||||
* remounts + refocuses. Running the close on the NEXT tick lets the current
|
||||
* key/close event (Esc/q/Enter/y/select) finish dispatching first, so the
|
||||
* keystroke that triggered the close can't leak into the freshly-focused
|
||||
* composer (e.g. `/clear`→y once left a stray "y" in the input).
|
||||
*/
|
||||
export function deferClose(fn: () => void): void {
|
||||
setTimeout(fn, 0)
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
import { Match, Switch } from 'solid-js'
|
||||
|
||||
import { deferClose } from '../logic/defer.ts'
|
||||
import type { PromptHistory } from '../logic/history.ts'
|
||||
import type { PasteStore } from '../logic/pastes.ts'
|
||||
import type { SessionStore } from '../logic/store.ts'
|
||||
|
|
@ -56,11 +57,11 @@ export function App(props: AppProps) {
|
|||
const switcher = () => props.store.state.switcher
|
||||
const picker = () => props.store.state.picker
|
||||
// Defer the close so the key that closed an overlay (Esc/q/Enter) can't land in
|
||||
// the freshly-remounted composer.
|
||||
const closePager = () => setTimeout(() => props.store.closePager(), 0)
|
||||
const closeDashboard = () => setTimeout(() => props.store.closeDashboard(), 0)
|
||||
const closeSwitcher = () => setTimeout(() => props.store.closeSwitcher(), 0)
|
||||
const closePicker = () => setTimeout(() => props.store.closePicker(), 0)
|
||||
// the freshly-remounted composer (see deferClose).
|
||||
const closePager = () => deferClose(() => props.store.closePager())
|
||||
const closeDashboard = () => deferClose(() => props.store.closeDashboard())
|
||||
const closeSwitcher = () => deferClose(() => props.store.closeSwitcher())
|
||||
const closePicker = () => deferClose(() => props.store.closePicker())
|
||||
const resume = (id: string) => {
|
||||
;(props.onResume ?? NOOP_RESUME)(id)
|
||||
closeSwitcher()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
import { Match, Switch } from 'solid-js'
|
||||
|
||||
import { deferClose } from '../../logic/defer.ts'
|
||||
import type { SessionStore } from '../../logic/store.ts'
|
||||
import { ApprovalPrompt } from './approvalPrompt.tsx'
|
||||
import { ClarifyPrompt } from './clarifyPrompt.tsx'
|
||||
|
|
@ -28,7 +29,7 @@ export function PromptOverlay(props: PromptOverlayProps) {
|
|||
// Defer the prompt-clear (which remounts + refocuses the composer) past the
|
||||
// CURRENT keystroke, so the key that answered the prompt (Enter/y/select) can't
|
||||
// leak into the freshly-focused composer (e.g. `/clear`→y left "y" in the input).
|
||||
const clearSoon = () => setTimeout(() => props.store.clearPrompt(), 0)
|
||||
const clearSoon = () => deferClose(() => props.store.clearPrompt())
|
||||
const respond = (method: string, params: Record<string, unknown>) => {
|
||||
props.onRespond(method, params)
|
||||
clearSoon()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue