From 96635ac813b358cd582819082d1e535eadad4b63 Mon Sep 17 00:00:00 2001 From: FuanSol Date: Sat, 6 Jun 2026 06:03:28 +0800 Subject: [PATCH 1/2] fix: send button not switching from voice button during IME composition (CJK input) Fixes #40146 The hasComposerPayload variable only checked the draft state, but during IME composition, handleEditorInput returns early and doesn't update draft. This caused the voice button to remain visible during CJK input. Changes: - Add composingVersion state to force re-renders on composition events - Check editor content directly in hasComposerPayload - Trigger re-render on compositionStart and compositionEnd --- apps/desktop/src/app/chat/composer/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx index 2288a7b7f82b..91b6e19e46ed 100644 --- a/apps/desktop/src/app/chat/composer/index.tsx +++ b/apps/desktop/src/app/chat/composer/index.tsx @@ -154,6 +154,7 @@ export function ChatBar({ const [focusRequestId, setFocusRequestId] = useState(0) const dragDepthRef = useRef(0) const composingRef = useRef(false) // true during IME composition (CJK input) + const [composingVersion, setComposingVersion] = useState(0) const lastSpokenIdRef = useRef(null) const narrow = useMediaQuery('(max-width: 30rem)') @@ -162,7 +163,7 @@ export function ChatBar({ const slash = useSlashCompletions({ gateway: gateway ?? null }) const stacked = expanded || narrow || tight - const hasComposerPayload = draft.trim().length > 0 || attachments.length > 0 + const hasComposerPayload = draft.trim().length > 0 || attachments.length > 0 || (editorRef.current && composerPlainText(editorRef.current).trim().length > 0) const canSubmit = busy || hasComposerPayload const editingQueuedPrompt = queueEdit ? (queuedPrompts.find(entry => entry.id === queueEdit.entryId) ?? null) : null const busyAction = busy && hasComposerPayload ? 'queue' : 'stop' @@ -1210,9 +1211,11 @@ export function ChatBar({ onBlur={() => window.setTimeout(closeTrigger, 80)} onCompositionEnd={() => { composingRef.current = false + setComposingVersion(v => v + 1) }} onCompositionStart={() => { composingRef.current = true + setComposingVersion(v => v + 1) }} onDragOver={handleInputDragOver} onDrop={handleInputDrop} From ca3e7a2340f9ff16f30d125b6af7ef2eb4d93597 Mon Sep 17 00:00:00 2001 From: FuanSol Date: Sat, 6 Jun 2026 06:40:08 +0800 Subject: [PATCH 2/2] fix: update draft when IME composition ends When IME composition ends, the draft state was not being updated from the editor content. This caused the send button to show correctly but the message wouldn't send when pressing Enter or clicking send. Now we update draftRef and aui composer state when composition ends. --- apps/desktop/src/app/chat/composer/index.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx index 91b6e19e46ed..7a8df345d01d 100644 --- a/apps/desktop/src/app/chat/composer/index.tsx +++ b/apps/desktop/src/app/chat/composer/index.tsx @@ -1211,6 +1211,15 @@ export function ChatBar({ onBlur={() => window.setTimeout(closeTrigger, 80)} onCompositionEnd={() => { composingRef.current = false + // Update draft from editor content when composition ends + const editor = editorRef.current + if (editor) { + const text = composerPlainText(editor) + if (text !== draftRef.current) { + draftRef.current = text + aui.composer().setText(text) + } + } setComposingVersion(v => v + 1) }} onCompositionStart={() => {