Skip to content

fix(desktop): commit IME-composed text on compositionend - #40200

Closed
chajinheon wants to merge 1 commit into
NousResearch:mainfrom
chajinheon:fix/desktop-ime-composition-commit
Closed

fix(desktop): commit IME-composed text on compositionend#40200
chajinheon wants to merge 1 commit into
NousResearch:mainfrom
chajinheon:fix/desktop-ime-composition-commit

Conversation

@chajinheon

@chajinheon chajinheon commented Jun 6, 2026

Copy link
Copy Markdown

Problem

Korean/CJK input in the desktop chat composer is broken: while typing, the last syllable is dropped on send ("글자가 짤려나감"), and input can stall after a few words. This is widely reported across CJK languages but had no merged fix.

Root cause

In Chromium (Electron), the final input event of an IME commit carries isComposing=true. handleEditorInput correctly skips state writes during composition — but no input event follows compositionend. The existing onCompositionEnd handler only flipped composingRef.current = false and never committed the finalized DOM text into draft state.

Result: the committed cluster lives in the contentEditable DOM but never reaches draftRef/the composer store. On submit, submitDraft() reads the stale draft → the trailing syllable is lost. The same stale-draft divergence is why the send button can stay as the voice button (it derives from hasComposerPayload, i.e. draft). ASCII typing is unaffected because isComposing is always false there — which is likely why this survived: contributors typing ASCII never see it.

The existing guards covered "don't submit on Enter mid-composition" but missed "commit the text when composition ends" — the fix completes the other half.

Fix

Extract the input-commit logic into a shared commitEditorState(editor) and invoke it from onCompositionEnd after clearing the composing flag, so IME-finalized text is written to draft state exactly once. No behavior change for non-IME input.

Surgical: two handlers in apps/desktop/src/app/chat/composer/index.tsx, plus a regression test driving the real Chromium IME event order (compositionstartinput{isComposing:true}compositionend).

Related issues

Desktop composer CJK truncation / stale-draft cluster this addresses:

Likely resolved as a side effect (send button stuck on voice/hidden stems from the same empty draft): #39231, #38883, #40146.

Not covered here (different code path): #38117 is the TUI/CLI (prompt_toolkit) analog, not the desktop composer.

Verification

  • npm run type-check — clean
  • eslint on changed files — clean
  • vitest composer suite — 12 passed (10 existing + 2 new)

The regression test reproduces the exact Chromium IME event order. Runtime verification in a packaged build is in progress.

🤖 Generated with Claude Code

Korean/CJK input was truncated and could stall in the chat composer. In
Chromium the final `input` event of an IME commit carries
isComposing=true, so handleEditorInput skips the state write, and no
input event follows compositionend. onCompositionEnd only flipped the
composing flag, so the last composed cluster (e.g. a Korean syllable)
stayed in the DOM but never reached draft state — lost on submit, and a
source of DOM/state divergence that froze further input.

Extract the input commit into commitEditorState and run it from
compositionend so the finalized text is written to draft state. ASCII
typing is unaffected (isComposing is always false). Adds a regression
test driving the real Chromium IME event order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chajinheon

chajinheon commented Jun 6, 2026

Copy link
Copy Markdown
Author

Verified in a packaged build on macOS (arm64, ad-hoc signed --dir pack of this branch).

Typed long Korean sentences with rapid input, e.g. 한글을 사용하면 마지막 문자가 남아있는 버그가 있어:

  • Trailing syllable is no longer dropped on submit — the full message sends intact.
  • No mid-composition input stalls / freezes.
  • No added latency while composing.

For contrast, the current released desktop build (without this change) still drops the trailing syllable on the same input — which is the originally reported symptom.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Fixes IME composition commit on compositionend in desktop composer. Shared commitEditorState helper, regression test included. Clean.

@chajinheon

Copy link
Copy Markdown
Author

Closing as superseded — #40210 landed the same compositionend-commit fix on main first, so this is now redundant and conflicting. Glad the IME truncation is resolved either way. Thanks @tonydwb for the review.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants