fix(app): preserve native IME composition state

Clearing the hidden terminal input after multi-character commits can leave the keyboard's composing buffer intact, causing later changes to replay committed text. Keep the accumulated native value so subsequent changes emit only their appended suffix.
This commit is contained in:
Mohamed Boudra
2026-08-04 10:44:00 +02:00
parent e238fea158
commit e90832eedd
2 changed files with 27 additions and 9 deletions
@@ -30,7 +30,7 @@ describe("native terminal typed input", () => {
expect(input.receiveTextChange("npm run typecheck")).toEqual({
data: "npm run typecheck",
shouldClear: true,
shouldClear: false,
});
});
@@ -122,11 +122,11 @@ describe("native terminal typed input", () => {
const input = createTerminalTextInputState();
const longText = "x".repeat(512);
expect(input.receiveTextChange(longText)).toEqual({ data: longText, shouldClear: true });
expect(input.receiveTextChange(longText)).toEqual({ data: longText, shouldClear: false });
input.reset();
expect(input.receiveTextChange(longText)).toEqual({ data: longText, shouldClear: true });
expect(input.receiveTextChange(longText)).toEqual({ data: longText, shouldClear: false });
});
it("translates software keyboard terminal control keys", () => {
@@ -197,14 +197,35 @@ describe("native terminal typed input", () => {
expect(input.receiveTextChange("echo clipboard item")).toEqual({
data: "echo clipboard item",
shouldClear: true,
shouldClear: false,
});
input.reset();
expect(input.receiveTextChange("echo clipboard item")).toEqual({
data: "echo clipboard item",
shouldClear: true,
shouldClear: false,
});
});
it("does not replay a stale IME suggestion when the native clear leaves composing text behind", () => {
const input = createTerminalTextInputState();
let typed = "";
for (const key of "resta") {
typed += key;
input.receiveKeyPress(key);
input.receiveTextChange(typed);
}
expect(input.receiveTextChange("restaurant ")).toEqual({
data: "urant ",
shouldClear: false,
});
expect(input.receiveTextChange("restaurant x")).toEqual({
data: "x",
shouldClear: false,
});
});
});
@@ -107,10 +107,7 @@ export function createTerminalTextInputState(): TerminalTextInputState {
previousText = text;
return {
data: appendedText,
// Treat multi-character IME commits as complete units. Clearing lets
// the keyboard commit the same clipboard item again without needing
// a different intermediate value.
shouldClear: appendedText.length > 1,
shouldClear: false,
};
},
reset(): void {