1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-11 09:43:58 +02:00

Fix Android cursor jumping to word start after autocorrect (#5901)

* Enhance Android input manager to store current selection before applying diffs and ensure correct selection position post-update.

* Add autocorrect test case to Android input examples

This update introduces a new test case for autocorrect functionality in both JavaScript and TypeScript examples. The test case instructs users to type "Cant" and verify the cursor position after autocorrection.

* Add changeset

* Remove unnecessary comments

* Drop pending selection change on programatic text insert
This commit is contained in:
Bartosz Legięć
2025-06-26 20:49:17 +02:00
committed by GitHub
parent aa27c2dfaf
commit 5a20ea3ad8
5 changed files with 63 additions and 2 deletions

View File

@@ -0,0 +1,5 @@
---
'slate-react': patch
---
Fix Android cursor jumping to word start after autocorrect

View File

@@ -689,7 +689,25 @@ export function createAndroidInputManager({
} }
if (canStoreDiff) { if (canStoreDiff) {
const currentSelection = editor.selection
storeDiff(start.path, diff) storeDiff(start.path, diff)
if (currentSelection) {
const newPoint = {
path: start.path,
offset: start.offset + text.length,
}
scheduleAction(
() => {
Transforms.select(editor, {
anchor: newPoint,
focus: newPoint,
})
},
{ at: newPoint }
)
}
return return
} }
} }

View File

@@ -1,6 +1,6 @@
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { BaseEditor, Node } from 'slate' import { BaseEditor, Node } from 'slate'
import { withDOM } from 'slate-dom' import { withDOM, IS_ANDROID, EDITOR_TO_PENDING_SELECTION } from 'slate-dom'
import { ReactEditor } from './react-editor' import { ReactEditor } from './react-editor'
import { REACT_MAJOR_VERSION } from '../utils/environment' import { REACT_MAJOR_VERSION } from '../utils/environment'
import { getChunkTreeForNode } from '../chunking' import { getChunkTreeForNode } from '../chunking'
@@ -21,10 +21,24 @@ export const withReact = <T extends BaseEditor>(
e = withDOM(e, clipboardFormatKey) e = withDOM(e, clipboardFormatKey)
const { onChange, apply } = e const { onChange, apply, insertText } = e
e.getChunkSize = () => null e.getChunkSize = () => null
if (IS_ANDROID) {
e.insertText = (text, options) => {
// COMPAT: Android devices, specifically Samsung devices, experience cursor jumping.
// This issue occurs when the insertText function is called immediately after typing.
// The problem arises because typing schedules a selection change.
// However, this selection change is only executed after the insertText function.
// As a result, the already obsolete selection is applied, leading to incorrect
// final cursor position.
EDITOR_TO_PENDING_SELECTION.delete(e)
return insertText(text, options)
}
}
e.onChange = options => { e.onChange = options => {
// COMPAT: React < 18 doesn't batch `setState` hook calls, which means // COMPAT: React < 18 doesn't batch `setState` hook calls, which means
// that the children and selection can get out of sync for one render // that the children and selection can get out of sync for one render

View File

@@ -173,6 +173,18 @@ const TEST_CASES = [
}, },
], ],
}, },
{
id: 'autocorrect',
name: 'Autocorrect',
instructions:
'Type "Cant", then press space to autocorrect it. Make sure the cursor position is correct (after the autocorrected word)',
value: [
{
type: 'paragraph',
children: [{ text: '' }],
},
],
},
] ]
const AndroidTestsExample = () => { const AndroidTestsExample = () => {
const [testId, setTestId] = useState( const [testId, setTestId] = useState(

View File

@@ -180,6 +180,18 @@ const TEST_CASES: AndroidTestCase[] = [
}, },
], ],
}, },
{
id: 'autocorrect',
name: 'Autocorrect',
instructions:
'Type "Cant" (make sure to misspell it), then press space to autocorrect it. Make sure the cursor position is correct (after the autocorrected word)',
value: [
{
type: 'paragraph',
children: [{ text: '' }],
},
],
},
] ]
const AndroidTestsExample = () => { const AndroidTestsExample = () => {