Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.43k stars 2.8k forks source link

[HOLD] [$2000] single backtick message selection has some extra padding at the top #15078

Closed kavimuru closed 1 year ago

kavimuru commented 1 year ago

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Navigate to any chat
  2. Send text message wrapped in single backtick, e.g. Hello world
  3. Long press the message
  4. Observe the selected message

Expected Result:

The selected area should have the same padding from the top and the bottom from the border

Actual Result:

top has some extra margin than bottom space

Workaround:

unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

Version Number: 1.2.69-2 Reproducible in staging?: y Reproducible in production?: y If this was caught during regression testing, add the test name, ID and link from TestRail: Email or phone of affected tester (no customers): Logs: https://stackoverflow.com/c/expensify/questions/4856 Notes/Photos/Videos:

https://user-images.githubusercontent.com/43996225/218231342-7a8fbeb6-d5b1-42a1-988a-21afae85348d.mp4

web ios

Expensify/Expensify Issue URL: Issue reported by: @jayeshmangwani Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1675802761130049 View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~015c356c51bf928ca6
  • Upwork Job ID: 1626148972311486464
  • Last Price Increase: 2023-02-23
MelvinBot commented 1 year ago

Triggered auto assignment to @sophiepintoraetz (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

MelvinBot commented 1 year ago

Bug0 Triage Checklist (Main S/O)

sophiepintoraetz commented 1 year ago

Came in over the weekend, will look into this tomorow.

sophiepintoraetz commented 1 year ago

Android image

iOS image

MelvinBot commented 1 year ago

Triggered auto assignment to @danieldoglas (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

sophiepintoraetz commented 1 year ago

Seems similar to https://github.com/Expensify/App/issues/15195

danieldoglas commented 1 year ago

Thanks @sophiepintoraetz . This one can be external, so adding the label.

MelvinBot commented 1 year ago

Job added to Upwork: https://www.upwork.com/jobs/~015c356c51bf928ca6

MelvinBot commented 1 year ago

Current assignee @sophiepintoraetz is eligible for the External assigner, not assigning anyone new.

MelvinBot commented 1 year ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @0xmiroslav (External)

MelvinBot commented 1 year ago

Current assignee @danieldoglas is eligible for the External assigner, not assigning anyone new.

bernhardoj commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

There is an extra space above code text and it's noticeable when we highlight it.

What is the root cause of that problem?

On native, we are using WrappedText component to render code block. Inside of it, we wrap the text with 2 views.

https://github.com/Expensify/App/blob/a5b9c9ba88fa0634a963bd248152b79e3006bd6d/src/components/InlineCodeBlock/index.native.js#L6-L24

https://github.com/Expensify/App/blob/a5b9c9ba88fa0634a963bd248152b79e3006bd6d/src/components/InlineCodeBlock/WrappedText.js#L55-L70

The outer view height is 20, while the inner view is 18 with top value is 4 (on iOS, the inner view height is 16). The height difference and the addition of the top is the culprit of this issue.

image

I think the reason we are doing that is to align the code block text well with other text. Here is the comparison.

With top Without top
330826 330827

What changes do you think we should make in order to solve the problem?

To solve this, we can apply a bottom padding to InlineCodeBlock (native). 4 for iOS, 6 for Android. We need to apply different value because iOS codeWordStyle height is 16 while Android is 18. Or we can set both height to 18, so both padding will be 6.

allroundexperts commented 1 year ago

Following.

allroundexperts commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Inline code block is not in the middle of the hovered report item

What is the root cause of that problem?

The root cause of this problem is rendering of View inside Text to display the code tag on native platforms. I'll try to demonstrate the problem here with a small (unrelated) code sample.

Consider the following code:

<Text>
    <Text>Hello world</Text>
    <Text>
        <View>
            <Text>This </Text>
        </View>
        <View>
            <Text>is </Text>
        </View>
        <View>
            <Text>a </Text>
        </View>
        <View>
            <Text>test </Text>
        </View>
    </Text>
</Text>

When this is run on a RN app, it looks like the following:

Screenshot 2023-02-24 at 2 09 43 AM

It is clearly noticeable that the items wrapped in the second text container are higher than the items in the first container. This is exactly what is happening in our app as well. To make the text and code elements inline, we're resorting to the addition of a top property to the code element in order to bring it down. This can be seen here:

https://github.com/allroundexperts/Expensify/blob/660e3892f8a8deace5e24497148a174ee8dde251/src/styles/codeStyles/index.android.js#L7

This addition is what results in a illusion of extra padding at the top of the message.

After removing this property, here is how it looks.

Screenshot 2023-02-24 at 2 20 51 AM

To prove that we are rendering View inside of Text, we can check the contentModel of different tags in the transientRenderEngine library. As seen from the link above, by default, code tag uses Textual content model which gets translated to a Text wrapper element. We're also defining a customer renderer for code tag which can be seen here. This custom renderer is translating each word into a View component. Since the contentModel of code tag is defined as Textual and we're rendering a View inside it, this is where the problem lies. This can be further confirmed by looking at the React Component Tree of one such render.

Screenshot 2023-02-24 at 2 30 50 AM

What changes do you think we should make in order to solve the problem?

Because we're using a View inside of a Text, this forces us to use the top property on the word container which in turn causes this issue. We should not use View inside of a Text element. To make this work, we have to change the contentModel of code tag to block. This can be done by adding following here:

    code: defaultHTMLElementModels.code.extend({
        contentModel: HTMLContentModel.block,
    }),

Next, we need to make sure that we set flexDirection: 'row', flexWrap: 'wrap' of the comment tag wrapper here.

We then need to remove TDefaultRenderer for the code tag here. This is because we don't want our words to be wrapped inside a View (which is then wrapped inside another comment View).

In the same component, we also have to replace {props.defaultRendererProps.tnode.data} with {props.defaultRendererProps.tnode.domNode.children[0].data}. We have to do the same replacement for the web version of this file.

Finally, we also need to remove the hacky styles here and here that we added in order to make View work inside Text.

This is how it looks after the changes mentioned above are applied:

Screenshot 2023-02-24 at 2 47 31 AM Screenshot 2023-02-24 at 2 55 11 AM Screenshot 2023-02-24 at 2 50 04 AM Screenshot 2023-02-24 at 2 55 46 AM

Once these changes are applied, here is how the component tree looks like:

Screenshot 2023-02-24 at 2 52 57 AM

What alternative solutions did you explore? (Optional)

None

danieldoglas commented 1 year ago

@0xmiroslav can you please check both proposals?

0xmiros commented 1 year ago

The outer view height is 20, while the inner view is 18 with top value is 4 (on iOS, the inner view height is 16). The height difference and the addition of the top is the culprit of this issue.

@bernhardoj can you please explain the reason why inner view height is set differently between android and iOS? And what is inner view height on web?

0xmiros commented 1 year ago

@allroundexperts thanks for your deep research. I agree with your root cause analysis. It's known issue that View inside Text doesn't work correctly on native and that's why hacky styles are added. I also confirmed that this is not only android issue but also iOS.

Screenshot 2023-02-24 at 2 30 54 PM

But I still have concerns about your solution, while I like the idea of removing hacky top paddings per platform.

Because we're using a View inside of a Text, this forces us to use the top property on the word container which in turn causes this issue. We should not use View inside of a Text element. To make this work, we have to change the contentModel of code tag to block

Can you please explain why block will work? Is there any documentation in upstream repo? Btw, after updating this, code block never shows for me. Am I missing anything?

We then need to remove TDefaultRenderer for the code tag here. This is because we don't want our words to be wrapped inside a View (which is then wrapped inside another comment View).

You mean to remove TDefaultRenderer wrapper completely?

allroundexperts commented 1 year ago

@allroundexperts thanks for your deep research. I agree with your root cause analysis. It's known issue that View inside Text doesn't work correctly on native and that's why hacky styles are added. I also confirmed that this is not only android issue but also iOS. Screenshot 2023-02-24 at 2 30 54 PM

But I still have concerns about your solution, while I like the idea of removing hacky top paddings per platform.

Because we're using a View inside of a Text, this forces us to use the top property on the word container which in turn causes this issue. We should not use View inside of a Text element. To make this work, we have to change the contentModel of code tag to block

Can you please explain why block will work? Is there any documentation in upstream repo? Btw, after updating this, code block never shows for me. Am I missing anything?

We then need to remove TDefaultRenderer for the code tag here. This is because we don't want our words to be wrapped inside a View (which is then wrapped inside another comment View).

You mean to remove TDefaultRenderer wrapper completely?

@0xmiroslav A block content model results in the element being rendered as a View instead of Text. This will fix the root cause of the issue. That's why we need to change it.

Yes, we have to remove TDefaultRenderer wrapper completely on native. The reason why its not showing up is because I missed a step in the proposal. In the same component, you also have to replace {props.defaultRendererProps.tnode.data} with {props.defaultRendererProps.tnode.domNode.children[0].data}. I've also updated my proposal and added this step. Apologies for the inconvenience this might have caused you.

Please let me know if there is anything else that is of a concern to you.

allroundexperts commented 1 year ago

@0xmiroslav You can also read the docs about the Transient render engine that we use here: https://meliorence.github.io/react-native-render-html/docs/architecture

I think this will provide you of more context of my proposal.

Pujan92 commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Incorrect top for single backtick message which displays it not in the center for native

What is the root cause of that problem?

It seems incorrect top and height are given for the codeWordStyle native files which aren't set them in the center.

What changes do you think we should make in order to solve the problem?

For IOS instead of top 4 set it to 2 which will add height of 16 and keeps 2 at the bottom which makes the message to the center(need to set considering 20px of the parent div). https://github.com/Expensify/App/blob/4d3390b156fcb59e694b0c21193bd699b276bafd/src/styles/codeStyles/index.ios.js#L6-L9

For android do the same setup where either change height to 16and top to 2 or keep the height to 18 with the change of top to 1. (Currently its 4 from the top and height is 18 which sums to 22 and that might be the cause of wrong placement) https://github.com/Expensify/App/blob/4d3390b156fcb59e694b0c21193bd699b276bafd/src/styles/codeStyles/index.android.js#L5-L8

bernhardoj commented 1 year ago

@0xmiroslav I think the inner view height number is "cherry-picked" to prevent the text getting cut off. On Android, setting the height to 16 will make the text cut off.

Edit 1: I just checked on iOS to make sure how it looks with height of 16 and looks like it is also getting cut off, and easily noticeable with an emoji inside the code block because of the fixed line height.

android: 331288

ios: image image

On web, we don't define the height. But looking at the element, the height is 16. The 0.8 is the border width.

image

I'm guessing the initial height set on iOS and Android is taken from web, and then adjusted ~on Android~ to allow the text fully visible.

By the way, there is an existing issue related to the code block which will change the height and top property here. I think we need to wait for it to be merged and adjust the padding bottom based on the new value set.

bernhardoj commented 1 year ago

Great insight @allroundexperts. That would be great if we can remove the style workaround. However, after trying your proposal, the text style is not applied to the text inside code block. The code block text size should be smaller (13). Also, after changing the content model of code to block, the text is empty on web as shown below

image

Maybe because the content model is not textual, the text style is lost? 🤔

allroundexperts commented 1 year ago

code: defaultHTMLElementModels.code.extend({ contentModel: HTMLContentModel.block, }),

@bernhardoj Thanks for pointing this out. I forgot to mention that we have to do the same replacement props.defaultRendererProps.tnode.domNode.children[0].data on web version of the InlineCodeBlock component as well. I have updated the proposal to include this.

In the same [component](https://github.com/allroundexperts/Expensify/blob/cd58bc8ff8e99a5ba61c1f6c0e18b68382753d92/src/components/InlineCodeBlock/index.js#L15), we also have to replace {props.defaultRendererProps.tnode.data} with {props.defaultRendererProps.tnode.domNode.children[0].data}. We have to do the same replacement for the web version of this [file](https://github.com/allroundexperts/Expensify/blob/660e3892f8a8deace5e24497148a174ee8dde251/src/components/InlineCodeBlock/index.js#L15).

I'll check why text styles aren't being applied.

MelvinBot commented 1 year ago

@danieldoglas @sophiepintoraetz @0xmiroslav this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

allroundexperts commented 1 year ago

Another update here. I did some more in depth research about my approach above. It seems like it does not wrap the text correctly. Check the image below for example.

image

As it can be seen, the text does not wrap correctly after the code block. It only comes to the same line as code block if the length of subsequent text is able to fit into the remaining space after code block.

I think that the reason why we added a custom renderer for code block on native platforms is that the default implementation does not allow for adding borders to the code block. We can only add a background colour. Thus, to make it look like the same as on web, we resorted to this custom renderer.

I was then curious on how Slack is solving this issue. It turns out, Slack goes with native implementation of a code block on its Android and iOS apps. For any inline code block, it just sets a background colour without any borders. I have attached a screenshot of a sample code block in Slack both on Android and on web app. The difference is clear enough I think.

Screenshot 2023-02-25 at 5 44 43 PM Screenshot 2023-02-25 at 8 09 39 PM

There might not be a bullet proof solution to solve this issue using custom renderer (Adjusting line heights and paddings might solve this temporarily but IMO something else will come up in the future). I've asked in this thread about what people think of discarding this whole approach of custom renderer for code block and just going with the native implementation (without border). Please do write your opinions in that thread as well.

bernhardoj commented 1 year ago

I found this issue that will add native support for code block to a Text component which probably will fix this issue too. Looks like that issue is going to be resolved soon, so I think we can hold this one until the PR for that issue is merged because this issue is just a minor visual thing.

allroundexperts commented 1 year ago

@bernhardoj This is still a work around. No? Like in that PR, I can see the line heights being tweaked.

allroundexperts commented 1 year ago

Although I haven't tested it fully yet so not sure if this fixes the bug in this ticket.

danieldoglas commented 1 year ago

thanks for connecting that issue here @bernhardoj . I'll put this on hold while we wait for it.

sophiepintoraetz commented 1 year ago

We're still holding.

sophiepintoraetz commented 1 year ago

Still holding

sophiepintoraetz commented 1 year ago

Still holding on https://github.com/Expensify/App/issues/4733

sophiepintoraetz commented 1 year ago

Bumped the CME for that issue. Still holding.

sophiepintoraetz commented 1 year ago

CME is back from holiday

sophiepintoraetz commented 1 year ago

Still holding.

sophiepintoraetz commented 1 year ago

Still holding.

sophiepintoraetz commented 1 year ago

Still holding.

sophiepintoraetz commented 1 year ago

Still holding

danieldoglas commented 1 year ago

Following the new guidelines for external issues, removing myself from this until we have approved proposals.

erikagail-binag commented 1 year ago

The user is reaching out again regarding the issue.

melvin-bot[bot] commented 1 year ago

📣 @erikagail-binag! 📣 Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  2. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  3. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details. Screen Shot 2022-11-16 at 4 42 54 PM Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
sophiepintoraetz commented 1 year ago

Still holding.

sophiepintoraetz commented 1 year ago

OG issue is in review!

sophiepintoraetz commented 1 year ago

Original linked issue has been closed to work on a more holistic solution - so will likely fold this issue into that one and pay out the reporting bonus here.

sophiepintoraetz commented 1 year ago

Thought on this, and this does not seem to be something we will fix for the mean time. If this does get resolved, we can reference this issue for the original reporter. But going to close for now.