Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Popover fixes on tablet #7985

Closed
wants to merge 26 commits into from

Conversation

srdjanrist
Copy link

@srdjanrist srdjanrist commented Mar 2, 2022

Details

I have changed how popovers are shown on iPad medium and large devices. Since these are considered as native, sometimes popovers were shown bottom docked modals, instead of onscreen modals. Medium and large devices are considered as being "not-small" and this flag (of not being small) with a combination of native methods caused inconsistencies in different places that popovers are shown.

Fixed Issues

$ #7375

Tests


  1. Click plus on list of all chats
  2. Observe popover behavior

  1. Open single chat
  2. Click plus beside compose message
  3. Observe popover behavior

  1. Follow previous steps
  2. Click attachment
  3. Observe popover behavior

  1. Open workspaces
  2. Click three dots
  3. Observe popover behavior

  1. Open single workspace
  2. Click on image
  3. Observe popover behavior

  1. Open user settings
  2. Click on image to change it
  3. Observe popover behavior

  1. Open user settings
  2. Click on payments
  3. Click on "Add payment method"
  4. Observe popover behavior

  • Verify that no errors appear in the JS console

PR Review Checklist

Contributor (PR Author) Checklist

  • I made sure to pull main before submitting my PR for review
  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I clearly indicated the environment tests should be run in (Staging vs Production)
  • I wrote testing steps that cover success & fail scenarios (if applicable)
  • I ran the tests & they passed on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified there are no console errors related to changes in this PR
  • I followed proper code patterns (see Reviewing the code)
    • I added comments when the code was not self explanatory
    • I put all copy / text shown in the product in all src/languages/* files (if applicable)
    • I followed proper naming convention for platform-specific files (if applicable)
    • I followed style guidelines (in Styling.md) for all style edits I made
  • I followed the guidelines as stated in the Review Guidelines

PR Reviewer Checklist

  • I verified the Author pulled main before submitting the PR
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the testing environment is mentioned in the test steps
  • I verified testing steps cover success & fail scenarios (if applicable)
  • I verified tests pass on all platforms & I tested again on all platforms
  • I checked that screenshots or videos are included for tests on all platforms
  • I verified there are no console errors related to changes in this PR
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified comments were added when the code was not self explanatory
    • I verified any copy / text shown in the product was added in all src/languages/* files (if applicable)
    • I verified proper naming convention for platform-specific files was followed (if applicable)
    • I verified style guidelines were followed
  • I verified that this PR follows the guidelines as stated in the Review Guidelines

QA Steps


  1. Click plus on list of all chats
  2. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Open single chat
  2. Click plus beside compose message
  3. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Follow previous steps
  2. Click attachment
  3. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Open workspaces
  2. Click three dots
  3. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Open single workspace
  2. Click on image
  3. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Open user settings
  2. Click on image to change it
  3. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  1. Open user settings
  2. Click on payments
  3. Click on "Add payment method"
  4. Verify that popover appears as modal on wide screens, and bottom docked on narrow screens

  • Verify that no errors appear in the JS console

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web 1-web-plus _ 2-web-chat-plus _ 3-web-call-options _ 4-web-workspace-threedots _ 5-web-workspace-image _ 6-web-profile-image _ 7-web-payment
Mobile web 8-mobile-web-plus _ 9-mobile-web-chat-plus _ 10-mobile-web-call-options _ 11-mobile-web-workspace-threedots _ 12-mobile-web-workspace-image _ 13-mobile-web-profile-image _ 14-mobile-web-payment _
Desktop 1-desktop-wide-plus _ 2-desktop-wide-chat-plus _ 3-desktop-wide-workspace-threedots _ 4-desktop-wide-workspace-image _ 5-desktop-wide-profile-image _ 6-desktop-wide-payment
iOS 1-iphone-plus 2-iphone-chat-plus 3-iphone-attachment 4-iphone-workspace-threedots 5-iphone-workspace-image 6-iphone-profile-image 7-iphone-payment
iPad Narrow 1-ipad-narrow-plus 2-ipad-narrow-chat-plus 3-ipad-narrow-attachment 4-ipad-narrow-workspace-threedots 5-ipad-narrow-workspace-image 6-ipad-narrow-profile-image 7-ipad-narrow-payment
iPad Wide 1-ipad-wide-plus 2-ipad-wide-chat-plus 3-ipad-wide-attachment 4-ipad-wide-workspace-threedots 5-ipad-wide-workspace-image 6-ipad-wide-profile-image 7-ipad-wide-payment
Android 1-android-plus 2-android-chat-plus 3-android-attachment 4-android-workspace-threedots 5-android-workspace-image 6-android-profile-image 7-android-payment

@srdjanrist srdjanrist requested a review from a team as a code owner March 2, 2022 18:02
@MelvinBot MelvinBot requested review from Julesssss and parasharrajat and removed request for a team March 2, 2022 18:02
Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing QA Steps.

image

Fix it please.

@srdjanrist
Copy link
Author

Missing QA Steps.

image

Fix it please.

I have updated QA steps.

@parasharrajat
Copy link
Member

parasharrajat commented Mar 3, 2022

image

This is still not fixed. Do not use MD link format. Directly use the link as $ https://github.com/Expensify/App/issues/7375

@srdjanrist
Copy link
Author

image

This is still not fixed. Do not use MD link format. Directly use the link as $ https://github.com/Expensify/App/issues/7375

Updated.

@parasharrajat
Copy link
Member

parasharrajat commented Mar 3, 2022

Thanks for the hard work on the PR @srdjanrist. Could you please help me understand the motive and your approach behind the changes you have done?

There are a lot of images. Please use


<details>
<summary>Details</summary>



</details>

to group them. Thanks.

@srdjanrist
Copy link
Author

Thanks for the hard work on the PR @srdjanrist. Could you please help me understand the motive and your approach behind the changes you have done?

Looking into component Popover native implementation, you can see on line 20 and 21, that depending on fromSidebarMediumScreen prop, either popover modal or bottom docked modal is used.
This issue occurs on iPads with diagonal greater than 9.7", and they are considered medium screen-sized.
Due to them being medium, they should behave like on web, meaning they should use popover modal, instead of bottom docked modal.
Adding property fromSidebarMediumScreen with proper value, I have resolved the issue, so that on the screens I mentioned, bottom-docked modal is not used, but a proper, popover modal is used in the problematic locations.

Simply adding property fromSidebarMediumScreen resolved the issue, since before
props.fromSidebarMediumScreen ? CONST.MODAL.MODAL_TYPE.POPOVER : CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED (this is taken from the code), it would fallback to bottom-docked modal, when this property wasn't set.

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many lint errors. Please fix those. Are you following the contribution guidelines? Please run npm run lint before pushing chnages.

I think the simplest way to do it would be to modify the Popover Component so that we do

 <Modal
            type={!props.isSidebarScreenWidth ? CONST.MODAL.MODAL_TYPE.POPOVER : CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED}

instead of passing fromSidebarMediumScreen which is basically doing the same.

Also, this prop is not defined in the prop definitions. If there is a reason to keep it, please add prop-types for it in every component it is passed as a prop.

@@ -42,6 +42,7 @@ const AddPaymentMethodMenu = props => (
isVisible={props.isVisible}
onClose={props.onClose}
anchorPosition={props.anchorPosition}
fromSidebarMediumScreen={!props.isSmallScreenWidth}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to pass this when you have already added to BasePopoverMenu

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This will be removed.

onModalHide={this.onModalHide}
anchorPosition={this.props.anchorPosition}
fromSidebarMediumScreen={!this.props.isSmallScreenWidth}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this prop related to this menu? This menu opens from the composer ➕ .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The menu for attachment picker opens from the same position as the one from the composer ➕.

Comment on lines 1055 to 1057
createPaymentMethodMenuContainer: {
top: 380,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why do we need to pass the width now. If it was working fine on web without it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because let position = getClickedElementLocation(nativeEvent); has native implementation which returns just { bottom: 0, left: 0 }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use https://reactnative.dev/docs/0.64/pressevent to calculate the values?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@parasharrajat Thanks for the docs.
Looking at the example:

{
    changedTouches: [PressEvent],
    identifier: 1,
    locationX: 8,
    locationY: 4.5,
    pageX: 24,
    pageY: 49.5,
    target: 1127,
    timestamp: 85131876.58868201,
    touches: []
}

we could theoretically calculate the top left coordinate of the pressed component, by using pageX, pageY and locationX, locationY. We would still need to add a height value of the pressed component to y coordinate, to move the popover to its bottom.
What do you think about that?

Copy link
Member

@parasharrajat parasharrajat Mar 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I think that's fine if height is needed let's calculate it. But I don't think that is needed. Setting the top and left edges should be fine. the menu will always be rendered top-down so we should be good without height.

@srdjanrist
Copy link
Author

There are many lint errors. Please fix those. Are you following the contribution guidelines? Please run npm run lint before pushing chnages.

I think the simplest way to do it would be to modify the Popover Component so that we do

 <Modal
            type={!props.isSidebarScreenWidth ? CONST.MODAL.MODAL_TYPE.POPOVER : CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED}

instead of passing fromSidebarMediumScreen which is basically doing the same.

Also, this prop is not defined in the prop definitions. If there is a reason to keep it, please add prop-types for it in every component it is passed as a prop.

Yes. This could be done that way. Would you like this prop isSidebarScreenWidth to be passed from outer component, or should I wrap Popover with withWindowDimensions, so it has properties from window dimensions?

@parasharrajat
Copy link
Member

Wrapping with withWindowDimensions is fine.

@@ -3,7 +3,7 @@ import React from 'react';
import {propTypes as popoverPropTypes, defaultProps} from './popoverPropTypes';
import CONST from '../../CONST';
import Modal from '../Modal';
import {windowDimensionsPropTypes} from '../withWindowDimensions';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';

const propTypes = {
...(_.omit(popoverPropTypes, _.keys(windowDimensionsPropTypes))),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs correction now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. I have left only that propTypes from popoverPropTypes without omitting windowDimensionsProps

return {
bottom: 0,
left: 0,
bottom: nativeEvent.nativeEvent.pageY - nativeEvent.nativeEvent.locationY,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativeEvent.nativeEvent looks confusing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Based on previous handling of this, I have changed the code that calls this method to pass the nested nativeEvent property instead of the whole object.

@@ -186,7 +186,10 @@ class AvatarWithImagePicker extends React.Component {
: (
<DefaultAvatar />
)}
<AttachmentPicker type={CONST.ATTACHMENT_PICKER_TYPE.IMAGE}>
<AttachmentPicker
anchorPosition={styles.createMenuPositionProfile}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
anchorPosition={styles.createMenuPositionProfile}
anchorPosition={this.props.anchorPosition}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

onModalHide={this.onModalHide}
anchorPosition={this.props.anchorPosition}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you add the new prop definition?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the prop definiton.

@srdjanrist
Copy link
Author

@parasharrajat
Thanks for the videos.
I might have misunderstood something then.
The fadein-fadeout animation is only on native platforms.

Second video shows Android, and the animation is present. Is it not supposed to be there?

@parasharrajat
Copy link
Member

The motive is to keep the same animation on all platforms. When Menu opens from bottom on Mobile native, the animation is differnt. But when they behave like a web on tablets. They should have same animations.

cc: @Expensify/design

@shawnborton
Copy link
Contributor

I agree with that Rajat.

@srdjanrist
Copy link
Author

Thanks for the input!
I have updated the pull request with a new commit that handles animations on smaller screen sizes on web.
My tests have went over few devices with various sizes, and I couldn't find any inconsistencies now.
Please, double check this @parasharrajat, so that we can proceed.

Comment on lines 113 to 114
animationInTiming={this.props.disableAnimation ? 1 : this.props.animationInTiming}
animationOutTiming={this.props.disableAnimation ? 1 : this.props.animationOutTiming}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not happy with this change. Can't we just follow the same pattern as we do on the web?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the pull request with a recommended change. 😊

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks fine. I will test it shortly.

@parasharrajat
Copy link
Member

Testing it. Finally fixed my Mac.

@parasharrajat
Copy link
Member

Didn't complete my testing. I will finish it up tomorrow.

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue on Android Tablet.
image

Steps:

  1. Open the payments page.
  2. Click at the middle of any payment method.
  3. Menu is off the screen.

Also pleas merge main.

@srdjanrist
Copy link
Author

Comment > Issue on Android Tablet. ![image](https://user-images.githubusercontent.com/24370807/162441455-63bf6f7a-6056-45f8-8673-d5f55ded6da6.png) > > Steps: > > 1. Open the payments page. > 2. Click at the middle of any payment method. > 3. Menu is off the screen. > > Also pleas merge main.

I have looked into this.
What I noticed is that depeneding on which part of the menu item is clicked, parameters from onPress callback are different. Actually, besides locationX and locationY, also target is different.

Touching the "Add payment method" part yields:
"locationX": 4.11676025390625, "locationY": 9.80316162109375, "target": 27237
image

Touching anywhere beside the "Add payment method" part yields:
"locationX": 351.5091552734375, "locationY": 11.81427001953125, "target": 27247
As you can see the target property is different as well.

By using this location and on-screen location, the popover's position is calculated.
Due to positions being different (depending on where the menu item is clicked), I have no way to precisely and consistently calculate the position of popover.

Have you had this situation before? Do you have any suggestions for improvement?

@Julesssss
Copy link
Contributor

Hey @srdjanrist, we'll need to resolve the issue @parasharrajat mentioned, as it doesn't look ideal. I'm afraid I don't have any suggestions for you, but sharing the issue in the shared Slack channel might be a good idea. As it's quite possible that someone has faced and solved this problem before.

@thesahindia thesahindia mentioned this pull request Apr 12, 2022
87 tasks
@srdjanrist
Copy link
Author

I have consulted people on Slack, and will try their approach as well.

I was thinking of another approach to this.
@parasharrajat Would it be fine to update MenuItem component, refactor a little bit, and make a transparent View, positioned over the whole menu item. That way, this new overlay view would take all touch events and positioning would be always relative to the whole menu item, instead of each separate child view individually?

@parasharrajat
Copy link
Member

That would be Overkill. Can't we use measureInWindow to get the coordinates?

@srdjanrist
Copy link
Author

That would be Overkill. Can't we use measureInWindow to get the coordinates?

I will check this today.

@srdjanrist
Copy link
Author

That would be Overkill. Can't we use measureInWindow to get the coordinates?

I will check this today.

Updated MenuItem with code for measuring layout with the mentioned method

Comment on lines -44 to -46
const MenuItem = props => (
<Pressable
onPress={(e) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not acceptable. We don't have to touch the MenuItem for this. Instead, use the ref to calculate whatever is needed on the parent components that use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @srdjanrist, could you please address this comment so we can move forward :)

@github-actions
Copy link
Contributor

CLA Assistant Lite bot:
Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


0 out of 2 committers have signed the CLA.
@srdjan Ristanovic
@srdjanrist
Srdjan Ristanovic, srdjanrist seem not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants