From b7de98993de4819224ac0907f83b99cec4bf4163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=89=E9=9F=AC?= Date: Mon, 6 Apr 2026 15:49:15 +0800 Subject: [PATCH] fix: stop Enter propagation when transitioning to Input steps in apply TUI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In OpenTUI's emitWithPriority, global listeners run first and renderable handlers are captured into an array afterwards. When handleKeys (a global listener) called showStep('name') or showStep('personality_custom'), the new Input widget was immediately focused inside showStep, registering its keypress handler before the renderable snapshot was taken. The same Enter keypress that triggered the transition was then delivered to the fresh Input, which instantly submitted an empty value and skipped the step. Fix: call key.stopPropagation() after showStep() for the two transitions that create an Input widget (searching→name and personality→personality_custom), preventing the triggering Enter from reaching the newly-focused Input. --- src/tui/apply/index.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tui/apply/index.ts b/src/tui/apply/index.ts index b2b1bcc..4bcc2d3 100644 --- a/src/tui/apply/index.ts +++ b/src/tui/apply/index.ts @@ -565,7 +565,7 @@ export async function runApplyTUI( // Input steps (name, personality_custom) are handled by InputRenderableEvents.ENTER // on the widget itself (set up in addInput callbacks). This handler covers // confirmations (Y/N), Select steps, and navigation-only steps. - function handleKeys(key: { name?: string; ctrl?: boolean }): void { + function handleKeys(key: { name?: string; ctrl?: boolean; stopPropagation?(): void }): void { if (key.ctrl) return; // Ctrl+C handled separately switch (currentStep) { @@ -575,7 +575,13 @@ export async function runApplyTUI( break; case 'searching': - if (key.name === 'return' && saltResult) showStep('name'); + if (key.name === 'return' && saltResult) { + showStep('name'); + // Stop propagation so the Enter that triggered this transition is not + // delivered to the newly-focused Input widget (which would instantly + // submit it with an empty value, skipping the name step entirely). + key.stopPropagation?.(); + } break; // 'name' and 'personality_custom' — Enter handled by Input widget callbacks @@ -598,6 +604,9 @@ export async function runApplyTUI( nextAfterPersonality(); } else { showStep('personality_custom'); + // Same as above: stop propagation so the Enter that selected + // "Write custom" is not delivered to the newly-focused Input. + key.stopPropagation?.(); } } break;