Skip to content

Commit 26ad695

Browse files
authored
Fix Chat Input Crashes on Android (#20058)
* Fix Chat Input Crashes on Android The input was crashing when you sent messages that had modified the native selection props. It crashed when you cleared the text because it would set the text to empty, and reused a cached selection that was out of bounds of an empty string. For example, say you type "hello @" and autocomplete to "hello @foo". We do some text selection magic to insert the @foo and put your cursor in the correct spot. The Selection start and end indicies are both 11. When you submit to message, we clear the text. When we clear the text, RN keeps reusing those selection indices (of 11) and Android complains the selection is outside of the bounds of the text ("" has a length of 0, but you want to move the cursor to position 11, outside the bounds of 0). The workaround here is to set the selection at the same time as the text. The RN Issue is: facebook/react-native#25265 * Apply changes to iOS as well * Update comment * Set lastNativeSelection
1 parent 6c2405a commit 26ad695

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

shared/common-adapters/plain-input.native.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,16 @@ class PlainInput extends Component<InternalProps> {
6666
text: this._lastNativeText || '',
6767
}
6868
const newTextInfo = fn(currentTextInfo)
69+
const newCheckedSelection = this._sanityCheckSelection(newTextInfo.selection, newTextInfo.text)
6970
checkTextInfo(newTextInfo)
70-
this.setNativeProps({text: newTextInfo.text})
71+
// This is to workaround this Issue for Android: https://github.com/imnapo/react-native-cn-richtext-editor/issues/81
72+
// By setting the text and selection at the same time
73+
this.setNativeProps({
74+
selection: newCheckedSelection,
75+
text: newTextInfo.text,
76+
})
7177
this._lastNativeText = newTextInfo.text
72-
this._setSelection(newTextInfo.selection)
78+
this._lastNativeSelection = newCheckedSelection
7379
if (reflectChange) {
7480
this._onChangeText(newTextInfo.text)
7581
}
@@ -87,14 +93,17 @@ class PlainInput extends Component<InternalProps> {
8793
this._setSelection(s)
8894
}
8995

96+
// Validate that this selection makes sense with current value
97+
_sanityCheckSelection = (selection: Selection, nativeText: string): Selection => {
98+
let {start, end} = selection
99+
end = Math.max(0, Math.min(end || 0, nativeText.length))
100+
start = Math.min(start || 0, end)
101+
return {end, start}
102+
}
103+
90104
_setSelection = (selection: Selection) => {
91105
this._setTimeout(() => {
92-
// Validate that this selection makes sense with current value
93-
let {start, end} = selection
94-
const text = this._lastNativeText || '' // TODO write a good internal getValue fcn for this
95-
end = Math.max(0, Math.min(end || 0, text.length))
96-
start = Math.min(start || 0, end)
97-
const newSelection = {end, start}
106+
const newSelection = this._sanityCheckSelection(selection, this._lastNativeText || '')
98107
this.setNativeProps({selection: newSelection})
99108
this._lastNativeSelection = selection
100109
}, 0)

0 commit comments

Comments
 (0)