zulip-mobile icon indicating copy to clipboard operation
zulip-mobile copied to clipboard

Rich text can be pasted into input box on Android

Open WesleyAC opened this issue 3 years ago • 10 comments

When a user copies and pastes formatted text (for instance, from a web browser), the rich text is pasted into the compose box. This is incorrect, we should strip this formatting instead.

See this CZO thread for details.

The next step here is to look at what we get from onChangeText when rich text is pasted in, since that seems like the most likely route to fix this.

WesleyAC avatar Apr 14 '21 18:04 WesleyAC

  • simple texts are being stored in state,
  • Only the \n next Line is retained by TextInput state

vaibhavs2 avatar Apr 16 '21 02:04 vaibhavs2

@vaibhavs2, it looks like Wesley is specifically asking about what gets passed to onChangeText; could you log all the arguments it's getting called with when you paste rich text in?

chrisbobbe avatar Apr 16 '21 03:04 chrisbobbe

The function has single argument that get passed to onChangeText and from the argument state is getting data that's why I directly comment with state data. log

I tried <TextInput onChangeText={(value)=>{this.setState({message:value})}} multiline style={{borderWidth:2, borderColor:'red',}}> <Text style={{ fontWeight:'bold'}}>hey therer</Text> <Text style = {{color:'red'}}> I don't know what to write</Text> <Text style = {{fontWeight:'bold', fontSize:20}}> I don't know what to write</Text> </TextInput>

Rich text do visible in TextInput but `onChangeText` doesn't return rich text, it gives simple text and that is being stored in state.

simulate

I think TextInput is doing something same under the hood when we paste rich text from somewhere and return us simple text

vaibhavs2 avatar Apr 16 '21 04:04 vaibhavs2

Thanks @vaibhavs2 !

So the answer to what onChangeText gives us is that it's just the plain text.

Which agrees with the RN docs, which say the type it passes to that callback is just string. So that fits, at least.

Given that RN is only actually giving us the plain text, not any of the formatting, it seems like an outright bug in RN that it accepts formatting on paste and shows the formatting in the input.

Though from what we saw in that chat thread linked above, it seems like Android may not give RN an easy way to fix this bug.

I think the next step is to search the RN issue tracker and see if there's an existing issue. If there is, then link to it here.

If there isn't, then the step after that would be to file a good bug report on RN. The key work to do to make a good bug report is that it shouldn't be about Zulip; instead it should have a simple repro, where you link to a tiny new RN app that demonstrates the bug and does nothing else. That way someone interested in fixing the RN bug can focus on that minimal repro.

gnprice avatar Apr 16 '21 05:04 gnprice

Issue Created https://github.com/facebook/react-native/issues/31442

vaibhavs2 avatar Apr 27 '21 10:04 vaibhavs2

As described on this CZO thread, this issue can lead to a very awkward user experience.

Screen capture

alya avatar Oct 25 '21 21:10 alya

For how to go about resolving this issue:

At the Android level, there's a handy solution that @WesleyAC found in a Stack Overflow answer:

A perfect and easy way: Override the EditText's onTextContextMenuItem and intercept the android.R.id.paste to be android.R.id.pasteAsPlainText

This works on Android >= M, which covers all the Android versions we support.

Then to apply that in Zulip:

  • I think the ideal solution is that React Native upstream should apply that fix in the implementation of the TextInput component.

    (It's already the case that the only data TextInput actually exposes to the app is the plain text -- so the fact that it lets the user paste formatted text, and shows that formatting back, is basically a bug in RN because there's no way the app can end up respecting that formatting.)

  • Alternatively, without any changes to RN, I think it should be possible to make our own component with a name like FixedTextInput, using inheritance in the native code to avoid needing to duplicate most of the existing implementation.

    OTOH TextInput has a more complicated implementation than most components, so this may not be simple. The relevant subclass of Android EditText is in ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java, and we should be able to make a pretty simple subclass of that that just adds the needed behavior by overriding onTextContextMenuItem… but then I'm not sure what other scaffolding is needed around that in order to get a React component that can be used in place of the upstream TextInput.

So one route to a fix would be to try the second approach, with a subclass, and then when it's working send a PR upstream to React Native to fix TextInput itself. This would be good, provided that it doesn't end up involving too much extra scaffolding, because it'd mean a straightforward way for us to have the fix immediately while the fix works its way through getting merged upstream and then going into a RN release we upgrade to.

Alternatively, we could go straight for the upstream fix. Then there'd be a lag of a few months before we're on an RN release that has the fix. We could simply accept that lag, or we'd also have the option of switching to our own patched version of RN with the fix applied.

gnprice avatar Aug 02 '22 23:08 gnprice

The upstream issue https://github.com/facebook/react-native/issues/31442 has apparently been fixed! Thanks @vaibhavs2 for filing it :slightly_smiling_face:

gnprice avatar Jul 31 '23 17:07 gnprice

(And from the PR thread — at https://github.com/facebook/react-native/pull/38189#issuecomment-1639757105 and https://github.com/facebook/react-native/pull/38189#pullrequestreview-1542055466 — it's clear that our discussion here was key in getting this fixed, by making it clear why the existing behavior was a bug. So good work everyone.)

gnprice avatar Jul 31 '23 17:07 gnprice

I sent a cherry pick request for this commit in 0.72.4, if they decline the cherry-pick request, we can ask again in the next release 0.73. Thanks a lot for the support! 🙏

fabOnReact avatar Aug 01 '23 04:08 fabOnReact