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.03k stars 2.54k forks source link

[$250] Compose box - Browser's back arrow do not focus composer if first image preview open #42368

Open lanitochka17 opened 2 weeks ago

lanitochka17 commented 2 weeks 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!


Version Number: 1.4.74-0 Reproducible in staging?: Y Reproducible in production?: Y If this was caught during regression testing, add the test name, ID and link from TestRail: N/A Issue reported by: Applause - Internal Team

Action Performed:

Precondition: upload multiple images in chat

  1. Open the first uploaded image
  2. Click the "Back" button in the browser

Expected Result:

Composer gets focused

Actual Result:

Last uploaded image preview opened

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Add any screenshot/video evidence

https://github.com/Expensify/App/assets/78819774/fb43f2cf-5fee-4545-8f25-4066cce2a725

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~013929a859819a7038
  • Upwork Job ID: 1792347976114130945
  • Last Price Increase: 2024-05-27
  • Automatic offers:
    • DylanDylann | Contributor | 0
    • tsa321 | Contributor | 102496699
Issue OwnerCurrent Issue Owner: @thesahindia
melvin-bot[bot] commented 2 weeks ago

Triggered auto assignment to @jliexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

melvin-bot[bot] commented 1 week ago

Job added to Upwork: https://www.upwork.com/jobs/~013929a859819a7038

melvin-bot[bot] commented 1 week ago

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

jliexpensify commented 1 week ago

Can repro, adding External and probably fits into VSB best?

tsa321 commented 1 week ago

Proposal

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

Browser back button open other images when user opens first attachment image in attachment view (and won't close attachment view) and press the back button.

What is the root cause of the problem?

In here:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/libs/Navigation/AppNavigator/AuthScreens.tsx#L152-L157

When back button is pressed, the beforeRemove listener is called immediately even though the modal is not completely hidden yet. The code above will set modal visibility to false too early and will make:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx#L283-L284

shouldAutoFocus to be true. This will make RNMarkdownTextInput:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/components/Composer/index.tsx#L324

autofocus to be true. This will make composer immediately focused even though the modal is not completelly hidden(because there is some animation). The trap focuse in react native modal will detect if focus is outside modal and will make focus back to element inside the modal, and here will eventually make the image changes to other/ next images. More context is in here:

https://github.com/Expensify/App/issues/27237#issuecomment-1751632831

More info about image changes in attachment view @DylanDylann Focus event catch by react native modal `ModalFocusTrap` is in here: https://github.com/necolas/react-native-web/blob/54c14d64dabd175e8055e1dc92e9196c821f9b7d/packages/react-native-web/src/exports/Modal/ModalFocusTrap.js#L137 The function of this file based on the comment is to trap focus so the focus won't leave modal, if the focus is outside of modal, the trap focus will focus last element inside modal. The code flow is: Composer focused (from autofocus of RNMarkdownTextInput)-> focus event triggered -> catch by trapFocus (which will try to focus child or last descendant element of the modal -> trap focus looping through descendant element -> until last element of the initial rendered image (initialNumToRender is 3 in AttachmentCarousel) list reached : The trapFocus try to focus the element of the attachment list will cause `onViewableItemsChanged` will be executed because the focus will make the displayed image slide(changes), hence will execute handler in: https://github.com/Expensify/App/blob/8375abea3a377e7416404addde255b6ac8530a9b/src/pages/home/report/ReportAttachments.tsx#L21-L25 which is navigate back to the attachment modal. Focus event catch by react native modal `ModalFocusTrap` is in here: https://github.com/necolas/react-native-web/blob/54c14d64dabd175e8055e1dc92e9196c821f9b7d/packages/react-native-web/src/exports/Modal/ModalFocusTrap.js#L137 The function of this file based on the comment is to trap focus so the focus won't leave modal, if the focus is outside of modal, the trap focus will focus last element inside modal. The code flow is: Composer focused (from autofocus of RNMarkdownTextInput)-> focus event triggered -> catch by trapFocus (which will try to focus child or last descendant element of the modal -> trap focus looping through descendant element -> until last element of the initial rendered image (initialNumToRender is 3 in AttachmentCarousel) list reached : The trapFocus try to focus the element of the attachment list will cause `onViewableItemsChanged` will be executed because the focus will make the displayed image slide(changes), hence will execute handler in: https://github.com/Expensify/App/blob/8375abea3a377e7416404addde255b6ac8530a9b/src/pages/home/report/ReportAttachments.tsx#L21-L25 which is navigate back to the attachment modal.

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

So basically we prevent set modal visibility too early, in here we should add a condition:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/libs/Navigation/AppNavigator/AuthScreens.tsx#L155-L156

the code could be:

if (Modal.areAllModalsHidden()) {
    Modal.setModalVisibility(false);
    Modal.willAlertModalBecomeVisible(false);
}

This will check whether all modals is hidden completely. Then the set of setModalVisibility and willAlertModalBecomeVisible are already exist in BaseModal - hideModal:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/components/Modal/BaseModal.tsx#L76

The modal already use it and so the if check above is sufficient to fix this issue.

To solve the closed issue that reappears above, in baseModal, we should call hide modal only in here:

https://github.com/Expensify/App/blob/e8ae3c5acedf0e6788dc574c7b6f3043ca37092a/src/components/Modal/BaseModal.tsx#L244

so we add hideModal inside handleDismissModal then remove onModalHide and onDismiss property of ReactNativeModal. This is because many types of modal (whether the modal support onModalHide or not) used in the app and put the hideModal call in here will make sure the hideModal is executed once.

Result: https://github.com/Expensify/App/assets/114975543/6cf06e68-d0a2-406d-b994-660b3f1a729b
Fix result for the other issue that reappears: https://github.com/Expensify/App/assets/114975543/82809373-86b4-4908-a110-fd8e03825360
arjun-dureja commented 1 week ago

Proposal

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

When an image attachment is opened inside a chat, pressing the browser back button will result in another image displaying, rather than being navigated back to the chat.

What is the root cause of that problem?

Inside the AttachmentCarousel component, the updatePage function is unexpectedly being called when the browser back button is pressed (due to how onViewableItemsChanged works on FlatList). This causes onNavigate to be called with the first attachment in the viewable items, which then navigates the user to a different attachment.

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

We should detect when the back button is pressed (potentially using a ref) and then return early inside the updatePage function. This will ensure that we're not unnecessarily fetching a different image and navigating the user to it. It will allow the user to go back to the chat

What alternative solutions did you explore? (Optional)

CleverWolf1220 commented 1 week ago

Proposal

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

Compose box - Browser's back arrow do not focus composer if first image preview open

This issue is reproducible for video attachments as well.

What is the root cause of that problem?

In FlatList component of AttachmentCarousel, onViewableItemsChanged is called when pressing browser back button without user interection.

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

We should add waitForInteraction: true in viewabilityConfig

What alternative solutions did you explore? (Optional)

melvin-bot[bot] commented 1 week ago

πŸ“£ @CleverWolf1220! πŸ“£ 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. Make sure you've read and understood the contributing guidelines.
  2. 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.
  3. 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.
  4. 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>
thesahindia commented 1 week ago

@jliexpensify, I won't be able to review this soon. Please reassign.

DylanDylann commented 1 week ago

I would love to take over this issue as C+

melvin-bot[bot] commented 1 week ago

πŸ“£ @DylanDylann πŸŽ‰ An offer has been automatically sent to your Upwork account for the Contributor role πŸŽ‰ Thanks for contributing to the Expensify app!

Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review πŸ§‘β€πŸ’» Keep in mind: Code of Conduct | Contributing πŸ“–

jliexpensify commented 1 week ago

All yours @DylanDylann!

EDIT: Still considering proposals!

DylanDylann commented 1 week ago

@tsa321 Could you detail this point? Which logic does that?

The trap focuse in react native modal will detect if focus is outside modal and will make focus back to element inside the modal, and here will eventually make the image changes to other/ next images.

DylanDylann commented 1 week ago

@arjun-dureja Could you deep dive into this point and explain why the updatePage is called? Is there any reference, document that explain why onViewableItemsChanged is triggered?

due to how onViewableItemsChanged works on FlatList

cc @CleverWolf1220

DylanDylann commented 1 week ago

@CleverWolf1220 Why waitForInteraction will resolve this problem?

tsa321 commented 1 week ago

@DylanDylann Focus event catch by react native modal ModalFocusTrap is in here:

https://github.com/necolas/react-native-web/blob/54c14d64dabd175e8055e1dc92e9196c821f9b7d/packages/react-native-web/src/exports/Modal/ModalFocusTrap.js#L137

The function of this file based on the comment is to trap focus so the focus won't leave modal, if the focus is outside of modal, the trap focus will focus last element inside modal.

The code flow is: Composer focused (from autofocus of RNMarkdownTextInput)-> focus event triggered -> catch by trapFocus (which will try to focus child or last descendant element of the modal -> trap focus looping through descendant element -> until last element of the initial rendered image (initialNumToRender is 3 in AttachmentCarousel) list reached : The trapFocus try to focus the element of the attachment list will cause onViewableItemsChanged will be executed because the focus will make the displayed image slide(changes), hence will execute handler in:

https://github.com/Expensify/App/blob/8375abea3a377e7416404addde255b6ac8530a9b/src/pages/home/report/ReportAttachments.tsx#L21-L25

which is navigate back to the attachment modal.

melvin-bot[bot] commented 5 days ago

πŸ“£ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? πŸ’Έ

melvin-bot[bot] commented 5 days ago

@jliexpensify, @DylanDylann Whoops! This issue is 2 days overdue. Let's get this updated quick!

DylanDylann commented 5 days ago

Hi Melv, thanks for tagging me. I will complete my review today

CleverWolf1220 commented 5 days ago

@DylanDylann

@CleverWolf1220 Why waitForInteraction will resolve this problem?

Sorry for late response. I found that my proposal solves this issue but causes other problems.

DylanDylann commented 4 days ago

@tsa321's proposal looks good to me. Let's go with them

πŸŽ€ πŸ‘€ πŸŽ€ C+ reviewed

melvin-bot[bot] commented 4 days ago

Triggered auto assignment to @dangrous, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

dangrous commented 4 days ago

Ooh, that's complicated. I think this solution makes sense to me, but we should make sure to do a lot of testing on closing other modals, etc. to make sure this doesn't cause any regressions there.

Assigining @tsa321

melvin-bot[bot] commented 4 days ago

πŸ“£ @tsa321 πŸŽ‰ An offer has been automatically sent to your Upwork account for the Contributor role πŸŽ‰ Thanks for contributing to the Expensify app!

Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review πŸ§‘β€πŸ’» Keep in mind: Code of Conduct | Contributing πŸ“–