fix(desktop): respect IME composition in composers - #38800
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Looks Good — minor cosmetic note
Small, well-scoped fix for IME composition handling in the desktop composer. The handleCompositionEnd callback correctly defers the input processing until composition ends, preventing premature submission while the user is composing CJK text.
The blank lines added inside the onSubmit handler (around the composingRef.current guard) are a minor readability nit — consider a comment like // skip submit while IME composition is active to make the intent explicit, but this is not blocking.
✅ Looks Good
- Clean separation of composition lifecycle events
- Reuses existing
composingRefpattern consistently - Low-risk change
Reviewed by Hermes Agent
|
Thanks for the PR! This successfully fixes the text synchronization issue by updating the state right on However, this change alone does not fully prevent the premature message submission on macOS/Chromium. The Problem on macOSOn macOS (Chromium/Electron), the event sequence when pressing
Because Suggested SolutionWe can introduce a transient flag (e.g., Here is the suggested adjustment: 1. Define the ref:const compositionJustEndedRef = useRef(false);2. Update
|
|
Thanks for the detailed macOS/Chromium event-order note. You were right: flipping composingRef on compositionend is not enough because the confirming Enter keydown can arrive immediately after compositionend with isComposing already false. I pushed d276837 to add a short post-composition Enter guard in both the main composer and the edit composer. compositionend still syncs the committed text immediately, but the Enter that confirmed the IME preedit text is ignored for submission. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing the macOS/Chromium event-order detail raised in the discussion. The underlying bug remains on current main: apps/desktop/src/app/chat/composer/index.tsx:727-740 clears composition state before the plain-Enter path at :558-589, and apps/desktop/src/components/assistant-ui/thread/user-edit-composer.tsx:527-576 still submits edits on Enter with no IME guard.
Problems
- The PR has no regression test for the key sequence it fixes:
compositionendimmediately followed by Enter withisComposing === false. Currentapps/desktop/src/app/chat/composer/ime-composition-dom-repro.test.tsx:61-107covers only composition-end text synchronization, and there is no edit-composer IME test. - The head is conflicting.
thread.tsxwas extracted intothread/user-edit-composer.tsxby7ff6908a59536d2d788c8bc9aac64791829dbdeb; current main also already usesflushEditorToDraft()atcomposer/index.tsx:262-278for the earlier composition-end synchronization fix (8e629b9f386d12b726bccb32e9d7b48402ea73ea).
Suggested changes
- Salvage the post-composition Enter guard into both current components and retain the current main-composer flush path.
- Add DOM regressions that verify the confirming Enter does not submit while a subsequent normal Enter does.
Automated hermes-sweeper review.
| @@ -173,6 +174,7 @@ export function ChatBar({ | |||
| const [focusRequestId, setFocusRequestId] = useState(0) | |||
| const dragDepthRef = useRef(0) | |||
There was a problem hiding this comment.
Please add a DOM regression for the macOS sequence this ref protects: composition end, then an immediate Enter with isComposing === false, asserting no submit; also assert a later ordinary Enter submits. The current IME regression test covers finalized-text synchronization only.
|
This fix landed on main via #86760, which consolidated the duplicate PRs for this bug (earliest submission by @satotakumi in #37487; all contributors credited in that PR's body). Closing as the fix is now merged. Thanks for catching it! |
Summary
This improves Desktop composer behavior for CJK and other IME-based input methods.
When typing Japanese, Chinese, Korean, or other text through an IME, Enter is commonly used to confirm the current preedit/composition text. The composer should treat that Enter as part of text input, not as a request to send or submit the message.
This PR:
Why
The main composer already had a composition-aware Enter guard, but composition end did not explicitly flush the finalized text through the same input path. The edit composer also did not track composition state, so confirming CJK preedit text with Enter could be interpreted as submitting the edit.
For CJK users, this makes normal text entry feel unsafe: a user can accidentally send or submit a half-composed message while simply trying to confirm conversion candidates.
Testing
Note: full npm --prefix apps/desktop run lint currently reports unrelated existing lint errors outside this change.