Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.

Commit b4e2a2d

Browse files
nmnfacebook-github-bot
authored andcommitted
Fix iOS double-space quick-type bug
Summary: Using a Pull Request from github that was made to fix this very bug, I was able to patch the code and fix the problem for us in the meantime. Since the open-source and internal codebases are totally out of sync, it's not easy to merge the original PR right now. #1152 Reviewed By: claudiopro Differential Revision: D20016281 fbshipit-source-id: aeefd5c3f17c51c62dd5d7c225cf62d0cd2db26f
1 parent 9ab5c5e commit b4e2a2d

File tree

1 file changed

+38
-5
lines changed

1 file changed

+38
-5
lines changed

src/component/handlers/composition/DraftEditorCompositionHandler.js

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const RESOLVE_DELAY = 20;
4646
let resolved = false;
4747
let stillComposing = false;
4848
let domObserver = null;
49+
let beforeInputData = null;
50+
let compositionEndData = null;
4951

5052
function startDOMObserver(editor: DraftEditor) {
5153
if (!domObserver) {
@@ -55,11 +57,14 @@ function startDOMObserver(editor: DraftEditor) {
5557
}
5658

5759
const DraftEditorCompositionHandler = {
60+
onBeforeInput(_editor: DraftEditor, e: SyntheticInputEvent<>): void {
61+
beforeInputData = (beforeInputData || '') + e.data;
62+
},
5863
/**
5964
* A `compositionstart` event has fired while we're still in composition
6065
* mode. Continue the current composition session to prevent a re-render.
6166
*/
62-
onCompositionStart: function(editor: DraftEditor): void {
67+
onCompositionStart(editor: DraftEditor): void {
6368
stillComposing = true;
6469
startDOMObserver(editor);
6570
},
@@ -78,9 +83,13 @@ const DraftEditorCompositionHandler = {
7883
* twice could break the DOM, we only use the first event. Example: Arabic
7984
* Google Input Tools on Windows 8.1 fires `compositionend` three times.
8085
*/
81-
onCompositionEnd: function(editor: DraftEditor): void {
86+
onCompositionEnd(editor: DraftEditor, e: SyntheticInputEvent<>): void {
8287
resolved = false;
8388
stillComposing = false;
89+
90+
// Use e.data from the first compositionend event seen
91+
compositionEndData = compositionEndData ?? e?.data ?? null;
92+
8493
setTimeout(() => {
8594
if (!resolved) {
8695
DraftEditorCompositionHandler.resolveComposition(editor);
@@ -95,7 +104,7 @@ const DraftEditorCompositionHandler = {
95104
* the arrow keys are used to commit, prevent default so that the cursor
96105
* doesn't move, otherwise it will jump back noticeably on re-render.
97106
*/
98-
onKeyDown: function(editor: DraftEditor, e: SyntheticKeyboardEvent<>): void {
107+
onKeyDown(editor: DraftEditor, e: SyntheticKeyboardEvent<>): void {
99108
if (!stillComposing) {
100109
// If a keydown event is received after compositionend but before the
101110
// 20ms timer expires (ex: type option-E then backspace, or type A then
@@ -116,7 +125,7 @@ const DraftEditorCompositionHandler = {
116125
* characters that we do not want. `preventDefault` allows the composition
117126
* to be committed while preventing the extra characters.
118127
*/
119-
onKeyPress: function(editor: DraftEditor, e: SyntheticKeyboardEvent<>): void {
128+
onKeyPress(_editor: DraftEditor, e: SyntheticKeyboardEvent<>): void {
120129
if (e.which === Keys.RETURN) {
121130
e.preventDefault();
122131
}
@@ -137,7 +146,7 @@ const DraftEditorCompositionHandler = {
137146
* Resetting innerHTML will move focus to the beginning of the editor,
138147
* so we update to force it back to the correct place.
139148
*/
140-
resolveComposition: function(editor: DraftEditor): void {
149+
resolveComposition(editor: DraftEditor): void {
141150
if (stillComposing) {
142151
return;
143152
}
@@ -146,12 +155,36 @@ const DraftEditorCompositionHandler = {
146155
domObserver = null;
147156
resolved = true;
148157

158+
const composedChars = beforeInputData ?? compositionEndData;
159+
beforeInputData = null;
160+
compositionEndData = null;
161+
149162
let editorState = EditorState.set(editor._latestEditorState, {
150163
inCompositionMode: false,
151164
});
152165

153166
editor.exitCurrentMode();
154167

168+
if (composedChars != null) {
169+
const currentStyle = editorState.getCurrentInlineStyle();
170+
const entityKey = getEntityKeyForSelection(
171+
editorState.getCurrentContent(),
172+
editorState.getSelection(),
173+
);
174+
// If characters have been composed, re-rendering with the update
175+
// is sufficient to reset the editor.
176+
const contentState = DraftModifier.replaceText(
177+
editorState.getCurrentContent(),
178+
editorState.getSelection(),
179+
composedChars,
180+
currentStyle,
181+
entityKey,
182+
);
183+
editor.update(
184+
EditorState.push(editorState, contentState, 'insert-characters'),
185+
);
186+
}
187+
155188
if (!mutations.size) {
156189
editor.update(editorState);
157190
return;

0 commit comments

Comments
 (0)