Repository navigation
Conversation
Sending while the IME still had marked text cleared the draft in JS, but the native editor skipped every controlled update during composition. The text stayed on screen, and committing the composition emitted it back into the draft, where it persisted. Defer only when JS echoes the text being composed; a different value commits the composition and is applied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused iOS composer bug fix that preserves IME composition updates while ensuring deliberate controlled replacements, such as clearing after send, take effect immediately. It is limited to one function and introduces no schema, configuration, security, or deployment changes. You can add or adjust custom eligibility rules. Learn more. |
|
Closing in favor of #26452. Device logging showed the leftover text in #20982 comes from the composition being committed by the post-send blur, after the clear, not from a clear arriving mid-composition. Committing the composition when the send reads the editor state fixes it: #26452 (comment) |
|
Heads-up on overlap: I opened #26504 for the same #20982 symptom before realizing this PR was already open. My branch (fork Triage on #26504 asked for coordination on the superseded overlap, so: happy to rebase the extra gating onto this PR if it lands first, or fold this PR's additions here, whichever the maintainers prefer. The device evidence situation is the same for both branches; a recording on whichever build lands would cover the shared core. |
|
Thanks for the heads-up. #22843 stays closed, so there's nothing to coordinate on this branch. One thing to check before you record: #22843 took the same approach as #26504, and I closed it because device logging showed a different order. The post-send blur commits the composition before the cleared document reaches the view, so by the time the clear arrives there is no marked text left for that path to handle, and the commit's change event has already refilled the draft. I haven't run #26504 on a device, so please confirm against that ordering. Committing the composition when the send reads the editor state avoided it in my testing: #26452 (comment). Your gating and the fail-safe for a failed |
Problem
On iOS, sending a message while the keyboard still has uncommitted IME text (for example Japanese kana that has not been converted yet) delivers the message but leaves the text in the composer. The leftover text is saved as the draft, so it is still there after leaving and reopening the thread.
Repro on the Japanese kana keyboard: type 「たかな」 without committing it, tap Send. The message appears in the thread, the composer still shows 「たかな」, and Send stays enabled.
Change
#17614 made
applyControlledDocumentskip every controlled update while marked text exists, so that rebuilding the attributed string does not tear down an active composition. Send clears the draft in JS, but that clear arrives during the composition and is skipped. When the composition commits later, the editor emits the old text back and it becomes the draft again.The editor now only defers while JS echoes the text being composed, which is the case #17614 protects (re-rendering pills next to the composition). A different value is a deliberate replacement such as the send clear: the editor commits the composition with change events suppressed and applies the value. Android replaces the text during composition already and is not affected.
Scope and approval
A small, focused fix for an obvious iOS-only regression from #17614, in one function of the iOS composer editor.
Verification
Both shots were taken after sending uncommitted kana, going back to the thread list, and reopening the thread. iOS 27 simulator with the dev client and the Japanese kana keyboard, using the same build with and without this change. Also checked on the fixed build:
Not checked: the original #17614 case (Chinese input right before a skill pill). That case echoes the composing text, which still takes the deferred path.
Done with Claude Opus 5.5 in Claude Code (via T3 Code).
🤖 Generated with Claude Code