WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit ae1ab7b

Browse files
author
zenggenfa
committed
fix(slate-react): prevent premature flush during composition for Android handwriting input
Fixes #5979 On Android devices, handwriting input on empty lines triggers childList mutations when creating new DOM structure for the first character. These mutations get restored by RestoreDOM during React re-render, which interrupts the IME composition session and causes premature stroke commits (e.g., writing '我' produces '一我'). The fix adds a targeted check in flush() to skip flushing only when: 1. Currently in composition (IS_COMPOSING is true) 2. Cursor is at the first character of an empty line This preserves normal onChange behavior for other scenarios while preventing the handwriting issue on empty lines.
1 parent addf0c5 commit ae1ab7b

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

.changeset/brave-dragons-write.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'slate-react': patch
3+
---
4+
5+
Fix Android handwriting input where first stroke commits prematurely on empty lines (e.g., '我' becomes '一我').
6+
7+
**Cause:** When writing the first character of an empty line, Android handwriting triggers childList mutations (creating new DOM structure). These mutations get restored by RestoreDOM during React re-render, which interrupts the IME composition session.
8+
9+
**Fix:** Skip flush during composition only when at the first character of an empty line. This targeted fix preserves normal onChange behavior for other scenarios while preventing the handwriting issue.
10+

packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,35 @@ export function createAndroidInputManager({
123123
action.run()
124124
}
125125

126+
// Helper: Check if cursor is at the first character of an empty line
127+
const isAtEmptyLineFirstChar = (): boolean => {
128+
const { selection, children } = editor
129+
if (!selection) return false
130+
131+
const { anchor } = selection
132+
// offset should be 0 or 1 (first char)
133+
if (anchor.offset > 1) return false
134+
135+
// Get the block node at current path
136+
const blockPath = anchor.path.slice(0, 1) // Get top-level path
137+
const blockNode = children[blockPath[0]]
138+
if (!blockNode) return true
139+
140+
// Check if this line/block is empty or has only one character
141+
const text = Node.string(blockNode)
142+
return text.length <= 1
143+
}
144+
126145
const flush = () => {
146+
// FIX: Only skip flush during composition for empty line first char scenario.
147+
// Android handwriting input triggers childList mutations when writing the first
148+
// character of an empty line. These mutations get restored by RestoreDOM, which
149+
// interrupts the IME composition and causes premature commits.
150+
// See: https://github.com/ianstormtaylor/slate/issues/5979
151+
if (IS_COMPOSING.get(editor) && isAtEmptyLineFirstChar()) {
152+
return
153+
}
154+
127155
if (flushTimeoutId) {
128156
clearTimeout(flushTimeoutId)
129157
flushTimeoutId = null

0 commit comments

Comments
 (0)