slate
slate copied to clipboard
The first letter is typing twice on Android
Description When I type Korean in Android, the first letter is entered twice. You can also check it on slate-react example. You can check it by changing the device to Android in developer tools and then refreshing.
Recording works fine on pc
https://github.com/ianstormtaylor/slate/assets/64782636/fcad5f8e-e0cd-4b4c-a2b1-ab55aa8d4449
but doesn't work on android
https://github.com/ianstormtaylor/slate/assets/64782636/f1179ce5-70b5-4bfe-8d5b-1495443393bc
Steps To reproduce the behavior:
- Go to slate-react-example
- open developer tools
- Change Android device
- Refresh
- Typing
- See the twice typing
Expectation it should be typed only once.
Environment
- Slate Version: "slate": "^0.94.1", "slate-history": "^0.93.0", "slate-hyperscript": "^0.77.0", "slate-react": "^0.98.0",
- Operating System: [e.g. MAC]
- Browser: [e.g. Android, Chrome]
I reproduce this behaviour when composing Chinese Characters in the same env
We are also facing this problem
This is also happening when compose in English
https://github.com/ianstormtaylor/slate/assets/48589760/144e7774-68e2-4938-aeab-590dd9ab9265
Digging into the source code
When the issue occur, the Range.isCollapsed(at)
returns true
at line 74 in text.ts
below
https://github.com/ianstormtaylor/slate/blob/0bdff51a081652000ffa707a15c8878e25d8d357/packages/slate/src/interfaces/transforms/text.ts#L74-L90
At this moment the offset
of anchor
and focus
from at
is both 1 which is unexpected, should be 0 for anchor
and 1 for focus
// should be
{
anchor: {
path: [3, 0],
offset: 0,
},
focus: {
path: [3, 0],
offset: 1,
},
}
// but is
{
anchor: {
path: [3, 0],
offset: 1, <- this is incorrect
},
focus: {
path: [3, 0],
offset: 1,
},
}
The variable at
is from getDefaultInsertLocation
https://github.com/ianstormtaylor/slate/blob/0bdff51a081652000ffa707a15c8878e25d8d357/packages/slate/src/interfaces/transforms/text.ts#L67
Don't know if is something wrong with the normalization
Update, I print out the apply operation from editor below
it seems like there is missing the set_selection
operation at the second try
Update, I print out the apply operation from editor below
it seems like there is missing the
set_selection
operation at the second try
Found out it might be an issue from AndroidInputManager
, because the following if statement is false and will not trigger Transforms.select(editor, range)
when it is going to have duplicated letters
https://github.com/ianstormtaylor/slate/blob/0bdff51a081652000ffa707a15c8878e25d8d357/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts#L178-L180
Maybe we need help from @BitPhinix, the author of AndroidInputManager
Saw this workaround at handleDOMBeforeInput
https://github.com/ianstormtaylor/slate/blob/0bdff51a081652000ffa707a15c8878e25d8d357/packages/slate-react/src/hooks/android-input-manager/android-input-manager.ts#L636-L658
Seems like we need another workaround to modify the start
and end
position, for example
} else if (type === 'insertCompositionText') {
if (_text.length !== _diff.end - _diff.start + 1) {
_diff.start = _diff.end - _text.length + 1
if (_diff.start < 0) {
const offset = Math.abs(_diff.start);
_diff.start += offset;
_diff.end += offset;
}
insertPositionHint = null;
scheduleFlush();
} else {
insertPositionHint = false;
}
}
NOTE: Workaround above has side effects and cannot be used in production.
Does this code change fix the behaviour? Will it be integrated into slate-react?
Facing the issue with Japanese IME too. First try of the fix above is not working. I'll investigate a bit more
Sorry my bad, the workaround above has side effects and cannot be used in production, I'm just trying to declare the position issue from the editor.