fix(app): make composer input IME-safe and paste-aware (#3343)

* fix(app): preserve native composer input semantics

Native text was round-tripped through application state on every keystroke, which could overwrite an input method's in-flight edits. Keep native text ownership inside the input and reserve application-driven replacement for explicit draft mutations.\n\nRoute native clipboard images through the existing persisted attachment pipeline so keyboard and system paste actions behave like other image sources.

* fix(nix): refresh dependency hash

The native composer dependency changes the fixed npm dependency closure used by desktop builds.

* fix(app): keep composer locked across image pastes

Count concurrent native image persistence operations so submit remains disabled until every pasted image is attached.

* fix(app): replace composer text through the DOM on web

Web TextInput refs are DOM elements, so application-driven draft replacement must update their value and selection without native setNativeProps.

* fix(app): preserve web IME composition

Carry the Chinese IME fix from #2990 into the web composer input boundary.

Co-authored-by: Jimmy Lee <jimersylee+github@gmail.com>

---------

Co-authored-by: Jimmy Lee <jimersylee+github@gmail.com>
This commit is contained in:
Mohamed Boudra
2026-08-14 11:52:24 +02:00
committed by GitHub
co-authored by Jimmy Lee
parent 770b87a15c
commit 30195d3bd1
23 changed files with 757 additions and 71 deletions
+4 -4
View File
@@ -52,7 +52,7 @@ interface DictationTranscriptContext {
isAgentRunning: boolean;
onQueue: ((payload: MessagePayload) => void) | undefined;
onSubmit: (payload: MessagePayload) => void;
onChangeText: (text: string) => void;
replaceText: (text: string) => void;
attachments: MessagePayload["attachments"];
cwd: string;
autoSend: boolean;
@@ -64,15 +64,15 @@ export function applyDictationTranscript(text: string, ctx: DictationTranscriptC
const nextValue = `${ctx.value}${shouldPad ? " " : ""}${text}`;
if (!ctx.autoSend) {
ctx.onChangeText(nextValue);
ctx.replaceText(nextValue);
return;
}
ctx.onChangeText(nextValue);
ctx.replaceText(nextValue);
if (ctx.defaultSendBehavior === "queue" && ctx.isAgentRunning && ctx.onQueue) {
ctx.onQueue({ text: nextValue, attachments: ctx.attachments, cwd: ctx.cwd });
ctx.onChangeText("");
ctx.replaceText("");
return;
}