zulip / zulip-mobile

Zulip mobile apps for Android and iOS.
https://zulip.com/apps/
Apache License 2.0
1.29k stars 652 forks source link

Keyboard state is wrong after picking @-mention or stream from autocomplete #5072

Open gnprice opened 3 years ago

gnprice commented 3 years ago

This issue appears on Android devices using certain keyboards. It does not occur with Gboard, so it does not occur on a typical Pixel device or emulator image.

I just observed this on v27.173 (the current alpha), on a Samsung J5 (model SM-J510FN) running Android 6.0.1. That's the only non-Google Android device I have lying around, but I expect it will repro on current Samsung devices, and likely LG and other vendors too.

Repro steps:

The exact same behavior happens if instead of an @, you type a # and choose a stream from the list, too.

This is on Samsung keyboard 1.5.46 (as found from the gear icon at the bottom of the keyboard > About Samsung keyboard.)


I discovered this while studying #4239, in https://github.com/zulip/zulip-mobile/issues/4239#issuecomment-950039743 and the next two comments. In short, React Native has a bug in the implementation of TextInput where exactly this kind of symptom happens when you update the contents of a TextInput. The bug has been worked around for the specific case of clearing the contents, but for any other update it's still live.

The situation is that the Android docs say that when you're updating the contents of a text input, you should call a certain method to let the input method -- that's the keyboard -- know it should refresh its state. Specifically the documentation for InputMethodManager#restartInput reads:

If the input method is currently connected to the given view, restart it with its new contents. You should call this when the text within your view changes outside of the normal input method or key input flow, such as when an application calls TextView.setText().

And React Native's TextInput does not follow that instruction.

There was a PR sent for this back in 2017: https://github.com/facebook/react-native/pull/12462 The RN maintainers in 2019 were amenable (https://github.com/facebook/react-native/pull/12462#pullrequestreview-193395775), but didn't hear from anyone who would test it out. (At that point in the thread, it was thought that the issue was limited to a few older devices.) So they didn't merge the fix.

Also in 2019, a change was merged in RN (https://github.com/facebook/react-native/pull/18859) which operated in the case where the text was being cleared, i.e. updated to be empty. That change doesn't call restartInput -- it calls setText(null) -- but reportedly that was enough to resolve the issue on some Samsung and LG devices, in the case of clearing the text.

Much later, in 2020-09, a bug was reported in another RN app (https://github.com/status-im/status-react/issues/11216) which had similar symptoms: the keyboard's state doesn't get refreshed when you insert something by picking it from the app's own autocomplete UI. (The details are a bit different; but also the app appears to be doing something more interesting with the text, styling the @-mention with a highlight color.) That issue was observed on Android 8 and Android 9. And it was fixed by… calling restartInput.


Probably the best path to fix this is:

gnprice commented 3 years ago

One other note: It may be possible to reproduce this issue on other Android devices, including the emulator, by installing Samsung Keyboard.

I can't find Samsung Keyboard in either the Play Store nor Samsung's own Galaxy Store. But it does appear here: https://www.apkmirror.com/apk/samsung-electronics-co-ltd/samsung-keyboard/ including version 4.9.00.8, just a few months old.