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.56k stars 2.9k forks source link

[HOLD for payment][$1000] Web - The popup menu overlaps the + icon on room #21809

Closed kbecciv closed 1 year ago

kbecciv 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. Go to staging dot on web chrome and login with User A
  2. Create a new room in public mode
  3. Go to header and copy the share URL
  4. Important step- Now click on + icon on the room so that a popup menu appears. Notice that the 'Attachment' is shown above the + icon (works well)- Do not click anywhere because it's important to have the popup opened
  5. But now , open another web chrome and login with User B and paste the URL that you copied earlier so that User B can have access to the room
  6. Now on User A side, notice that 'Split bill' also arises on popup and notice that the menu popup overlaps the + icon of the room.
  7. If you click somewhere on the screen and again click on + icon, you'll notice this time, the menu doesn't overlaps the + icon and is shown above it

Expected Result:

The popup menu should not overlap the + icon on room when User B joins it

Actual Result:

The popup menu overlaps the + icon on room

Workaround:

Unknown

Platforms:

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

Version Number: 1.3.33-3 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: Any additional supporting documentation

https://github.com/Expensify/App/assets/93399543/d132a818-32c3-4d38-a355-df0bfe34f660

https://github.com/Expensify/App/assets/93399543/79b704e2-ede9-4d13-bec0-c7669da7247e

Expensify/Expensify Issue URL: Issue reported by: @priya-zha Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1687846865181099

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~01a5b67e57313ec40b
  • Upwork Job ID: 1674159615707922432
  • Last Price Increase: 2023-08-13
  • 2023-07-26
  • Automatic offers:
    • abdulrahuman5196 | Reviewer | 25812254
    • priya-zha | Reporter | 25812259
melvin-bot[bot] commented 1 year ago

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

melvin-bot[bot] commented 1 year ago

Bug0 Triage Checklist (Main S/O)

kushu7 commented 1 year ago

Dupe of https://github.com/Expensify/App/issues/20198 Issue is same about popover

priya-zha commented 1 year ago

This issue is about the position of popover over any chat when split bill is introduced when a user joins and and not about the fluctuating behaviour of popup menu.

sakluger commented 1 year ago

I agree with @priya-zha - this is a different popover (global-add vs in-chat-add) and also different behavior (the other issue is about switching between offline and online, this issue is about what happens when a new user joins a public room).

melvin-bot[bot] commented 1 year ago

Job added to Upwork: https://www.upwork.com/jobs/~01a5b67e57313ec40b

melvin-bot[bot] commented 1 year ago

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

melvin-bot[bot] commented 1 year ago

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

ygshbht commented 1 year ago

Anyone else receiving this error? All my permissions are set to true image

s-alves10 commented 1 year ago

Proposal

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

The popup menu overlaps the + icon on room when menu items are dynamically added

What is the root cause of that problem?

https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L185 In PopoverWithMeasuredContent component, onLayout is called only after the first render. So the width and height are not calculated dynamically when contents are changed, and anchor position won't be changed as well.

This is the root cause

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

We have to recalculate the width and height when contents are changed.

Introducing a new state variable children and remove isContentMeasured state

        this.state = {
            children: this.popoverWidth > 0 && this.popoverHeight > 0 ? props.children : null,
            isVisible: false,
        };

Replace the below code

https://github.com/Expensify/App/blob/be7b6a09cde880cd96470e4e9e0c2f921499dd20/src/components/PopoverWithMeasuredContent.js#L89

with

            return {
                children: lodashGet(props, 'popoverDimensions.width', 0) > 0 && lodashGet(props, 'popoverDimensions.height', 0) > 0 ? props.children : null,
                isVisible: true
            };

Replace the below code

https://github.com/Expensify/App/blob/be7b6a09cde880cd96470e4e9e0c2f921499dd20/src/components/PopoverWithMeasuredContent.js#L115

with

        this.setState({children: this.props.children});

Change the return part of the render function

        return (
            <>
                {this.state.children && (
                    <Popover
                        // eslint-disable-next-line react/jsx-props-no-spreading
                        {...this.props}
                        anchorPosition={shiftedAnchorPosition}
                    >
                        {this.state.children}
                    </Popover>
                )}
                {!_.isEqual(this.state.children, this.props.children) && (
                    <View
                        style={styles.invisible}
                        onLayout={this.measurePopover}
                    >
                        {this.props.children}
                    </View>
                )}
            </>
        );

This works as expected.

Result https://github.com/Expensify/App/assets/126839717/3452c1d9-653d-4c78-86b8-d1d135b8fe5e

What alternative solutions did you explore? (Optional)

ExGraviton commented 1 year ago

I've checked the above proposal, it solves the issue, but it also creates a bug, the popup glitches for a quick second, it's not visible in the above video, because of lower FPS of the video.

Check this high FPS video, in which we can clearly see the glitch.

https://github.com/Expensify/App/assets/69392597/80ff00fe-2c30-4851-b3a1-a2f681be9dab


Also the same result(as s-alves10's proposal) can be achieved by just adding the onLayout in the popup itself.

 <Popover
    // eslint-disable-next-line react/jsx-props-no-spreading
    {...this.props}
    anchorPosition={shiftedAnchorPosition}
 >
+    <View onLayout={this.measurePopover}>
        {this.props.children}
+    </View>
 </Popover>

edit: undo last edit

melvin-bot[bot] commented 1 year ago

📣 @ExGraviton! 📣 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>
ExGraviton commented 1 year ago

Contributor details Your Expensify account email: ExGraviton@gmail.com Upwork Profile Link: https://www.upwork.com/freelancers/~01c4d5a0214da52f73

melvin-bot[bot] commented 1 year ago

✅ Contributor details stored successfully. Thank you for contributing to Expensify!

ExGraviton commented 1 year ago

Proposal

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

Popup menu overlaps the plus icon(actions button) when the menu is dynamically changed after rendering.

What is the root cause of that problem?

The popup menu uses PopoverWithMeasuredContent, which calculates the anchor position only once in the first render, the dynamic changes are not handled by PopoverWithMeasuredContent, which causes the popup to be placed in incorrect position.

https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L168

https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L183-L188

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

We can wrap the contents of Popover in a View with onLayout={this.measurePopover}.

 <Popover
   // eslint-disable-next-line react/jsx-props-no-spreading
   {...this.props}
   anchorPosition={shiftedAnchorPosition}
 >
+    <View onLayout={this.measurePopover}>
       {this.props.children}
+    </View>
  </Popover>

And move popoverWidth and popoverHeight to state.

What alternative solutions did you explore? (Optional)

Calculate the anchor position whenever the content changes.

We can make the following changes in PopoverWithMeasuredContent

Add a new state variable measuredChildren

{ measuredChildren: null }

Set state measuredChildren = this.props.children when the content is measured

this.setState({isContentMeasured: true, measuredChildren: this.props.children});    }

If this.props.children != measuredChildren, recalculate the position again.

return (
    <>
        {this.state.isContentMeasured && (
            <Popover
                // eslint-disable-next-line react/jsx-props-no-spreading
                {...this.props}
                anchorPosition={shiftedAnchorPosition}
            >
                {this.state.measuredChildren || this.props.children}
            </Popover>
        )}
        {!_.isEqual(this.state.measuredChildren, this.props.children) && (
            <View
                style={styles.invisible}
                onLayout={this.measurePopover}
            >
                {this.props.children}
            </View>
        )}
    </>
);
Result(alternate proposal) https://github.com/Expensify/App/assets/69392597/3b8da163-913c-45f5-86c2-5c3a10dcb2a3

The alternate proposal also solves the above mentioned glitch.

sakluger commented 1 year ago

@abdulrahuman5196 what do you think of the proposals so far?

abdulrahuman5196 commented 1 year ago

@s-alves10 From the proposal here https://github.com/Expensify/App/issues/21809#issuecomment-1612257519 I agree there is something going wrong with the position calculation. And I almost agree on the root cause.

But for the solution I wouldn't want to directly compare the children which is essentially a node and doesn't seem to be the optimised way. Maybe some other way of comparing?

abdulrahuman5196 commented 1 year ago

@ExGraviton I don't think we could consider the proposal here https://github.com/Expensify/App/issues/21809#issuecomment-1612735374 a valid new proposal, since it seems to be a minor optimization over the proposal here https://github.com/Expensify/App/issues/21809#issuecomment-1612257519

ExGraviton commented 1 year ago

Hi @abdulrahuman5196, I also proposed that the same solution by just adding the onLayout in the popup itself, can we consider that?

 <Popover
   // eslint-disable-next-line react/jsx-props-no-spreading
   {...this.props}
   anchorPosition={shiftedAnchorPosition}
 >
+    <View onLayout={this.measurePopover}>
       {this.props.children}
+    </View>
  </Popover>
s-alves10 commented 1 year ago

@abdulrahuman5196

Yes. you're right, but PopoverWithMeasuredContent is a general component and there is no assumption on its children. I'm afraid there would no perfect way to compare them.

However, we have some other ways as described here. I think 3rd method is preferred.

Please let me know your thoughts

abdulrahuman5196 commented 1 year ago

@s-alves10 I am unable to understand what you are mentioning on the link?

If it is better could you include the same in your proposal and ping? So that i can review again?

melvin-bot[bot] commented 1 year ago

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

s-alves10 commented 1 year ago

Proposal

Updated

@abdulrahuman5196 I added the clearer way to determine when we should calculate the layout

sakluger commented 1 year ago

@abdulrahuman5196 friendly bump, have you had a chance to review the updated proposal?

ShogunFire commented 1 year ago

onLayout is supposed to be fired when the layout changes https://reactnative.dev/docs/view#onlayout

ShogunFire commented 1 year ago

Proposal

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

The pop up overlaps the + icon when it changes size

What is the root cause of that problem?

The first time we calculate the pop over size we use onLayout here: https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L185

After that we change isContentMeasured to true here: https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L115

Because of that we don't display the View with onLayout anymore, we display the popover that doesn't have onLayout here: https://github.com/Expensify/App/blob/59973575da78597ccac89781b4d7117110b82078/src/components/PopoverWithMeasuredContent.js#L168-L173

Since we don't have onLayout anymore, when the size of the layout changes measurePopover is not called

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

We just need to add onLayout={this.measurePopover} to the Popover component

Result:

https://github.com/Expensify/App/assets/19537677/2bae04e0-a5d0-4e00-a3e5-ba59824461b0

What alternative solutions did you explore? (Optional)

We could get rid of the invisble View since it was made for an animation that is barely visible

ExGraviton commented 1 year ago

Hi, @ShogunFire I already proposed the same solution here and here.

Also adding the onLayout={this.measurePopover} to the Popover component won't work, just try resizing the window. We need to wrap it in view component like this.

ShogunFire commented 1 year ago

@ExGraviton You are right there is a problem on resize, you should update your proposal when you make a new proposition

ShogunFire commented 1 year ago

And then send a comment like this

## Proposal
[Updated](link to proposal)
ExGraviton commented 1 year ago

@ShogunFire Thank you.

ExGraviton commented 1 year ago

Proposal

Updated

ShogunFire commented 1 year ago

@ExGraviton I would have put it as the main one since your main one has already been reviewed and that way you have more space to explain what you are doing.

ExGraviton commented 1 year ago

@ShogunFire Thanks again.

Proposal

Updated

sakluger commented 1 year ago

@abdulrahuman5196 looks like there are quite a few proposal updates, mind giving them a review when you have a chance?

s-alves10 commented 1 year ago

@abdulrahuman5196

Please check the updated proposal.

Some optimizations can be applied but didn't include them. I only added the way how to determine when recalculation should be done

melvin-bot[bot] commented 1 year ago

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

sakluger commented 1 year ago

@abdulrahuman5196 just checking in, could you please take a look at the updated proposals today?

melvin-bot[bot] commented 1 year ago

@sakluger @abdulrahuman5196 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!

s-alves10 commented 1 year ago

@abdulrahuman5196

This is a generic wrapper component and there would no special way to determine when layout should be changed.

melvin-bot[bot] commented 1 year ago

@sakluger, @abdulrahuman5196 Eep! 4 days overdue now. Issues have feelings too...

sakluger commented 1 year ago

@abdulrahuman5196 could you please prioritize this issue?

melvin-bot[bot] commented 1 year ago

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

abdulrahuman5196 commented 1 year ago

Reviewing this issue now

abdulrahuman5196 commented 1 year ago

@ExGraviton your proposal here main solution https://github.com/Expensify/App/issues/21809#issuecomment-1612735374 is not working for me.

abdulrahuman5196 commented 1 year ago

For @s-alves10 proposal here https://github.com/Expensify/App/issues/21809#issuecomment-1612257519, It seems to solve the issue but causes a glitch(even for normal checking) as mentioned by @ExGraviton here https://github.com/Expensify/App/issues/21809#issuecomment-1612729277

abdulrahuman5196 commented 1 year ago

@ShogunFire 's proposal is also the same as this. https://github.com/Expensify/App/issues/21809#issuecomment-1612735374

abdulrahuman5196 commented 1 year ago

I think i covered all the proposals here @sakluger . Currently I don't see any suitable for approval. Can we raise the bounty?

ShogunFire commented 1 year ago

It's strange, the proposal with onLayout is workjng well for us, what platform are you using ?

s-alves10 commented 1 year ago

@abdulrahuman5196

Glitch can be removed by some optimization, I think

abdulrahuman5196 commented 1 year ago

It's strange, the proposal with onLayout is workjng well for us, what platform are you using ?

Firefox