Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix issue#11068 of duplicating characters when replacing letters to l…
…owercase or uppercase in TextInput (#35929) Summary: These changes are intended to resolve #11068. ## Changelog: [Android] [Fixed] - Fix letters duplication when using autoCapitalize Pull Request resolved: #35929 Test Plan: I took the `RewriteExample` from `TextInputSharedExamples.js` duplicated it, updated the labels, attached to the same screen. Modified its `onChangeText` function, from `text = text.replace(/ /g, '_');` to `text = text.toLowerCase();` then tested via rn-tester as shown in the video: - No duplicate characters - Characters are updated to be lowercase - Long pressing delete properly deletes, doesn’t stop after deleting one character - Suggestions (selected from keyboard) work and are updated to lowercase when it becomes part of the input text - Moving the cursor and typing works, cursor position is kept as it should - Moving the cursor and deleting works - Selection portion and deleting it works, cursor position is kept as it should https://user-images.githubusercontent.com/14225329/213890296-2f194e21-2cf9-493f-a516-5e0212ed070e.mp4 Note: I have tested manually with 0.67.4, because later versions failed on my machine with cmake and argument errors when building the rn-tester from Android Studio to any device. Help regarding that would be appreciated. ## Possible Future Improvements As it can be seen the video, the letter duplication is resolved, however since the lowercase modification happens on the Javascript side, it takes a couple milliseconds and the Uppercase can still be shown momentarily while typing. ## Technical details, why the solution works I've debugged a simple AppCompatEditText with calling the same `getText().replace` in `doAfterTextChanged` with a bit of delay and noticed a difference to the `ReactEditText`. The ReactEditText removes the `android.view.inputmethod.ComposingText` Span in `manageSpans` before calling replace (ComposingText is `Spanned.SPAN_EXCLUSIVE_EXCLUSIVE`). That `ComposingText` Span is used in `android.view.inputmethod.BaseInputConnection` `private replaceText` to find from what point the text should be replaced from when applying suggestions or typing new letters. Without that Span, it defaults to the selection position, which is usually the end of the text causing duplication of the old "word". **In simple terms, while typing with suggestions on the keyboard, each new letter is handled similarly as clicking a suggestion would be, aka replacing the current "word" with the new "word". (let's say "Ar" word with "Are" word)** Another way to describe it: While typing with suggestions, with the ComposingText Span the TextView keeps track of what word completions are suggested for on the keyboard UI. When receiving a new letter input, it replaces the current "word" with a new "word", and without the Span, it replaces nothing at the end (selection point) with the new word which results in character duplication. It also seems to make sense then why without suggestions (like password-visible and secureTextEntry) the issue hasn't occurred. ### Examples How the issue happened: > - User types: A (ComposingText Span becomes (0,1), composingWord: "A") > - Javascript replaced A with a, ComposingText Span was removed from getText() > - User types a new character: r (ComposingText, defaulting to selection, from selection, empty string is replaced with word "Ar") > => Complete text: aAr => letter duplication. How it works with the changes applied: > - User types: A (ComposingText Span becomes (0,1), composingWord: "A") > - Javascript replaces A with a, (ComposingText Span (0,1) is re-set after replace) > - User types a new character: r (ComposingText (0,1), "a" word is replaced with word "Ar". ComposingText becomes (0,2) "Ar") > - Javascript replaced Ar with ar, (ComposingText Span (0,2) is re-set after replace) > => Complete text: ar => no letter duplication > - User selects suggestion "Are" (ComposingText Span (0,2) "ar" is replaced with new word and space "Are ") > - CompleteText: "Are " > - Javascript replaces "Are " with "are " (ComposingText Span doesn't exist, no string after space " ") Note: the Editable.replace also removes the ComposingText, if it doesn't cover the whole text, that's why we need to re-setSpan them even if we wouldn't remove them in `manageSpans`. ## Note This is my first attempt to contribute so if I missed something or messed up, please point out and I will try to adapt. Reviewed By: NickGerleman Differential Revision: D47243817 Pulled By: lunaleaps fbshipit-source-id: 5f3551d17466f2c7cd1aa89ffb09af50e065b52e
- Loading branch information