diff --git a/packages/app/src/docker-git/menu-input-handler.ts b/packages/app/src/docker-git/menu-input-handler.ts index 95614ae5..6bd6695a 100644 --- a/packages/app/src/docker-git/menu-input-handler.ts +++ b/packages/app/src/docker-git/menu-input-handler.ts @@ -34,27 +34,13 @@ const activateInput = ( } const normalized = input.trim() - - if (normalized.length > 1) { + const hasMenuInput = normalized.length > 0 || input.length > 0 + const hasMenuActionKey = key.upArrow || key.downArrow || key.return + if (hasMenuInput || hasMenuActionKey) { context.setInputStage("active") return { activated: true, allowProcessing: true } } - if (key.upArrow || key.downArrow || key.return) { - context.setInputStage("active") - return { activated: true, allowProcessing: false } - } - - if (normalized.length === 1) { - context.setInputStage("active") - return { activated: true, allowProcessing: false } - } - - if (input.length > 0) { - context.setInputStage("active") - return { activated: true, allowProcessing: false } - } - return { activated: false, allowProcessing: false } } diff --git a/packages/app/src/docker-git/menu-state.ts b/packages/app/src/docker-git/menu-state.ts index 5319ba09..3982ecd5 100644 --- a/packages/app/src/docker-git/menu-state.ts +++ b/packages/app/src/docker-git/menu-state.ts @@ -32,6 +32,16 @@ export type MenuSnapshotStore = { current: MenuSnapshot } +// CHANGE: make a fresh CLI TUI process the first user key after readiness gates +// WHY: ready/ignoreUntil already filters bootstrap noise; skipping valid input breaks menu liveness +// QUOTE(ISSUE): "Почему-то CLI TUI не работает" +// REF: issue-274 +// SOURCE: n/a +// FORMAT THEOREM: forall key in ValidMenuInput: ready(menu) -> processed(key) +// PURITY: CORE +// EFFECT: n/a +// INVARIANT: initial snapshot has no synthetic skipped user inputs +// COMPLEXITY: O(1) export const defaultMenuSnapshot = (): MenuSnapshot => ({ activeDir: null, runningDockerGitContainers: 0, @@ -39,9 +49,9 @@ export const defaultMenuSnapshot = (): MenuSnapshot => ({ busy: false, message: null, view: { _tag: "Menu" }, - inputStage: "cold", + inputStage: "active", ready: false, - skipInputs: 2, + skipInputs: 0, sshActive: false, startupLoaded: false }) diff --git a/packages/app/tests/docker-git/menu-input-handler.test.ts b/packages/app/tests/docker-git/menu-input-handler.test.ts index 6bc91910..20999834 100644 --- a/packages/app/tests/docker-git/menu-input-handler.test.ts +++ b/packages/app/tests/docker-git/menu-input-handler.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it, vi } from "vitest" import { handleUserInput } from "../../src/docker-git/menu-input-handler.js" import type { MenuInputContext } from "../../src/docker-git/menu-input-handler.js" +import { defaultMenuSnapshot } from "../../src/docker-git/menu-state.js" const makeContext = (inputStage: "cold" | "active"): MenuInputContext & { readonly runnerRunEffect: ReturnType @@ -47,15 +48,15 @@ const makeContext = (inputStage: "cold" | "active"): MenuInputContext & { } describe("menu-input-handler", () => { - it("swallows the first single-character alias on cold start", () => { + it("handles the first single-character alias on cold start", () => { const context = makeContext("cold") handleUserInput("s", {}, context) expect(context.setInputStageMock).toHaveBeenCalledWith("active") - expect(context.runnerRunEffect).not.toHaveBeenCalled() + expect(context.runnerRunEffect).toHaveBeenCalledTimes(1) + expect(context.setSkipInputsMock).toHaveBeenCalledTimes(1) expect(context.setViewMock).not.toHaveBeenCalled() - expect(context.setMessageMock).not.toHaveBeenCalled() }) it("allows the same alias once input is already active", () => { @@ -66,4 +67,11 @@ describe("menu-input-handler", () => { expect(context.runnerRunEffect).toHaveBeenCalledTimes(1) expect(context.setSkipInputsMock).toHaveBeenCalledTimes(1) }) + + it("starts a fresh TUI snapshot without synthetic skipped inputs", () => { + const snapshot = defaultMenuSnapshot() + + expect(snapshot.inputStage).toBe("active") + expect(snapshot.skipInputs).toBe(0) + }) })