From 3e01de0b092c7b14842c5165d09146b45c140066 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 23 Apr 2026 12:40:39 -0500 Subject: [PATCH] fix(ui-tui): preserve composer after resize-burst healing - run the xterm.js settle-heal pass through a full render commit instead of diff-only scheduleRender - guard against overlapping resize renders and clear settle timers on unmount --- ui-tui/packages/hermes-ink/src/ink/ink.tsx | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/ui-tui/packages/hermes-ink/src/ink/ink.tsx b/ui-tui/packages/hermes-ink/src/ink/ink.tsx index 4e0c54ec9..036954a77 100644 --- a/ui-tui/packages/hermes-ink/src/ink/ink.tsx +++ b/ui-tui/packages/hermes-ink/src/ink/ink.tsx @@ -467,13 +467,29 @@ export default class Ink { this.resizeSettleTimer = setTimeout(() => { this.resizeSettleTimer = null - if (this.isUnmounted || this.isPaused || !this.altScreenActive || !this.options.stdout.isTTY) { + if ( + this.isUnmounted || + this.isPaused || + !this.altScreenActive || + !this.options.stdout.isTTY || + this.currentNode === null || + this.pendingResizeRender + ) { return } - this.resetFramesForAltScreen() - this.needsEraseBeforePaint = true - this.scheduleRender() + this.pendingResizeRender = true + queueMicrotask(() => { + this.pendingResizeRender = false + + if (this.isUnmounted || this.isPaused || !this.altScreenActive || !this.options.stdout.isTTY || this.currentNode === null) { + return + } + + this.resetFramesForAltScreen() + this.needsEraseBeforePaint = true + this.render(this.currentNode) + }) }, 160) } } @@ -1954,6 +1970,10 @@ export default class Ink { clearTimeout(this.drainTimer) this.drainTimer = null } + if (this.resizeSettleTimer !== null) { + clearTimeout(this.resizeSettleTimer) + this.resizeSettleTimer = null + } reconciler.updateContainerSync(null, this.container, null, noop) reconciler.flushSyncWork()