-
Notifications
You must be signed in to change notification settings - Fork 1k
Open
Description
Description
When using the Japanese keyboard on iOS, long-pressing the "next candidate" (次候補) button causes repeated character insertion instead of cycling through candidates normally.
Root Cause
In updateRemoteValueIfNeeded() (raw_editor_state_text_input_client_mixin.dart), the method sends the editing state back to the platform with composing=(-1,-1) even while the IME is actively composing. The iOS platform interprets this as "composing text has been committed" and re-sends the composing text as new input, creating a feedback loop that inserts duplicate characters.
Flow of the bug:
- User types Japanese text → IME composing range is active (e.g.,
composing=(10,12)) - Controller change triggers
updateRemoteValueIfNeeded() - Method builds
actualValuewithcomposing=(-1,-1)(hardcodedTextRange.empty) - Sends this value to platform via
setEditingState() - Platform sees
composing=(-1,-1)→ thinks composing text was committed - Platform re-sends the composing text as new input via
updateEditingValue() - This triggers another controller change → goto step 2
- Result: infinite loop of character insertion
Proposed Fix
During active composing, handle updates selectively instead of always sending composing=(-1,-1):
- Text changed → skip sending (let the platform drive state, prevents the loop)
- Selection-only changed → send with composing range preserved (allows cursor movement within composing region to update conversion candidates)
- Nothing changed → skip (existing equality check)
if (composingRange.isValid && composingRange.end <= value.text.length) {
if (actualValue.text == _lastKnownRemoteTextEditingValue!.text &&
actualValue.selection != _lastKnownRemoteTextEditingValue!.selection) {
_lastKnownRemoteTextEditingValue = actualValue;
_textInputConnection!.setEditingState(actualValue);
}
return;
}Verified behavior
- Long-press "next candidate" → no repeated character insertion ✓
- Cursor movement within composing region → candidates update correctly ✓
- Normal Japanese input (compose → commit) → works ✓
- Candidate selection by tap → works ✓
Steps to Reproduce
- Open a QuillEditor on iOS
- Switch to Japanese keyboard (e.g., Kana input)
- Type some Japanese text (e.g., "なた")
- Long-press the "次候補" (next candidate) button on the keyboard
- Expected: Candidates cycle through without inserting text
- Actual: Characters are repeatedly inserted, filling the editor
Environment
- flutter_quill version: 11.5.0
- Flutter: 3.38.9
- Platform: iOS
- Keyboard: Japanese (Kana)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels