Skip to content

fix: send button not switching from voice button during IME composition - #40148

Closed
FuanSol wants to merge 2 commits into
NousResearch:mainfrom
FuanSol:fix/ime-composition-send-button
Closed

fix: send button not switching from voice button during IME composition#40148
FuanSol wants to merge 2 commits into
NousResearch:mainfrom
FuanSol:fix/ime-composition-send-button

Conversation

@FuanSol

@FuanSol FuanSol commented Jun 5, 2026

Copy link
Copy Markdown

Description

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

  1. Add composingVersion state - A dummy counter to force React re-renders when composition state changes
  2. Check editor content directly - hasComposerPayload now also checks if the editor has content via composerPlainText(editorRef.current)
  3. Trigger re-renders on composition events - Both onCompositionStart and onCompositionEnd now call setComposingVersion(v => v + 1) to force a re-render

Testing

  • Tested with Microsoft Pinyin IME on Windows 10
  • Voice button now switches to send button immediately when starting to type
  • No flickering when committing Chinese characters
  • English/number input still works as before

Code Changes

// Add state for forcing re-renders
const [composingVersion, setComposingVersion] = useState(0)

// Check editor content directly in hasComposerPayload
const hasComposerPayload = draft.trim().length > 0 || 
                          attachments.length > 0 || 
                          (editorRef.current && composerPlainText(editorRef.current).trim().length > 0)

// Trigger re-render on composition events
onCompositionStart={() => {
  composingRef.current = true
  setComposingVersion(v => v + 1)
}}
onCompositionEnd={() => {
  composingRef.current = false
  setComposingVersion(v => v + 1)
}}

…on (CJK input)

Fixes NousResearch#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
@FuanSol

FuanSol commented Jun 5, 2026

Copy link
Copy Markdown
Author

Detailed Explanation of the Flickering Issue

The flickering occurs during the IME composition lifecycle:

Timeline of the Bug

  1. User starts typing pinyincompositionstart fires → composingRef.current = true
  2. During compositionhandleEditorInput returns early (skips updating draft)
  3. User commits Chinese character (presses space) → compositionend fires → composingRef.current = false
  4. At this exact moment:
    • draft is still empty (wasn't updated during composition)
    • composingRef.current is now false
    • hasComposerPayload = draft.trim().length > 0 || attachments.length > 0 evaluates to false
    • Button switches back to voice button ← This is the flicker!
  5. Immediately after: input event fires → handleEditorInput updates draft
  6. Button switches back to send button

Visual Representation

Time:     |---composition---|---commit---|---after---|
Button:   [SEND]            [VOICE]      [SEND]
                      ↑
              Flicker happens here

Why the Fix Works

By checking editorRef.current && composerPlainText(editorRef.current).trim().length > 0 directly, we read the editor's actual content instead of relying on the draft state. This ensures the button stays as "send" throughout the entire composition lifecycle, eliminating the flicker.

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.
@FuanSol FuanSol closed this Jun 5, 2026
@FuanSol
FuanSol deleted the fix/ime-composition-send-button branch June 5, 2026 23:24
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 5, 2026
@FuanSol
FuanSol restored the fix/ime-composition-send-button branch June 5, 2026 23:28
@FuanSol FuanSol reopened this Jun 5, 2026
@FuanSol

FuanSol commented Jun 5, 2026

Copy link
Copy Markdown
Author

Sorry, after fixing this issue, another problem was discovered: when entering non-English characters, they cannot be sent directly. You must add a number or an English character after them for the input to be sent. I was worried that this might be caused by the change I made, so I closed the PR. However, after trying, I can't fix it in a short time. So, after some thought, I decided to raise the issue and reopen the PR.

@alt-glitch alt-glitch added comp/desktop Electron desktop app (apps/desktop/*) and removed comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 26, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the careful IME lifecycle analysis. This is now implemented on current main.

  • apps/desktop/src/app/chat/composer/index.tsx:727-738 clears the composition flag and synchronously flushes the live editor text into composer state on compositionend, covering both the send-button visibility problem and the follow-up direct-submission problem described in the discussion.
  • apps/desktop/src/app/chat/composer/ime-composition-dom-repro.test.tsx:61-106 covers committed Chinese, Japanese, and Korean text when no trailing input event is emitted.
  • The implementation shipped in 8e629b9f386d12b726bccb32e9d7b48402ea73ea (fix(desktop): flush committed IME text on compositionend so the send button appears) and is contained in release tag v2026.6.19.

Automated hermes-sweeper review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop app: Send button doesn't switch from voice button when typing Chinese (IME composition)

3 participants