diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index f97edbd744eb..3c3812774380 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -219,6 +219,9 @@ const ONYXKEYS = { /** The NVP containing all information related to educational tooltip in workspace chat */ NVP_WORKSPACE_TOOLTIP: 'workspaceTooltip', + /** The NVP containing the target url to navigate to when deleting a transaction */ + NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL: 'nvp_deleteTransactionNavigateBackURL', + /** Whether to show save search rename tooltip */ SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP: 'shouldShowSavedSearchRenameTooltip', @@ -1012,6 +1015,7 @@ type OnyxValuesMapping = { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: number; [ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END]: number; [ONYXKEYS.NVP_WORKSPACE_TOOLTIP]: OnyxTypes.WorkspaceTooltip; + [ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL]: string | undefined; [ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP]: boolean; [ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[]; [ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string; diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 008c1353cd68..9ca142aae1b0 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -502,7 +502,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea isVisible={isDeleteRequestModalVisible} onConfirm={deleteTransaction} onCancel={() => setIsDeleteRequestModalVisible(false)} - onModalHide={() => ReportUtils.navigateBackAfterDeleteTransaction(navigateBackToAfterDelete.current)} + onModalHide={() => ReportUtils.navigateBackOnDeleteTransaction(navigateBackToAfterDelete.current)} prompt={translate('iou.deleteConfirmation', {count: 1})} confirmText={translate('common.delete')} cancelText={translate('common.cancel')} diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a19ffbae1703..136521e23f64 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4208,7 +4208,7 @@ function goBackToDetailsPage(report: OnyxEntry, backTo?: string) { Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? '-1', backTo)); } -function navigateBackAfterDeleteTransaction(backRoute: Route | undefined, isFromRHP?: boolean) { +function navigateBackOnDeleteTransaction(backRoute: Route | undefined, isFromRHP?: boolean) { if (!backRoute) { return; } @@ -8720,7 +8720,7 @@ export { canWriteInReport, navigateToDetailsPage, navigateToPrivateNotes, - navigateBackAfterDeleteTransaction, + navigateBackOnDeleteTransaction, parseReportRouteParams, parseReportActionHtmlToText, requiresAttentionFromCurrentUser, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ba5b29a5d217..de1ba6779b28 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -61,6 +61,7 @@ import type {IOUAction, IOUType} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {Route} from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Attendee, Participant, Split} from '@src/types/onyx/IOU'; import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon'; @@ -1795,10 +1796,21 @@ function getDeleteTrackExpenseInformation( if (shouldDeleteTransactionThread) { optimisticData.push( + // Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear. + // The remaining parts of the report object will be removed after the API call is successful. { - onyxMethod: Onyx.METHOD.SET, + onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`, - value: null, + value: { + reportID: null, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.CLOSED, + participants: { + [userAccountID]: { + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, + }, + }, + }, }, { onyxMethod: Onyx.METHOD.SET, @@ -1838,6 +1850,19 @@ function getDeleteTrackExpenseInformation( }, ]; + // Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response. + // This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function. + 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; + }, {}), + }); + } + const failureData: OnyxUpdate[] = []; if (shouldDeleteTransactionFromOnyx) { @@ -5409,10 +5434,9 @@ function updateMoneyRequestAmountAndCurrency({ * * @param transactionID - The transactionID of IOU * @param reportAction - The reportAction of the transaction in the IOU report - * @param isSingleTransactionView - whether we are in the transaction thread report * @return the url to navigate back once the money request is deleted */ -function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false) { +function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction) { // STEP 1: Get all collections we're updating const allReports = ReportConnection.getAllReports(); const iouReportID = ReportActionsUtils.isMoneyRequestAction(reportAction) ? ReportActionsUtils.getOriginalMessage(reportAction)?.IOUReportID : '-1'; @@ -5532,19 +5556,6 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT updatedReportPreviewAction.childMoneyRequestCount = reportPreviewAction.childMoneyRequestCount - 1; } - // STEP 5: Calculate the url that the user will be navigated back to - // This depends on which page they are on and which resources were deleted - let reportIDToNavigateBack: string | undefined; - if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) { - reportIDToNavigateBack = iouReport.reportID; - } - - if (iouReport?.chatReportID && shouldDeleteIOUReport) { - reportIDToNavigateBack = iouReport.chatReportID; - } - - const urlToNavigateBack = reportIDToNavigateBack ? ROUTES.REPORT_WITH_ID.getRoute(reportIDToNavigateBack) : undefined; - return { shouldDeleteTransactionThread, shouldDeleteIOUReport, @@ -5558,10 +5569,59 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT transactionViolations, reportPreviewAction, iouReport, - urlToNavigateBack, }; } +/** + * 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 are in the transaction thread report + * @returns The URL to navigate to + */ +function getNavigationUrlOnMoneyRequestDelete(transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false): Route | undefined { + const {shouldDeleteTransactionThread, shouldDeleteIOUReport, iouReport} = prepareToCleanUpMoneyRequest(transactionID, reportAction); + + // 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): Route | 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 getNavigationUrlOnMoneyRequestDelete(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; +} + /** * * @param transactionID - The transactionID of IOU @@ -5580,9 +5640,9 @@ function cleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repo chatReport, iouReport, reportPreviewAction, - urlToNavigateBack, - } = prepareToCleanUpMoneyRequest(transactionID, reportAction, isSingleTransactionView); + } = prepareToCleanUpMoneyRequest(transactionID, reportAction); + const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView); // build Onyx data // Onyx operations to delete the transaction, update the IOU report action and chat report action @@ -5726,8 +5786,9 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor transactionViolations, iouReport, reportPreviewAction, - urlToNavigateBack, - } = prepareToCleanUpMoneyRequest(transactionID, reportAction, isSingleTransactionView); + } = prepareToCleanUpMoneyRequest(transactionID, reportAction); + + const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView); // STEP 2: Build Onyx data // The logic mostly resembles the cleanUpMoneyRequest function @@ -5747,10 +5808,21 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor if (shouldDeleteTransactionThread) { optimisticData.push( + // Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear. + // The remaining parts of the report object will be removed after the API call is successful. { - onyxMethod: Onyx.METHOD.SET, + onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`, - value: null, + value: { + reportID: null, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.CLOSED, + participants: { + [userAccountID]: { + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, + }, + }, + }, }, { onyxMethod: Onyx.METHOD.SET, @@ -5848,6 +5920,19 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor }, ]; + // Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response. + // This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function. + 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; + }, {}), + }); + } + if (shouldDeleteIOUReport) { successData.push({ onyxMethod: Onyx.METHOD.SET, @@ -5951,15 +6036,18 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor } function deleteTrackExpense(chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false) { + const urlToNavigateBack = getNavigationUrlAfterTrackExpenseDelete(chatReportID, transactionID, reportAction, isSingleTransactionView); + // STEP 1: Get all collections we're updating const chatReport = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] ?? null; if (!ReportUtils.isSelfDM(chatReport)) { - return deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView); + deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView); + return urlToNavigateBack; } const whisperAction = ReportActionsUtils.getTrackExpenseActionableWhisper(transactionID, chatReportID); const actionableWhisperReportActionID = whisperAction?.reportActionID; - const {parameters, optimisticData, successData, failureData, shouldDeleteTransactionThread} = getDeleteTrackExpenseInformation( + const {parameters, optimisticData, successData, failureData} = getDeleteTrackExpenseInformation( chatReportID, transactionID, reportAction, @@ -5974,10 +6062,7 @@ function deleteTrackExpense(chatReportID: string, transactionID: string, reportA CachedPDFPaths.clearByKey(transactionID); // STEP 7: Navigate the user depending on which page they are on and which resources were deleted - if (isSingleTransactionView && shouldDeleteTransactionThread) { - // 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 ?? '-1'); - } + return urlToNavigateBack; } /** @@ -8585,5 +8670,7 @@ export { updateLastLocationPermissionPrompt, resolveDuplicates, getIOUReportActionToApproveOrPay, + getNavigationUrlOnMoneyRequestDelete, + getNavigationUrlAfterTrackExpenseDelete, }; export type {GPSPoint as GpsPoint, IOURequestType}; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 229192e7a7bb..e69fe2de51a1 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2917,6 +2917,8 @@ function leaveGroupChat(reportID: string) { }); } + // Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response. + // This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function. const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -4401,6 +4403,14 @@ function exportReportToCSV({reportID, transactionIDList}: ExportReportCSVParams, fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_CSV}), 'Expensify.csv', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); } +function setDeleteTransactionNavigateBackUrl(url: string) { + Onyx.set(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, url); +} + +function clearDeleteTransactionNavigateBackUrl() { + Onyx.merge(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, null); +} + export type {Video}; export { @@ -4490,4 +4500,6 @@ export { updateReportName, updateRoomVisibility, updateWriteCapability, + setDeleteTransactionNavigateBackUrl, + clearDeleteTransactionNavigateBackUrl, }; diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 15fd39bd66e9..5668d91b4999 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -961,6 +961,36 @@ function getParentReport(report: OnyxEntry): 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; +} + /** * Cancels a task by setting the report state to SUBMITTED and status to CLOSED */ @@ -1117,15 +1147,10 @@ function deleteTask(report: OnyxEntry) { API.write(WRITE_COMMANDS.CANCEL_TASK, parameters, {optimisticData, successData, failureData}); Report.notifyNewAction(report.reportID, currentUserAccountID); - if (shouldDeleteTaskReport) { + const urlToNavigateBack = getNavigationUrlOnTaskDelete(report); + if (urlToNavigateBack) { Navigation.goBack(); - if (parentReport?.reportID) { - return ROUTES.REPORT_WITH_ID.getRoute(parentReport.reportID); - } - const mostRecentReportID = Report.getMostRecentReportID(report); - if (mostRecentReportID) { - return ROUTES.REPORT_WITH_ID.getRoute(mostRecentReportID); - } + return urlToNavigateBack; } } @@ -1239,6 +1264,7 @@ export { canModifyTask, canActionTask, setNewOptimisticAssignee, + getNavigationUrlOnTaskDelete, }; export type {PolicyValue, Assignee, ShareDestination}; diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 3547da8bcc97..961d43bda012 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -795,16 +795,9 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta ); - // A flag to indicate whether the user choose to delete the transaction or not - const isTransactionDeleted = useRef(false); - // Where to go back after deleting the transaction and its report. It's empty if the transaction report isn't deleted. - const navigateBackToAfterDelete = useRef(); - const deleteTransaction = useCallback(() => { - setIsDeleteModalVisible(false); - if (caseID === CASES.DEFAULT) { - navigateBackToAfterDelete.current = Task.deleteTask(report); + Task.deleteTask(report); return; } @@ -812,14 +805,63 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta return; } - if (ReportActionsUtils.isTrackExpenseAction(requestParentReportAction)) { - navigateBackToAfterDelete.current = IOU.deleteTrackExpense(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, isSingleTransactionView); + const isTrackExpense = ReportActionsUtils.isTrackExpenseAction(requestParentReportAction); + + if (isTrackExpense) { + IOU.deleteTrackExpense(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, isSingleTransactionView); } else { - navigateBackToAfterDelete.current = IOU.deleteMoneyRequest(iouTransactionID, requestParentReportAction, isSingleTransactionView); + IOU.deleteMoneyRequest(iouTransactionID, requestParentReportAction, isSingleTransactionView); } + }, [caseID, iouTransactionID, isSingleTransactionView, moneyRequestReport?.reportID, report, requestParentReportAction]); - isTransactionDeleted.current = true; - }, [caseID, iouTransactionID, moneyRequestReport?.reportID, report, requestParentReportAction, isSingleTransactionView]); + // A flag to indicate whether the user chose to delete the transaction or not + const isTransactionDeleted = useRef(false); + + useEffect(() => { + return () => { + // Perform the actual deletion after the details page is unmounted. This prevents the [Deleted ...] text from briefly appearing when dismissing the modal. + if (!isTransactionDeleted.current) { + return; + } + + deleteTransaction(); + }; + }, [deleteTransaction]); + + // Where to navigate back to after deleting the transaction and its report. + const navigateToTargetUrl = useCallback(() => { + let urlToNavigateBack: string | undefined; + + if (!isTransactionDeleted.current) { + if (caseID === CASES.DEFAULT) { + urlToNavigateBack = Task.getNavigationUrlOnTaskDelete(report); + if (urlToNavigateBack) { + Report.setDeleteTransactionNavigateBackUrl(urlToNavigateBack); + Navigation.goBack(urlToNavigateBack as Route); + } else { + Navigation.dismissModal(); + } + return; + } + return; + } + + if (!isEmptyObject(requestParentReportAction)) { + const isTrackExpense = ReportActionsUtils.isTrackExpenseAction(requestParentReportAction); + if (isTrackExpense) { + urlToNavigateBack = IOU.getNavigationUrlAfterTrackExpenseDelete(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, isSingleTransactionView); + } else { + urlToNavigateBack = IOU.getNavigationUrlOnMoneyRequestDelete(iouTransactionID, requestParentReportAction, isSingleTransactionView); + } + } + + if (!urlToNavigateBack) { + Navigation.dismissModal(); + } else { + Report.setDeleteTransactionNavigateBackUrl(urlToNavigateBack); + ReportUtils.navigateBackOnDeleteTransaction(urlToNavigateBack as Route, true); + } + }, [caseID, iouTransactionID, moneyRequestReport?.reportID, report, requestParentReportAction, isSingleTransactionView, isTransactionDeleted]); const mentionReportContextValue = useMemo(() => ({currentReportID: report.reportID, exactlyMatch: true}), [report.reportID]); @@ -912,32 +954,17 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta setIsDeleteModalVisible(false)} - onModalHide={() => { - // 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) { - Navigation.goBack(navigateBackToAfterDelete.current); - } else { - Navigation.dismissModal(); - } - } - return; - } - - if (!navigateBackToAfterDelete.current) { - Navigation.dismissModal(); - } else { - ReportUtils.navigateBackAfterDeleteTransaction(navigateBackToAfterDelete.current, true); - } + onConfirm={() => { + setIsDeleteModalVisible(false); + isTransactionDeleted.current = true; }} + onCancel={() => setIsDeleteModalVisible(false)} prompt={caseID === CASES.DEFAULT ? translate('task.deleteConfirmation') : translate('iou.deleteConfirmation', {count: 1})} confirmText={translate('common.delete')} cancelText={translate('common.cancel')} danger shouldEnableNewFocusManagement + onModalHide={navigateToTargetUrl} /> !!linkedAction && ReportActionsUtils.isWhisperAction(linkedAction) && !(linkedAction?.whisperedToAccountIDs ?? []).includes(currentUserAccountID), [currentUserAccountID, linkedAction], ); + const [deleteTransactionNavigateBackUrl] = useOnyx(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL); + + useEffect(() => { + if (!isFocused || !deleteTransactionNavigateBackUrl) { + return; + } + // Clear the URL after all interactions are processed to ensure all updates are completed before hiding the skeleton + InteractionManager.runAfterInteractions(() => { + requestAnimationFrame(() => { + Report.clearDeleteTransactionNavigateBackUrl(); + }); + }); + }, [isFocused, deleteTransactionNavigateBackUrl]); const isLoading = isLoadingApp ?? (!reportIDFromRoute || (!isSidebarLoaded && !isInNarrowPaneModal) || PersonalDetailsUtils.isPersonalDetailsEmpty()); + const shouldShowSkeleton = (isLinkingToMessage && !isLinkedMessagePageReady) || (!isLinkingToMessage && !isInitialPageReady) || isEmptyObject(reportOnyx) || isLoadingReportOnyx || !isCurrentReportLoadedFromOnyx || + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + (deleteTransactionNavigateBackUrl && ReportUtils.getReportIDFromLink(deleteTransactionNavigateBackUrl) === report?.reportID) || isLoading; const isLinkedActionBecomesDeleted = prevIsLinkedActionDeleted !== undefined && !prevIsLinkedActionDeleted && isLinkedActionDeleted; diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 4430ec0ce052..e8cd65123656 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -2313,7 +2313,7 @@ describe('actions/IOU', () => { }); }); - expect(report).toBeFalsy(); + expect(report?.reportID).toBeFalsy(); mockFetch?.resume?.(); // Then After resuming fetch, the report for the given thread ID still does not exist @@ -2328,7 +2328,7 @@ describe('actions/IOU', () => { }); }); - expect(report).toBeFalsy(); + expect(report?.reportID).toBeFalsy(); }); it('delete the transaction thread if there are only changelogs (i.e. MODIFIED_EXPENSE actions) in the thread', async () => { @@ -2435,7 +2435,7 @@ describe('actions/IOU', () => { }); }); - expect(report).toBeFalsy(); + expect(report?.reportID).toBeFalsy(); }); it('does not delete the transaction thread if there are visible comments in the thread', async () => {