docs/solutions/ui-bugs/2026-05-23-slate-react-android-marked-inserts-must-not-replay-raw-old-leaf-selection.md
Android marked typing can be model-correct while the caret is still wrong. When collapsed typing with active marks splits the current text leaf, any delayed selection restoration based on the old DOM point must be normalized onto the new marked leaf before it reaches the editor.
{ text: "a" }, { text: "w", bold: true }.[0,0]@2, outside the original leaf's
length, instead of [0,1]@1.Keep the Android manager's scheduled action so pending text diffs still flush,
but let the existing at normalization own selection placement. Do not run a
second raw selection write after performAction() normalizes the point.
scheduleAction(() => {}, {
at: newPoint,
preserveInsertPositionHint: true,
})
The focused contract belongs beside the Android input manager tests:
Editor.select(editor, range(1))
Editor.addMark(editor, 'bold', true)
EDITOR_TO_PENDING_INSERTION_MARKS.set(editor, { bold: true })
manager.handleDOMBeforeInput(beforeInputEvent('insertText', 'w'))
manager.flush()
expect(Editor.getSnapshot(editor).selection).toEqual({
anchor: { path: [0, 1], offset: 1 },
focus: { path: [0, 1], offset: 1 },
})
performAction() already normalizes pending points through
normalizePoint(editor, action.at). For old point [0,0]@2, normalization walks
past the old one-character leaf and lands on the inserted marked sibling at
[0,1]@1.
The previous scheduled action then immediately overwrote that normalized
selection by calling tx.selection.set(...) with the raw old point. Removing
that second write preserves the correct normalized result and keeps the flush
timing behavior.
selection.set(...) writes.#6022: Android keyboard dismissal after collapsed mark toggle.#6027: upstream PR evidence for the same stale follow-up selection class.