diff --git a/desktop/src/features/terminal/TerminalSubstrate.test.mjs b/desktop/src/features/terminal/TerminalSubstrate.test.mjs index 609ac4062..3fbd70d35 100644 --- a/desktop/src/features/terminal/TerminalSubstrate.test.mjs +++ b/desktop/src/features/terminal/TerminalSubstrate.test.mjs @@ -131,6 +131,8 @@ test("mounted IME paths neither toggle nor emit preedit text", async () => { fireEvent.input(input, { target: { value: "か" } }); assert.deepEqual(calls.input, []); fireEvent.compositionEnd(input, { data: "か" }); + assert.deepEqual(calls.input, []); + fireEvent.input(input, { target: { value: "か" } }); assert.deepEqual(calls.input, ["か"]); }); @@ -148,6 +150,15 @@ test("welcome survives non-intersecting frame and dismisses on input or intersec }, ], }, + { + line: 8, + spans: [ + { + style: { fg: 0, bg: 0, flags: 0 }, + clusters: [{ column: 70, text: "x", width: 1 }], + }, + ], + }, ], viewport: { columns: 80, generation: 1, screenLines: 24 }, }; @@ -157,8 +168,13 @@ test("welcome survives non-intersecting frame and dismisses on input or intersec toggleChord(); const input = view.getByLabelText("Terminal input"); fireEvent.input(input, { target: { value: "x" } }); - await waitFor(() => - assert.equal(view.container.querySelector(".buzz-terminal-welcome"), null), + await waitFor( + () => + assert.equal( + view.container.querySelector(".buzz-terminal-welcome"), + null, + ), + { timeout: 1_000 }, ); cleanup(); @@ -171,7 +187,7 @@ test("welcome survives non-intersecting frame and dismisses on input or intersec spans: [ { style: { fg: 0, bg: 0, flags: 0 }, - clusters: [{ column: 0, text: "x", width: 1 }], + clusters: [{ column: 30, text: "x", width: 1 }], }, ], }, diff --git a/desktop/src/features/terminal/TerminalSubstrate.tsx b/desktop/src/features/terminal/TerminalSubstrate.tsx index 295d9246b..ed8a18f88 100644 --- a/desktop/src/features/terminal/TerminalSubstrate.tsx +++ b/desktop/src/features/terminal/TerminalSubstrate.tsx @@ -67,18 +67,18 @@ function welcomeRect(frame: TerminalFrame) { } function frameDamageRects(frame: TerminalFrame) { - return frame.rows - .filter((row) => - row.spans.some((span) => - span.clusters.some((cluster) => cluster.text.trim().length > 0), - ), - ) - .map((row) => ({ - top: row.line, - left: 0, - bottom: row.line + 1, - right: frame.viewport.columns, - })); + return frame.rows.flatMap((row) => + row.spans.flatMap((span) => + span.clusters + .filter((cluster) => cluster.text.trim().length > 0) + .map((cluster) => ({ + top: row.line, + left: cluster.column, + bottom: row.line + 1, + right: cluster.column + cluster.width, + })), + ), + ); } export function TerminalSubstrate({ @@ -388,13 +388,10 @@ export function TerminalSubstrate({ autoCapitalize="off" autoComplete="off" className="buzz-terminal-input" - onCompositionEnd={(event) => { + onCompositionEnd={() => { handoffRef.current = reduceHandoff(handoffRef.current, { type: "composition-end", }).state; - const committed = event.currentTarget.value; - event.currentTarget.value = ""; - sendInput(committed); }} onCompositionStart={() => { handoffRef.current = reduceHandoff(handoffRef.current, {