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.53k stars 2.88k forks source link

[HOLD for payment 2023-12-06] [$1000] Web - Pressing ESC on attachment preview glitches the preview #27237

Closed kbecciv closed 11 months 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. Open the app
  2. Click on any chat
  3. Click '+' add attachment
  4. Attach multiple images
  5. Open first uploaded image
  6. Click on ESC multiple times, observe that preview closes, reopens with different image and closes

Expected Result:

App should close preview on ESC click (note you need to press Esc multiple times)

Actual Result:

App glitches on closing preview on ESC click

Workaround:

Unknown

Platforms:

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

Version Number: 1.3.61-1 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/1c6168d6-ff13-4892-892f-4a98015c026a

https://github.com/Expensify/App/assets/93399543/9e5b35a2-db33-474a-957e-6fe952084b2e

Expensify/Expensify Issue URL: Issue reported by: @dhanashree-sawant Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1693558112570809

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~01ebd6c095f0ad277c
  • Upwork Job ID: 1701562714140925952
  • Last Price Increase: 2023-10-03
paultsimura commented 1 year ago

Proposal

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

When clicking "Esc" multiple times, the attachment preview glitches.

What is the root cause of that problem?

The root cause here is buried quite deep and required a lot of debugging, so I'll try to be as detailed as possible here.

TL;DR

When we are hiding the attachments modal, we try to focus the composer, which causes the onScroll event on the FlatList inside the AttachmentCarousel. This causes an avalanche effect of bugs.

This same RCA can be easier reproduced here: https://github.com/Expensify/App/issues/29109

More detailed explanation:

In ComposerWithSuggestions, we are trying to focus the Composer right after we hide the modal:

https://github.com/Expensify/App/blob/01ef03f850047ca36caa21fd38b9f2f8555ef78d/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js#L481

However, since the modal dismissal is an animated process, it's not happening right away. So we are, in fact, focusing on the composer when the modal is still open. The focus action fires a scroll event, which is then captured by the FlatList inside the AttachmentsCarousel (since FlatList is a combination of a VirtualizedList and a ScrollView).

Here's the call stack that comes all the way back to the ComposerWithSuggestions:

image image

This, as a result, causes the onViewableItemsChanged of the FlatList, which causes glitchy change of the image in this issue, and the endless redirection loop in https://github.com/Expensify/App/issues/29109.

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

First, we need to call the composer focus on modal hide with delay:

-       focus();
+       focus(true);
    }, [focus, prevIsFocused, prevIsModalVisible, isFocused, modal.isVisible, isNextModalWillOpenRef]);

https://github.com/Expensify/App/blob/01ef03f850047ca36caa21fd38b9f2f8555ef78d/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js#L469-L482

Second, the focusWithDelay relies on ComposerFocusManager.isReadyToFocus():

https://github.com/Expensify/App/blob/3789cc36ed4c96ea4e94bf1552d87cc19b66beeb/src/libs/focusWithDelay.ts#L25-L30

This is, in fact, barely useful since the ComposerFocusManager.resetReadyToFocus() is called only in one place, and it's on Android:

https://github.com/Expensify/App/blob/11717c5772c631af6629d443270b8fbf107bf875/src/components/Modal/index.android.js#L12-L14

We should set the composer as "not ready to focus" every time a modal is open, and set it back to "ready to focus" when the modal is dismissed.

For this, we need to add the following prop to the ReactNativeModal component (it was by mistake removed in https://github.com/Expensify/App/pull/25672):

+   const handleModalWillShow = () => {
+       ComposerFocusManager.resetReadyToFocus();
+   };

    ...

    return (
        <ReactNativeModal
            onBackdropPress={handleBackdropPress}
            // Note: Escape key on web/desktop will trigger onBackButtonPress callback
            // eslint-disable-next-line react/jsx-props-no-multi-spaces
            onBackButtonPress={onClose}
+           onModalWillShow={handleModalWillShow}
            onModalShow={handleShowModal}
            propagateSwipe={propagateSwipe}
    ....

This solution alone would be enough to solve the current issue. However, if we want to fix both this and https://github.com/Expensify/App/issues/29109 in one take, we should make the following change:

Third, we need to correctly handle setting back the composer to "Ready to focus".

Currently, the ComposerFocusManager.setReadyToFocus() is called in 2 places in BaseModal:

https://github.com/Expensify/App/blob/a348859ff43f38c487de96a3f1b4a75428f493b9/src/components/Modal/BaseModal.js#L123-L125

https://github.com/Expensify/App/blob/a348859ff43f38c487de96a3f1b4a75428f493b9/src/components/Modal/BaseModal.js#L75-L77

Calling it in the handleDismissModal was preferred because it's called finally, after the onModalHide. But this specific method - Modal.onDismiss - is not called in case of a non-fullscreen modal, and it's not called on navigating back via browser navigation.

The non-fullscreen case is already handled in hideModal, but since the Attachment modal is full-screen, the "go-back" navigation will not call the ComposerFocusManager.setReadyToFocus() at all, so the composer will not be focused on closing the attachment preview by navigating back.

That's why my suggestion is to move the ComposerFocusManager.setReadyToFocus() fully into hideModal: Remove handleDismissModal and make this change:

-   const handleDismissModal = () => {
-       ComposerFocusManager.setReadyToFocus();
-   };

    ...

    const hideModal = useCallback(
        (callHideCallback = true) => {
            if (shouldSetModalVisibility) {
                Modal.setModalVisibility(false);
            }
            if (callHideCallback) {
                onModalHide();
            }
            Modal.onModalDidClose();
-           if (!fullscreen) {
            ComposerFocusManager.setReadyToFocus();
-           }
        },
        [shouldSetModalVisibility, onModalHide, fullscreen],
    );

    ....

    return (
        <ReactNativeModal
            onBackdropPress={handleBackdropPress}
            // Note: Escape key on web/desktop will trigger onBackButtonPress callback
            // eslint-disable-next-line react/jsx-props-no-multi-spaces
            onBackButtonPress={onClose}
+           onModalWillShow={handleModalWillShow}
-           onDismiss={handleDismissModal}

As a result, we will have both issues fixed, as it solves the actual root cause, and is not a workaround compared to some existing proposals:

https://github.com/Expensify/App/assets/12595293/61f76d19-60c4-4776-afb5-31f6d45d0f3a

What alternative solutions did you explore? (Optional)

Optionally, we could only call the ComposerFocusManager.setReadyToFocus() for the attachment modal here: https://github.com/Expensify/App/blob/7fb66cdd840ba14f5c958dd60fc1bb4f75d58bab/src/pages/home/report/ReportAttachments.js#L33

But I don't see any major reason against step 3 of this proposal, as it will be more versatile.

melvin-bot[bot] commented 1 year ago

@abdulrahuman5196 @Christinadobrzyn this issue is now 4 weeks old and preventing us from maintaining WAQ, can you:

Thanks!

melvin-bot[bot] commented 1 year ago

Current assignee @abdulrahuman5196 is eligible for the Internal assigner, not assigning anyone new.

melvin-bot[bot] commented 1 year ago

@abdulrahuman5196, @Christinadobrzyn Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

abdulrahuman5196 commented 1 year ago

Will review the new proposals today

abdulrahuman5196 commented 1 year ago

The latest proposals have much information which needs dive deep. Will review again tomorrow.

tsa321 commented 1 year ago

@abdulrahuman5196 I have answered your question about the root cause and found a related bug, in my comment

abdulrahuman5196 commented 1 year ago

Still investigating. Will close over the weekend.

abdulrahuman5196 commented 1 year ago

Thank you everyone for the root cause analysis. Status so far: I was able to review the root cause which is onViewableItemsChanged of flatlist getting called causing this issue. I am have checked couple of proposals. Need to do some different platform testing on some of the proposals, before providing more info. Will post here once that is done.

abdulrahuman5196 commented 1 year ago

Still investigating. Will provide update sooner

abdulrahuman5196 commented 1 year ago

RE-Reviewing now

abdulrahuman5196 commented 1 year ago

From investigation, the proposal by @pradeepmdk here https://github.com/Expensify/App/issues/27237#issuecomment-1751743967 seems simpler fixes which is aiming to fix in the attachment component itself which is good compared to other proposals so far. I tried 1st option and it didn't work for me. Just reducing the flicker time IMO.

2nd option is one I am more inclined for now. But it is showing loading indicator when closing the attachment modal.

https://github.com/Expensify/App/assets/46707890/f9590752-1735-4e54-8206-e43afd407e21

@pradeepmdk Could you check on these concerns and update the proposal if possible to fix the concerns?

paultsimura commented 1 year ago

@abdulrahuman5196 I hate to be this kind of person, but: The 2nd proposal by @pradeepmdk looks more like a local workaround that doesn't solve a quite similar issue with the same root cause: https://github.com/Expensify/App/issues/29109

On the other hand, while being more complex, my proposal https://github.com/Expensify/App/issues/27237#issuecomment-1753912527 fixes the actual root cause and resolves both this issue (without causing the loading indicator) and https://github.com/Expensify/App/issues/29109.

tsa321 commented 1 year ago

@abdulrahuman5196 I agree with @paultsimura, I think proposal from @pradeepmdk doesn't address the root cause or doesn't catch the real root cause. I mean what is causing the onViewableItemsChanged to be triggered. And I have replied to your question about the root cause, Do you have any opinion about my answer of the root cause? and I found another bug and it's possible solution to fix it. So there is two bugs about attachment preview which we can solve here.

Thank you...

pradeepmdk commented 1 year ago

@abdulrahuman5196 i updated propsoal. and i agree with @paultsimura my solution not solved https://github.com/Expensify/App/issues/29109 because when we press back button https://github.com/Expensify/App/blob/389d7b0c4b96c6f2a2295055c685791d35b65252/src/components/AttachmentModal.js#L370 it's not triggering. so now the decision with to you but @paultsimura proposes solving both issues.

but waitForInteraction: true, worked on initially but now not working I am not sure what happened now ๐Ÿ˜ž

and one more thing but all are saying https://github.com/Expensify/App/blob/389d7b0c4b96c6f2a2295055c685791d35b65252/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js#L481 focus on immediately cause this issue. then this issue is always there, right? if we have more images then when navigating between images then no issues on here only thing before navigating images we are facing issues. any idea on this? ref: (from staging no issues)

https://github.com/Expensify/App/assets/16595846/38574fa3-2d3b-4243-bce7-8c85da009b3e

tsa321 commented 1 year ago

@abdulrahuman5196 so basically the root cause is when user pressing the second esc: the focus change to composer -> react native modal catch focus event and check whether the focused element is outside modal -> focused element is outside modal -> react native modal trap focus will focus the last element of the modal to prevent the focused element is outside of the modal -> the last rendered image of attachment preview is focused -> onViewableChange triggered. Here is the code that catch the focus event in trap focus of react native modal:

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

for detailed explanation you can see my answer of root cause and also I found the other bug and provide a solution for it. Thank you...

abdulrahuman5196 commented 1 year ago

Hi folks thanks for the detailed discussion. Just to note simpler fixes are not always workaround fixes. But anyways since the proposal couldn't fix the loading indicator issue and other similar issue we have to drop it.

The proposals left currently to re-review are

1) @ilkeruyanik proposal here https://github.com/Expensify/App/issues/27237#issuecomment-1746045280 : I am not aligned on this since the proposal is still attempting to present multiple dismissModal by using stored values. But anyways will compare with other proposals as well.

2) @tsa321 's proposal here https://github.com/Expensify/App/issues/27237#issuecomment-1746060535 Could you kindly update the proposal if it doesn't included all the changes you have mentioned.

3) @paultsimura 's proposal here https://github.com/Expensify/App/issues/27237#issuecomment-1753912527 Need to fresh check this one.

tsa321 commented 1 year ago

@abdulrahuman5196 I have updated my proposal to include root cause and add a fix for the freeze or hangs app bug when user pressing back button based on my answer of the root cause.

abdulrahuman5196 commented 1 year ago

Will work on the action items here https://github.com/Expensify/App/issues/27237#issuecomment-1779814093 today.

abdulrahuman5196 commented 1 year ago

~Re-reviewing now~

melvin-bot[bot] commented 1 year ago

@abdulrahuman5196, @Christinadobrzyn Huh... This is 4 days overdue. Who can take care of this?

abdulrahuman5196 commented 1 year ago

Still on this phase going back and forth testing - https://github.com/Expensify/App/issues/27237#issuecomment-1779814093. Will update in a day.

Christinadobrzyn commented 12 months ago

Hi @abdulrahuman5196 just checking to see if there's any update based on the testing. Thanks!

abdulrahuman5196 commented 12 months ago

Hi, Will review today just back from weekend

Christinadobrzyn commented 11 months ago

hi @abdulrahuman5196 can you provide an update for us? Thanks!

abdulrahuman5196 commented 11 months ago

Sorry for dragging on. Still investigating proposal. Will cover over weekend or reach out for another C+ on monday.

shubham1206agra commented 11 months ago

@abdulrahuman5196 If you want help from another C+, I will be happy to help you cause I have been following this issue from the start.

abdulrahuman5196 commented 11 months ago

Sure. Let me check over this weekend, if not will forward.

abdulrahuman5196 commented 11 months ago

All the 3 pending proposals are working well. Let me compare them and come back with results.

abdulrahuman5196 commented 11 months ago

@paultsimura 's proposal here https://github.com/Expensify/App/issues/27237#issuecomment-1753912527 looks good and work well. It is better than other proposal IMO. Reason being, the main root cause is that onViewableItemsChanged is being called incorrectly from FlatList during our usage. But its not worth some upstream fix and since fix at our end is relatively small in all proposals. And another reason I think of is that if we add Navigation.dismissModal in future in another place, we don't have to do any extra checks specific to this issue. And I think we can just implement the First change proposed, I think some of the other changes proposed have been already implemented with some other PRs.

๐ŸŽ€ ๐Ÿ‘€ ๐ŸŽ€ C+ Reviewed

melvin-bot[bot] commented 11 months ago

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

paultsimura commented 11 months ago

Thank you, the PR will be ready today.

Christinadobrzyn commented 11 months ago

I'm going ooo until Monday Nov 27th so going to assign another BZ teammate to monitor this until I'm back. Thanks!

Status - reviewing PR! ๐ŸŽ‰

melvin-bot[bot] commented 11 months ago

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

melvin-bot[bot] commented 11 months ago

Bug0 Triage Checklist (Main S/O)

tsa321 commented 11 months ago

@abdulrahuman5196 the proposal by @paultsimura is almost match my proposal, I describe the root cause first and the solution for the other bug which is similar to @paultsimura proposal, but I posted it first: https://github.com/Expensify/App/issues/27237#issuecomment-1751632831

adding focus(true) parameter and other additional lines in basemodal to fix this issue and the other issue is my original proposal, you can see it in my answer of your question about root cause...

Could you explain why you doesn't choose my proposal / optional solution? As I propose similar to @paultsimura solution but I am first.

abdulrahuman5196 commented 11 months ago

@tsa321 let me check if you had proposed the solution first.

Cc: @paultsimura do share if you have thoughts

tsa321 commented 11 months ago

@abdulrahuman5196 please check https://github.com/Expensify/App/issues/27237#issuecomment-1751632831

in the last section, start with:

And another bug: If we press back button ...

I have posted the solution on 8 oct for the And another bug: If we press back button... section...


I had added more detail in my original proposal to use this solution...

abdulrahuman5196 commented 11 months ago

Looking at the proposals

@tsa321 edit the original proposal to include focus code suggestions only 3 weeks back https://github.com/Expensify/App/issues/27237#issuecomment-1746060535

Whereas @paultsimura had the suggestion on his original proposal in Oct 10 itself https://github.com/Expensify/App/issues/27237#issuecomment-1753912527 that let to my decision.

But seems @tsa321 suggested the solution as part of analysis replies here https://github.com/Expensify/App/issues/27237#issuecomment-1751632831 which happened at Oct 8, 2 days before @paultsimura 's solution.

So if we consider only main proposals @paultsimura would be one to choose. But I am not sure if we would consider replies and conversations which has code change suggestions as a valid proposals

@tsa321 / @paultsimura let me know if I got the timelines in any way wrongly.

@hayata-suenaga do you have any suggestions here?

And note for contributors: We have guideline to update original proposal everytime you think of a solution is worth mentioning to avoid this type of concerns.

tsa321 commented 11 months ago

@abdulrahuman5196 I am sorry, at that time I have just waiting for your reply on my answer of root cause and then I will update the proposal accordingly...

paultsimura commented 11 months ago

@abdulrahuman5196 I agree that the proposal of @tsa321 was not updated on time. Because of this, I did not even see those suggested changes before posting my proposal.

But in order not to make a decision based only on this, here are a couple more thoughts:

Setting focus(true) is, in fact, only a partial solution, because without my third proposed change (which I still think we should implement), we have an issue: when clicking the browser "back" button, the composer does not get focused similar to clicking "x" or "esc".

Third, we need to correctly handle setting back the composer to "Ready to focus".

https://github.com/Expensify/App/assets/12595293/594e7d75-1e0d-4cc8-817b-be699d33b027

@tsa321 did not include it in their original discussion but added it in the modified proposal after mine was posted, meaning they considered it valuable enough to be included in the proposal, but missed this change in the discussion.

Here is the behavior with the fix applied:

Fixed focus https://github.com/Expensify/App/assets/12595293/0c82d48c-14d2-40ab-9d5c-9cbaf111954f
tsa321 commented 11 months ago

@paultsimura but the general idea is similar, the root cause is at the focus() and need to add parameter true and for the detailed implementation need more testing... and of course we need to reset and set the ready state accordingly to works...


and Also let consider the root cause section to consider which proposal gives more proper and correct explanation of the root cause...

paultsimura commented 11 months ago

I'd just like to add that in the past, I had a similar situation when my proposal was rejected because as was originally added in a discussion. The reason was that "You should be confident about the proposed solution, so when you have it, it should be reflected in the proposal".

To me, it seems logical that when some new idea comes to mind, it should be reflected in the proposal, otherwise waiting for some extra response before updating the proposal means that the Contributor is not sure about the proposed solution and doesn't want to risk putting it in the proposal before an extra confirmation.

I would prefer to avoid going back and forth further here because it can lead to some personal confrontations. I'll let @abdulrahuman5196 and @hayata-suenaga make the further decision taking into account the timing and these 2 comments: https://github.com/Expensify/App/issues/27237#issuecomment-1817412283 https://github.com/Expensify/App/issues/27237#issuecomment-1817417013

Christinadobrzyn commented 11 months ago

I'm going ooo until Monday Nov 27th so going to assign another BZ teammate to monitor this until I'm back. Thanks!

Status: working on PR

melvin-bot[bot] commented 11 months ago

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

melvin-bot[bot] commented 11 months ago

Bug0 Triage Checklist (Main S/O)

hayata-suenaga commented 11 months ago

I still agree with @abdulrahuman5196 that @paultsimura should take the PR considering the timeline and they updated their proposal.

However, I really want to appreciate everyone who suggested proposals. Thank you so much everyone ๐Ÿ™‡

paultsimura commented 11 months ago

Thanks. To keep things relatively fair for all, I'd like to offer $250 of my bounty to @tsa321 when the issue gets fixed.

tsa321 commented 11 months ago

Wow thank you @paultsimura, That is really nice of you

Christinadobrzyn commented 11 months ago

Back from ooo - I'll take this back. Thanks for watching Tom!