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

[$250] Expense - Not here page shows up briefly when deleting the expense #45576

Open izarutskaya opened 4 months ago

izarutskaya commented 4 months 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: 9.0.8-1 Reproducible in staging?: Y Reproducible in production?: N Found when executing PR : https://github.com/Expensify/App/pull/44537 Logs: https://stackoverflow.com/c/expensify/questions/4856 Issue reported by: Applause-Internal team

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go to DM.
  3. Submit two expenses to the user.
  4. Open any of the transaction thread.
  5. Tap on the report header.
  6. Tap Delete expense..
  7. Delete the expense.

Expected Result:

Not here page will not show up when deleting the expense.

Actual Result:

Not here page shows up briefly when deleting the expense.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

https://github.com/user-attachments/assets/819b601e-65bc-4aab-82ea-69cfa7faa418

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~01c66dfe570a289fac
  • Upwork Job ID: 1813534350182069816
  • Last Price Increase: 2024-08-20
  • Automatic offers:
    • alitoshmatov | Reviewer | 103693223
    • wildan-m | Contributor | 104145017
Issue OwnerCurrent Issue Owner: @alitoshmatov
melvin-bot[bot] commented 4 months ago

Triggered auto assignment to @sonialiap (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 4 months ago

Triggered auto assignment to @iwiznia (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

github-actions[bot] commented 4 months ago

:wave: Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

  1. Identify the pull request that introduced this issue and revert it.
  2. Find someone who can quickly fix the issue.
  3. Fix the issue yourself.
izarutskaya commented 4 months ago

We think this issue might be related to the #collect project.

izarutskaya commented 4 months ago

Production

https://github.com/user-attachments/assets/31cea64f-98a8-451a-8a98-802d893545f4

melvin-bot[bot] commented 4 months ago

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

melvin-bot[bot] commented 4 months ago

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

allgandalf commented 4 months ago

We pass isFromRHP to true without checking the screen size (whether we are on larger screen or smaller): https://github.com/Expensify/App/blob/fc9b7ac988a1e520fcdb904ae13dfd6e091f8bcd/src/pages/ReportDetailsPage.tsx#L778 This will trigger us to dismiss the modal first and then navigate back: https://github.com/Expensify/App/blob/fc9b7ac988a1e520fcdb904ae13dfd6e091f8bcd/src/libs/ReportUtils.ts#L3594-L3600

Simplest fix would be to use the check the screen size from the hook useResponsiveLayout and only pass true if we are on bigger screen

const {isSmallScreenWidth} = useResponsiveLayout();

ReportUtils.navigateBackAfterDeleteTransaction(navigateBackToAfterDelete.current, !isSmallScreenWidth ? true: false); 

I assume there is a check for large screen too, both can be used either ways

allgandalf commented 4 months ago

I assume that is what was intended with the PR https://github.com/Expensify/App/pull/44537

allgandalf commented 4 months ago

does that make sense to you @iwiznia ?

iwiznia commented 4 months ago

Oh right, seems that PR did not fix the issue it was intended to fix, going to close in favor of that issue

melvin-bot[bot] commented 4 months ago

⚠️ Looks like this issue was linked to a Deploy Blocker here

If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

If a regression has occurred and you are the assigned CM follow the instructions here.

If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

daledah commented 4 months ago

Edited by proposal-police: This proposal was edited at 2024-08-06 13:59:34 UTC.

Proposal

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

Not here page shows up briefly when deleting the expense.

What is the root cause of that problem?

After deleting the transaction, we delete the data first here, then navigate later https://github.com/Expensify/App/blob/371093660f398a3895726931baa303ce9d823e5d/src/pages/ReportDetailsPage.tsx#L778

So the data will be updated even before the user finishes the navigation back, this causes the brief deleted-transaction data (not found page/[Deleted expense] text) to show in the screen (which is still navigating back).

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

We should navigate the user back first, then delete the transaction data in the background after the user has successfully navigated. This will make sure through out the navigation back, the user still sees the correct transaction data.

setTimeout(() => { IOU.deleteMoneyRequest(iouTransactionID, requestParentReportAction, isSingleTransactionView); }, CONST.ANIMATED_TRANSITION);



In summary, we only change the order in which optimistic data update and navigation back happens, we don't make any logic change. That's for submit expense case, we should check track expense case and handle in similar manner.

### What alternative solutions did you explore? (Optional)
We could additionally add the change suggested [above here](https://github.com/Expensify/App/issues/45576#issuecomment-2233093947), but this does not fully fix the issue, `[Deleted expense]` still shows and also buttons disappearing, before the user is navigated back. So it's an incremental thing we can add.

Alternative to `waitForNavigate` approach, we can use `setTimeout` with the navigation timeout (similar to in [here](https://github.com/Expensify/App/blob/963f8ce2c108d543c5058e7574f21465106440a6/src/hooks/useAutoFocusInput.ts#L41)). Or we can delete the data in `InteractionManager.runAfterInteractions`, but it might not work as reliably.

<!---
ATTN: Contributor+

You are the first line of defense in making sure every proposal has a clear and easily understood problem with a "root cause". Do not approve any proposals that lack a satisfying explanation to the first two prompts. It is CRITICALLY important that we understand the root cause at a minimum even if the solution doesn't directly address it. When we avoid this step we can end up solving the wrong problems entirely or just writing hacks and workarounds.

Instructions for how to review a proposal:

1. Address each contributor proposal one at a time and address each part of the question one at a time e.g. if a solution looks acceptable, but the stated problem is not clear then you should provide feedback and make suggestions to improve each prompt before moving on to the next. Avoid responding to all sections of a proposal at once. Move from one question to the next each time asking the contributor to "Please update your original proposal and tag me again when it's ready for review".

2. Limit excessive conversation and moderate issues to keep them on track. If someone is doing any of the following things please kindly and humbly course-correct them:

- Posting PRs.
- Posting large multi-line diffs (this is basically a PR).
- Skipping any of the required questions.
- Not using the proposal template at all.
- Suggesting that an existing issue is related to the current issue before a problem or root cause has been established.
- Excessively wordy explanations.

3. Choose the first proposal that has a reasonable answer to all the required questions.
-->
daledah commented 3 months ago

Hey @iwiznia the other issue was closed and this is still reproducible. As explained in my proposal this has a different RCA and won't be fixed in that issue.

Could you help reopen this GH issue to address the bug?

Kind thanks!

daledah commented 3 months ago

Proposal updated with small alternative approach

melvin-bot[bot] commented 3 months 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 3 months ago

@iwiznia, @sonialiap, @alitoshmatov Whoops! This issue is 2 days overdue. Let's get this updated quick!

trjExpensify commented 3 months ago

@alitoshmatov can you review the proposal and keep this moving please? Thanks!

alitoshmatov commented 3 months ago

@daledah In https://github.com/Expensify/App/blob/963f8ce2c108d543c5058e7574f21465106440a6/src/pages/ReportDetailsPage.tsx#L694

We need IOU.deleteMoneyRequest to be executed so it returns a url to navigate back. How are planning on not calling this function but still getting url to navigate back?

allgandalf commented 3 months ago

hey @alitoshmatov , can you also check my proposed solution here, thanks

alitoshmatov commented 3 months ago

@allgandalf Sorry missed your proposal.

Your solution seems to be working but now, instead of not found page, title is changing into [deleted expense]

https://github.com/user-attachments/assets/53a2fef7-fb71-4685-b0ae-f0af7ea55a9c

Screenshot 2024-08-10 at 7 25 11 PM
melvin-bot[bot] commented 3 months ago

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

allgandalf commented 3 months ago

That is because we wait for the action to get completed, but if we want it to happen in the background then we can do it without waiting for the interaction to be completed:

https://github.com/Expensify/App/blob/d8622863739197affbcf5d3400f6964761608309/src/libs/ReportUtils.ts#L3828

@allgandalf Sorry missed your proposal.

Actually i am sorry @alitoshmatov , for not posting a proper proposal format, it happened that i came in from slack to test this bug and posted a simple fix for it. do let me know if you need any other details

melvin-bot[bot] commented 3 months ago

@iwiznia, @sonialiap, @alitoshmatov Whoops! This issue is 2 days overdue. Let's get this updated quick!

melvin-bot[bot] commented 3 months ago

@iwiznia @sonialiap @alitoshmatov this issue is now 4 weeks old, please consider:

Thanks!

daledah commented 3 months ago

We need IOU.deleteMoneyRequest to be executed so it returns a url to navigate back. How are planning on not calling this function but still getting url to navigate back?

Updating on this shortly...

daledah commented 3 months ago

We need IOU.deleteMoneyRequest to be executed so it returns a url to navigate back. How are planning on not calling this function but still getting url to navigate back?

urlToNavigateBack is just a value that's returned from prepareToCleanUpMoneyRequest (reference), so we can call prepareToCleanUpMoneyRequest directly to get it, no need to call IOU.deleteMoneyRequest.

const { urlToNavigateBack } = IOU.prepareToCleanUpMoneyRequest(iouTransactionID, requestParentReportAction, true);

(prepareToCleanUpMoneyRequest needs to be exported from IOU)

Alternatively, we can extract only the parts that produce the urlToNavigateBack inside prepareToCleanUpMoneyRequest into a new method getUrlToNavigateBackAfterMoneyRequestCleanUp

melvin-bot[bot] commented 3 months ago

@iwiznia, @sonialiap, @alitoshmatov Huh... This is 4 days overdue. Who can take care of this?

melvin-bot[bot] commented 3 months ago

Triggered auto assignment to @RachCHopkins (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.

sonialiap commented 3 months ago

@RachCHopkins I'm OOO Aug 19-30, adding leave buddy. Status: waiting for proposals / C+ to review proposals

alitoshmatov commented 3 months ago

That is because we wait for the action to get completed, but if we want it to happen in the background then we can do it without waiting for the interaction to be completed:

@allgandalf That does still not work

alitoshmatov commented 3 months ago

@daledah Can you provide detailed changes for your solution, I am still struggling to understand it.

melvin-bot[bot] commented 3 months ago

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

iwiznia commented 3 months ago

No Melvin, still evaluating proposals

daledah commented 3 months ago

Updating on this tomorrow!

melvin-bot[bot] commented 3 months ago

@iwiznia, @sonialiap, @RachCHopkins, @alitoshmatov Whoops! This issue is 2 days overdue. Let's get this updated quick!

daledah commented 2 months ago

@alitoshmatov Proposal updated to highlight detailed code changes

mvtglobally commented 2 months ago

Issue not reproducible during KI retests. (First week)

melvin-bot[bot] commented 2 months ago

@iwiznia, @sonialiap, @RachCHopkins, @alitoshmatov Huh... This is 4 days overdue. Who can take care of this?

wildan-m commented 2 months ago

Edited by proposal-police: This proposal was edited at 2024-10-07 09:47:20 UTC.

Proposal

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

  1. The "Not here" page briefly appears when deleting expenses.
  2. [Deleted expense] briefly appear when deleting the expense

What is the root cause of that problem?

  1. We completely remove the thread report object that cause shouldShowNotFoundPage true.
  2. There is race condition between dismissing the ReportDetailsPage and deleting the expense.

These issues are noticeable on mobile devices due to their slower performance compared to web/desktop, but they occur across all platforms and layout sizes.

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

We should decouple target URL generation when deleting a transaction, navigate to target url on confirm delete and perform actual deletion after ReportDetailsPage unmounted.

Extract url generation to these components getNavigationUrlAfterTaskDelete, getNavigationUrlAfterMoneyRequestDelete, getNavigationUrlAfterTrackExpenseDelete.

Decoupled functions ```tsx /** * Calculate the URL to navigate to after a money request deletion * @param transactionID - The ID of the money request being deleted * @param reportAction - The report action associated with the money request * @param isSingleTransactionView - Whether we're in single transaction view * @returns The URL to navigate to */ function getNavigationUrlAfterMoneyRequestDelete( transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false ): string | undefined { const { shouldDeleteTransactionThread, shouldDeleteIOUReport, iouReport, } = prepareToCleanUpMoneyRequest(transactionID, reportAction, isSingleTransactionView); // Determine which report to navigate back to if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) { return ROUTES.REPORT_WITH_ID.getRoute(iouReport.reportID); } if (iouReport?.chatReportID && shouldDeleteIOUReport) { return ROUTES.REPORT_WITH_ID.getRoute(iouReport.chatReportID); } return undefined; } /** * Calculate the URL to navigate to after a track expense deletion * @param chatReportID - The ID of the chat report containing the track expense * @param transactionID - The ID of the track expense being deleted * @param reportAction - The report action associated with the track expense * @param isSingleTransactionView - Whether we're in single transaction view * @returns The URL to navigate to */ function getNavigationUrlAfterTrackExpenseDelete( chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false ): string | undefined { const chatReport = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] ?? null; // If not a self DM, handle it as a regular money request if (!ReportUtils.isSelfDM(chatReport)) { return getNavigationUrlAfterMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView); } const transactionThreadID = reportAction.childReportID; const shouldDeleteTransactionThread = transactionThreadID ? (reportAction?.childVisibleActionCount ?? 0) === 0 : false; // Only navigate if in single transaction view and the thread will be deleted if (isSingleTransactionView && shouldDeleteTransactionThread && chatReport?.reportID) { // Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report. return ROUTES.REPORT_WITH_ID.getRoute(chatReport.reportID); } return undefined; } /** * Calculate the URL to navigate to after a task deletion * @param report - The task report being deleted * @returns The URL to navigate to */ function getNavigationUrlAfterTaskDelete(report: OnyxEntry): string | undefined { if (!report) { return undefined; } const shouldDeleteTaskReport = !ReportActionsUtils.doesReportHaveVisibleActions(report.reportID ?? '-1'); if (!shouldDeleteTaskReport) { return undefined; } // First try to navigate to parent report const parentReport = getParentReport(report); if (parentReport?.reportID) { return ROUTES.REPORT_WITH_ID.getRoute(parentReport.reportID); } // If no parent report, try to navigate to most recent report const mostRecentReportID = Report.getMostRecentReportID(report); if (mostRecentReportID) { return ROUTES.REPORT_WITH_ID.getRoute(mostRecentReportID); } return undefined; } ```

Move onHideModalLogic to a new function navigateToTargetUrl that will only navigate without actual deletion

navigateToTargetUrl ```tsx // Where to go back after deleting the transaction and its report. const navigateToTargetUrl = useCallback(() => { setIsDeleteModalVisible(false); isTransactionDeleted.current = true; let urlToNavigateBack: string | undefined; if (caseID === CASES.DEFAULT) { urlToNavigateBack = IOU.getUrlToNavigateBackForTask(report); Onyx.set(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, urlToNavigateBack); if (urlToNavigateBack) { Navigation.goBack(urlToNavigateBack as Route); } else { Navigation.dismissModal(); } return; } if (!requestParentReportAction) { return; } const isTrackExpense = ReportActionsUtils.isTrackExpenseAction(requestParentReportAction); if (isTrackExpense) { urlToNavigateBack = IOU.getUrlToNavigateBackForTrackExpense(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, isSingleTransactionView); } else { urlToNavigateBack = IOU.getUrlToNavigateBackForMoneyRequest(iouTransactionID, requestParentReportAction, isSingleTransactionView); } Onyx.set(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, urlToNavigateBack); if (!urlToNavigateBack) { Navigation.dismissModal(); } else { ReportUtils.navigateBackAfterDeleteTransaction(urlToNavigateBack as Route, true); } }, [caseID, iouTransactionID, moneyRequestReport?.reportID, report, requestParentReportAction, isSingleTransactionView, setIsDeleteModalVisible, isTransactionDeleted]); ```

The deleteTransaction will only responsible for actual deletion without URL generation and will be called in unmount phase of ReportDetailsPage if isTransactionDeleted.current true.

deleteTransaction function ```tsx const deleteTransaction = useCallback(() => { if (caseID === CASES.DEFAULT) { Task.deleteTask(report); return; } if (!requestParentReportAction) { return; } const isTrackExpense = ReportActionsUtils.isTrackExpenseAction(requestParentReportAction); if (isTrackExpense) { IOU.deleteTrackExpense(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, isSingleTransactionView); } else { IOU.deleteMoneyRequest(iouTransactionID, requestParentReportAction, isSingleTransactionView); } }, [caseID, iouTransactionID, isSingleTransactionView, moneyRequestReport?.reportID, report, requestParentReportAction]); ```

    useEffect(() => {
        return () => {
            if (!isTransactionDeleted.current) {
                return;
            }

            deleteTransaction();
        };
    }, []);

In mWeb, even when we navigate to destination report earlier, not found might still appear, to handle this we can re-implement soft deletion of thread report from my previous proposal (see. alternative proposal),

Soft deletion snippet ```tsx if (shouldDeleteTransactionThread) { optimisticData.push( { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`, value: { reportID: null, stateNum: CONST.REPORT.STATE_NUM.APPROVED, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, participants: { [userAccountID]: { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }, }, }, }, .............. if (shouldDeleteTransactionThread && transactionThread) { successData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`, value: Object.keys(transactionThread).reduce>((acc, key) => { acc[key] = null; return acc; }, {}), }); } .............. ```

Optional

After we implement the solution, the update of target report might be delayed. This is expected because we reach the target report too early

https://github.com/user-attachments/assets/d68329c9-cd9b-4a66-977a-93c69382ebfa

[!NOTE]
Auto scroll issue is known separate issue https://github.com/Expensify/App/issues/45576#issuecomment-2384466032

If we don't want to show the delay, we can store target url in NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL to determine if we should show skeleton or not.

In Task.deleteTask, IOU.deleteTrackExpense, IOU.deleteMoneyRequest reset NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL when optimisticData updated


    optimisticData.push({
        onyxMethod: Onyx.METHOD.SET,
        key: ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL,
        value: null,
    });

Add new useEffect to clear the url and modify shouldShowSkeleton logic in ReportScreen


    const [deleteTransactionNavigateBackUrl] = useOnyx(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL);

    useEffect(() => {
        if (!isFocused || !deleteTransactionNavigateBackUrl) {
            return;
        }
        // Schedule the code to run after the current call stack is cleared,
        // ensuring all updates are processed before hide the skeleton
        lodashDefer(() => {
            Onyx.merge(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, null);
        });
    }, [isFocused]);

    const isLoading = isLoadingApp ?? ((!reportIDFromRoute || (!isSidebarLoaded && !isInNarrowPaneModal) || PersonalDetailsUtils.isPersonalDetailsEmpty()));
    const shouldShowSkeleton =
        (isLinkingToMessage && !isLinkedMessagePageReady) ||
        (!isLinkingToMessage && !isInitialPageReady) ||
        isEmptyObject(reportOnyx) ||
        isLoadingReportOnyx ||
        !isCurrentReportLoadedFromOnyx ||
        (deleteTransactionNavigateBackUrl && ReportUtils.getReportIDFromLink(deleteTransactionNavigateBackUrl) === report?.reportID) ||
        isLoading;

Further, we can make Task.deleteTask, IOU.deleteTrackExpense, IOU.deleteMoneyRequest completely not return URL or use our new decoupled functions to prevent duplicate code.

Branch for this solution

What alternative solutions did you explore? (Optional)

[!NOTE]
This solution not solve all cases

  1. We can soft delete the report first and then completely delete the report object when the API call success. This pattern also implemented when we leaving a room.

https://github.com/Expensify/App/blob/f58439cfb116abd338dae880088a26725794108e/src/libs/actions/Report.ts#L2819-L2824

Change transaction thread optimistic data

https://github.com/Expensify/App/blob/f58439cfb116abd338dae880088a26725794108e/src/libs/actions/IOU.ts#L5793-L5799

To

    if (shouldDeleteTransactionThread) {
        optimisticData.push(
            {
                onyxMethod: Onyx.METHOD.MERGE,
                key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
                value: {
                    reportID: null,
                    stateNum: CONST.REPORT.STATE_NUM.APPROVED,
                    statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
                    notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
                },
            },

When success, remove remaining properties value to ensure the object completely deleted:

    if(shouldDeleteTransactionThread) {
        successData.push({
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
            value: Object.keys(transactionThread as OnyxTypes.Report).reduce<Record<string, null>>((acc, key) => {
                        acc[key] = null;
                        return acc;
                    }, {}),
        })
    }

Do the same for getDeleteTrackExpenseInformation

  1. To handle [deleted expense] issue, we can delay the delete process until the confirm modal hidden. Introduce new ref isDeletedButtonPressed to know that the deletion process confirmed.

Change

https://github.com/Expensify/App/blob/f58439cfb116abd338dae880088a26725794108e/src/pages/ReportDetailsPage.tsx#L788

To:

                    onConfirm={()=>{
                        Navigation.dismissModal();
                        setIsDeleteModalVisible(false);
                        isDeletedButtonPressed.current = true;
                    }}

And modify onModalHide to:

                    onModalHide={() => {
                        if (isDeletedButtonPressed.current) {
                            deleteTransaction();
                        }

                        // We use isTransactionDeleted to know if the modal hides because the user deletes the transaction.
                        if (!isTransactionDeleted.current) {
                            if (caseID === CASES.DEFAULT) {
                                if (navigateBackToAfterDelete.current) {
......

Remove setIsDeleteModalVisible(false); in deleteTransaction

Branch for this solution

alitoshmatov commented 2 months ago

@wildan-m Thank you for your proposal, I really liked the first solution, but does not solve the complete problem. The second solution I think is similar to @daledah 's proposal in some way.

alitoshmatov commented 2 months ago

I think we can go with @daledah 's proposal which suggests delaying deletion until page animation is complete

C+ reviewed 🎀 👀 🎀

melvin-bot[bot] commented 2 months ago

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

wildan-m commented 2 months ago

@alitoshmatov Thanks for your review. I wanted to clarify that I only proposed one solution for each issue. They should be implemented together since the root causes are different. My delay for the second issue is based on the hide modal event, not on a timeout. I believe this should be considered distinct.

luacmartins commented 2 months ago

Proposal LGTM and we already call the same navigateBackAfterDeleteTransaction in a few other places.

melvin-bot[bot] commented 2 months ago

📣 @alitoshmatov 🎉 An offer has been automatically sent to your Upwork account for the Reviewer role 🎉 Thanks for contributing to the Expensify app!

Offer link Upwork job

melvin-bot[bot] commented 2 months ago

📣 @daledah You have been assigned to this job! Please apply to the Upwork job and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻 Once you apply to this job, your Upwork ID will be stored and you will be automatically hired for future jobs! Keep in mind: Code of Conduct | Contributing 📖

daledah commented 2 months ago

@alitoshmatov This PR is ready for review.

RachCHopkins commented 2 months ago

@alitoshmatov how is this going?

sonialiap commented 2 months ago

@RachCHopkins thanks for buddy sitting this! Taking it back off of your plate 🍽️