From 92bb48fd8d0426665a816f6939e162e256f67c2e Mon Sep 17 00:00:00 2001 From: Adam Horodyski Date: Fri, 27 Mar 2026 14:54:05 +0100 Subject: [PATCH 1/2] extract ReportNavigateAwayHandler from ReportScreen Co-Authored-By: Claude Opus 4.6 (1M context) --- src/pages/inbox/ReportNavigateAwayHandler.tsx | 218 ++++++++++++++++++ src/pages/inbox/ReportScreen.tsx | 190 +-------------- 2 files changed, 224 insertions(+), 184 deletions(-) create mode 100644 src/pages/inbox/ReportNavigateAwayHandler.tsx diff --git a/src/pages/inbox/ReportNavigateAwayHandler.tsx b/src/pages/inbox/ReportNavigateAwayHandler.tsx new file mode 100644 index 000000000000..a70b28b55742 --- /dev/null +++ b/src/pages/inbox/ReportNavigateAwayHandler.tsx @@ -0,0 +1,218 @@ +import {useIsFocused, useRoute} from '@react-navigation/native'; +import {useEffect, useEffectEvent, useRef} from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; +import {useCurrentReportIDState} from '@hooks/useCurrentReportID'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useOnyx from '@hooks/useOnyx'; +import useParentReportAction from '@hooks/useParentReportAction'; +import usePrevious from '@hooks/usePrevious'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; +import Navigation, {navigationRef} from '@libs/Navigation/Navigation'; +import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; +import {isDeletedParentAction} from '@libs/ReportActionsUtils'; +import {isAdminRoom, isAnnounceRoom, isGroupChat, isMoneyRequest, isMoneyRequestReport, isMoneyRequestReportPendingDeletion, isPolicyExpenseChat} from '@libs/ReportUtils'; +import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@navigation/types'; +import {setShouldShowComposeInput} from '@userActions/Composer'; +import {navigateToConciergeChat} from '@userActions/Report'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import type * as OnyxTypes from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import useReportWasDeleted from './hooks/useReportWasDeleted'; + +type ReportScreenRoute = + | PlatformStackRouteProp + | PlatformStackRouteProp; + +const reportDetailScreens = [ + ...Object.values(SCREENS.REPORT_DETAILS), + ...Object.values(SCREENS.REPORT_SETTINGS), + ...Object.values(SCREENS.PRIVATE_NOTES), + ...Object.values(SCREENS.REPORT_PARTICIPANTS), +]; + +/** + * Check is the report is deleted. + * We currently use useMemo to memorize every properties of the report + * so we can't check using isEmpty. + */ +function isEmpty(report: OnyxEntry): boolean { + if (isEmptyObject(report)) { + return true; + } + return !Object.values(report).some((value) => value !== undefined && value !== ''); +} + +/** + * Component that does not render anything. Owns navigate-on-removal and navigate-on-deletion logic + * that was previously in ReportScreen. + * + * Self-subscribes to route params via useRoute(). + */ +function ReportNavigateAwayHandler() { + const route = useRoute(); + const reportIDFromRoute = getNonEmptyStringOnyxID(route.params?.reportID); + + const isFocused = useIsFocused(); + const {isInNarrowPaneModal} = useResponsiveLayout(); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); + const {currentReportID: currentReportIDValue} = useCurrentReportIDState(); + const isTopMostReportId = currentReportIDValue === reportIDFromRoute; + + const [reportOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportIDFromRoute}`); + const [userLeavingStatus = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportIDFromRoute}`); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); + const [betas] = useOnyx(ONYXKEYS.BETAS); + const [onboarding] = useOnyx(ONYXKEYS.NVP_ONBOARDING); + const isSelfTourViewed = onboarding?.selfTourViewed; + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); + + const report = reportOnyx; + + const parentReportAction = useParentReportAction(reportOnyx); + const deletedParentAction = isDeletedParentAction(parentReportAction); + const prevDeletedParentAction = usePrevious(deletedParentAction); + + const prevReport = usePrevious(report); + const prevUserLeavingStatus = usePrevious(userLeavingStatus); + const lastReportIDFromRoute = usePrevious(reportIDFromRoute); + + const isOptimisticDelete = report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED; + const {wasDeleted: reportWasDeleted, parentReportID: deletedReportParentID} = useReportWasDeleted(reportIDFromRoute, report, isOptimisticDelete, userLeavingStatus); + + const firstRender = useRef(true); + + // Navigation action that reads non-reactive context (concierge params, modal state, etc.) + const navigateAwayFromReport = useEffectEvent((prevOnyxReportID: string | undefined, prevParentReportID: string | undefined) => { + const currentRoute = navigationRef.getCurrentRoute(); + const topmostReportIDInSearchRHP = Navigation.getTopmostSearchReportID(); + const isTopmostSearchReportID = reportIDFromRoute === topmostReportIDInSearchRHP; + const isHoldScreenOpenInRHP = currentRoute?.name === SCREENS.MONEY_REQUEST.HOLD && (route.name === SCREENS.RIGHT_MODAL.SEARCH_REPORT ? isTopmostSearchReportID : isTopMostReportId); + const isReportDetailOpenInRHP = + isTopMostReportId && + reportDetailScreens.find((r) => r === currentRoute?.name) && + !!currentRoute?.params && + typeof currentRoute.params === 'object' && + 'reportID' in currentRoute.params && + reportIDFromRoute === currentRoute.params.reportID; + // Early return if the report we're passing isn't in a focused state. We only want to navigate to Concierge if the user leaves the room from another device or gets removed from the room while the report is in a focused state. + // Prevent auto navigation for report in RHP + if ((!isFocused && !isHoldScreenOpenInRHP && !isReportDetailOpenInRHP) || (!isHoldScreenOpenInRHP && isInNarrowPaneModal)) { + return; + } + Navigation.dismissModal(); + if (Navigation.getTopmostReportId() === prevOnyxReportID) { + Navigation.isNavigationReady().then(() => { + Navigation.popToSidebar(); + }); + } + if (prevParentReportID) { + // Prevent navigation to the IOU/Expense Report if it is pending deletion. + if (isMoneyRequestReportPendingDeletion(prevParentReportID)) { + return; + } + Navigation.isNavigationReady().then(() => { + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(prevParentReportID)); + }); + return; + } + + Navigation.isNavigationReady().then(() => { + navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas, false); + }); + }); + + // Navigate on removal + useEffect(() => { + // We don't want this effect to run on the first render. + if (firstRender.current) { + firstRender.current = false; + return; + } + + const onyxReportID = report?.reportID; + const prevOnyxReportID = prevReport?.reportID; + const wasReportRemoved = !!prevOnyxReportID && prevOnyxReportID === reportIDFromRoute && !onyxReportID; + const isRemovalExpectedForReportType = + isEmpty(report) && + (isMoneyRequest(prevReport) || + isMoneyRequestReport(prevReport) || + isPolicyExpenseChat(prevReport) || + isGroupChat(prevReport) || + isAdminRoom(prevReport) || + isAnnounceRoom(prevReport)); + const didReportClose = wasReportRemoved && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED; + const isTopLevelPolicyRoomWithNoStatus = !report?.statusNum && !prevReport?.parentReportID && prevReport?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM; + const isClosedTopLevelPolicyRoom = wasReportRemoved && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && isTopLevelPolicyRoomWithNoStatus; + // Navigate to the Concierge chat if the room was removed from another device (e.g. user leaving a room or removed from a room) + if ( + // non-optimistic case + (!prevUserLeavingStatus && !!userLeavingStatus) || + didReportClose || + isRemovalExpectedForReportType || + isClosedTopLevelPolicyRoom || + (prevDeletedParentAction && !deletedParentAction) + ) { + navigateAwayFromReport(prevOnyxReportID, prevReport?.parentReportID); + return; + } + + // If you already have a report open and are deeplinking to a new report on native, + // the ReportScreen never actually unmounts and the reportID in the route also doesn't change. + // Therefore, we need to compare if the existing reportID is the same as the one in the route + // before deciding that we shouldn't call OpenReport. + if (reportIDFromRoute === lastReportIDFromRoute && (!onyxReportID || onyxReportID === reportIDFromRoute)) { + return; + } + + setShouldShowComposeInput(true); + }, [ + report, + prevReport?.reportID, + prevUserLeavingStatus, + userLeavingStatus, + prevReport?.statusNum, + prevReport?.parentReportID, + prevReport?.chatType, + prevReport, + reportIDFromRoute, + lastReportIDFromRoute, + isFocused, + deletedParentAction, + prevDeletedParentAction, + ]); + + // Navigate on deletion + useEffect(() => { + if (!reportWasDeleted) { + return; + } + + // Only redirect if focused + if (!isFocused) { + return; + } + + // Try to navigate to parent report if available + if (deletedReportParentID && !isMoneyRequestReportPendingDeletion(deletedReportParentID)) { + Navigation.isNavigationReady().then(() => { + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(deletedReportParentID)); + }); + return; + } + + // Fallback to Concierge + Navigation.isNavigationReady().then(() => { + navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas); + }); + }, [reportWasDeleted, isFocused, deletedReportParentID, conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas]); + + return null; +} + +ReportNavigateAwayHandler.displayName = 'ReportNavigateAwayHandler'; + +export default ReportNavigateAwayHandler; diff --git a/src/pages/inbox/ReportScreen.tsx b/src/pages/inbox/ReportScreen.tsx index 9ab0402f7c47..cf423108da03 100644 --- a/src/pages/inbox/ReportScreen.tsx +++ b/src/pages/inbox/ReportScreen.tsx @@ -1,6 +1,5 @@ import {PortalHost} from '@gorhom/portal'; -import {useIsFocused} from '@react-navigation/native'; -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useCallback, useMemo} from 'react'; import type {ViewStyle} from 'react-native'; // We use Animated for all functionality related to wide RHP to make it easier // to interact with react-navigation components (e.g., CardContainer, interpolator), which also use Animated. @@ -20,7 +19,6 @@ import useShowWideRHPVersion from '@components/WideRHPContextProvider/useShowWid import WideRHPOverlayWrapper from '@components/WideRHPOverlayWrapper'; import useActionListContextValue from '@hooks/useActionListContextValue'; import {useCurrentReportIDState} from '@hooks/useCurrentReportID'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDocumentTitle from '@hooks/useDocumentTitle'; import useIsInSidePanel from '@hooks/useIsInSidePanel'; import useIsReportReadyToDisplay from '@hooks/useIsReportReadyToDisplay'; @@ -29,7 +27,6 @@ import useNewTransactions from '@hooks/useNewTransactions'; import useOnyx from '@hooks/useOnyx'; import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; import useParentReportAction from '@hooks/useParentReportAction'; -import usePrevious from '@hooks/usePrevious'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useReportTransactionsCollection from '@hooks/useReportTransactionsCollection'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -39,44 +36,29 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useViewportOffsetTop from '@hooks/useViewportOffsetTop'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {getAllNonDeletedTransactions, shouldDisplayReportTableView, shouldWaitForTransactions as shouldWaitForTransactionsUtil} from '@libs/MoneyRequestReportUtils'; -import Navigation, {navigationRef} from '@libs/Navigation/Navigation'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; -import {getFilteredReportActionsForReportView, getOneTransactionThreadReportID, isDeletedParentAction, isTransactionThread} from '@libs/ReportActionsUtils'; +import {getFilteredReportActionsForReportView, getOneTransactionThreadReportID, isTransactionThread} from '@libs/ReportActionsUtils'; import {getReportName} from '@libs/ReportNameUtils'; -import { - getReportOfflinePendingActionAndErrors, - isAdminRoom, - isAnnounceRoom, - isGroupChat, - isInvoiceReport, - isMoneyRequest, - isMoneyRequestReport, - isMoneyRequestReportPendingDeletion, - isPolicyExpenseChat, - isReportTransactionThread, -} from '@libs/ReportUtils'; +import {getReportOfflinePendingActionAndErrors, isInvoiceReport, isMoneyRequestReport, isReportTransactionThread} from '@libs/ReportUtils'; import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@navigation/types'; -import {setShouldShowComposeInput} from '@userActions/Composer'; -import {navigateToConciergeChat} from '@userActions/Report'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; -import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import {reportByIDsSelector} from '@src/selectors/Attributes'; import type * as OnyxTypes from '@src/types/onyx'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; import AccountManagerBanner from './AccountManagerBanner'; import {AgentZeroStatusProvider} from './AgentZeroStatusContext'; import DeleteTransactionNavigateBackHandler from './DeleteTransactionNavigateBackHandler'; import HeaderView from './HeaderView'; -import useReportWasDeleted from './hooks/useReportWasDeleted'; import LinkedActionNotFoundGuard from './LinkedActionNotFoundGuard'; import ReactionListWrapper from './ReactionListWrapper'; import ReportActionsView from './report/ReportActionsView'; import ReportFooter from './report/ReportFooter'; import ReportFetchHandler from './ReportFetchHandler'; import ReportLifecycleHandler from './ReportLifecycleHandler'; +import ReportNavigateAwayHandler from './ReportNavigateAwayHandler'; import ReportNotFoundGuard from './ReportNotFoundGuard'; import ReportRouteParamHandler from './ReportRouteParamHandler'; import {ActionListContext} from './ReportScreenContext'; @@ -97,33 +79,10 @@ const defaultReportMetadata = { isOptimisticReport: false, }; -const reportDetailScreens = [ - ...Object.values(SCREENS.REPORT_DETAILS), - ...Object.values(SCREENS.REPORT_SETTINGS), - ...Object.values(SCREENS.PRIVATE_NOTES), - ...Object.values(SCREENS.REPORT_PARTICIPANTS), -]; - -/** - * Check is the report is deleted. - * We currently use useMemo to memorize every properties of the report - * so we can't check using isEmpty. - * - * @param report - */ -function isEmpty(report: OnyxEntry): boolean { - if (isEmptyObject(report)) { - return true; - } - return !Object.values(report).some((value) => value !== undefined && value !== ''); -} - function ReportScreen({route, navigation}: ReportScreenProps) { const styles = useThemeStyles(); const reportIDFromRoute = getNonEmptyStringOnyxID(route.params?.reportID); const reportActionIDFromRoute = route?.params?.reportActionID; - const isFocused = useIsFocused(); - const [firstRender, setFirstRender] = useState(true); const {isOffline} = useNetwork(); const {isInNarrowPaneModal} = useResponsiveLayout(); const isInSidePanel = useIsInSidePanel(); @@ -131,21 +90,12 @@ function ReportScreen({route, navigation}: ReportScreenProps) { const {currentReportID: currentReportIDValue} = useCurrentReportIDState(); const [reportOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportIDFromRoute}`); - const [userLeavingStatus = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportIDFromRoute}`); const [reportNameValuePairsOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportIDFromRoute}`); const [reportMetadata = defaultReportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportIDFromRoute}`); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(reportOnyx?.policyID)}`); - const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); - const [betas] = useOnyx(ONYXKEYS.BETAS); - const [onboarding] = useOnyx(ONYXKEYS.NVP_ONBOARDING); - const isSelfTourViewed = onboarding?.selfTourViewed; - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const parentReportAction = useParentReportAction(reportOnyx); - const deletedParentAction = isDeletedParentAction(parentReportAction); - const prevDeletedParentAction = usePrevious(deletedParentAction); - /** * Create a lightweight Report so as to keep the re-rendering as light as possible by * passing in only the required props. @@ -209,11 +159,6 @@ function ReportScreen({route, navigation}: ReportScreenProps) { useDocumentTitle(getReportName(report, reportAttributes)); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`); - const prevReport = usePrevious(report); - const prevUserLeavingStatus = usePrevious(userLeavingStatus); - const lastReportIDFromRoute = usePrevious(reportIDFromRoute); - - const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const {reportActions: unfilteredReportActions, hasNewerActions, hasOlderActions} = usePaginatedReportActions(reportID, reportActionIDFromRoute); // wrapping in useMemo because this is array operation and can cause performance issues @@ -222,9 +167,6 @@ function ReportScreen({route, navigation}: ReportScreenProps) { const {reportPendingAction, reportErrors} = getReportOfflinePendingActionAndErrors(report); const screenWrapperStyle: ViewStyle[] = [styles.appContent, styles.flex1, {marginTop: viewportOffsetTop}]; - const isOptimisticDelete = report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED; - - const {wasDeleted: reportWasDeleted, parentReportID: deletedReportParentID} = useReportWasDeleted(reportIDFromRoute, report, isOptimisticDelete, userLeavingStatus); const allReportTransactions = useReportTransactionsCollection(reportIDFromRoute); const hasPendingDeletionTransaction = Object.values(allReportTransactions ?? {}).some((transaction) => transaction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); @@ -308,127 +250,6 @@ function ReportScreen({route, navigation}: ReportScreenProps) { const isReportArchived = useReportIsArchived(report?.reportID); const {isEditingDisabled} = useIsReportReadyToDisplay(report, reportIDFromRoute, isReportArchived); - useEffect(() => { - // We don't want this effect to run on the first render. - if (firstRender) { - setFirstRender(false); - return; - } - - const onyxReportID = report?.reportID; - const prevOnyxReportID = prevReport?.reportID; - const wasReportRemoved = !!prevOnyxReportID && prevOnyxReportID === reportIDFromRoute && !onyxReportID; - const isRemovalExpectedForReportType = - isEmpty(report) && - (isMoneyRequest(prevReport) || - isMoneyRequestReport(prevReport) || - isPolicyExpenseChat(prevReport) || - isGroupChat(prevReport) || - isAdminRoom(prevReport) || - isAnnounceRoom(prevReport)); - const didReportClose = wasReportRemoved && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED; - const isTopLevelPolicyRoomWithNoStatus = !report?.statusNum && !prevReport?.parentReportID && prevReport?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM; - const isClosedTopLevelPolicyRoom = wasReportRemoved && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && isTopLevelPolicyRoomWithNoStatus; - // Navigate to the Concierge chat if the room was removed from another device (e.g. user leaving a room or removed from a room) - if ( - // non-optimistic case - (!prevUserLeavingStatus && !!userLeavingStatus) || - didReportClose || - isRemovalExpectedForReportType || - isClosedTopLevelPolicyRoom || - (prevDeletedParentAction && !deletedParentAction) - ) { - const currentRoute = navigationRef.getCurrentRoute(); - const topmostReportIDInSearchRHP = Navigation.getTopmostSearchReportID(); - const isTopmostSearchReportID = reportIDFromRoute === topmostReportIDInSearchRHP; - const isHoldScreenOpenInRHP = - currentRoute?.name === SCREENS.MONEY_REQUEST.HOLD && (route.name === SCREENS.RIGHT_MODAL.SEARCH_REPORT ? isTopmostSearchReportID : isTopMostReportId); - const isReportDetailOpenInRHP = - isTopMostReportId && - reportDetailScreens.find((r) => r === currentRoute?.name) && - !!currentRoute?.params && - typeof currentRoute.params === 'object' && - 'reportID' in currentRoute.params && - reportIDFromRoute === currentRoute.params.reportID; - // Early return if the report we're passing isn't in a focused state. We only want to navigate to Concierge if the user leaves the room from another device or gets removed from the room while the report is in a focused state. - // Prevent auto navigation for report in RHP - if ((!isFocused && !isHoldScreenOpenInRHP && !isReportDetailOpenInRHP) || (!isHoldScreenOpenInRHP && isInNarrowPaneModal)) { - return; - } - Navigation.dismissModal(); - if (Navigation.getTopmostReportId() === prevOnyxReportID) { - Navigation.isNavigationReady().then(() => { - Navigation.popToSidebar(); - }); - } - if (prevReport?.parentReportID) { - // Prevent navigation to the IOU/Expense Report if it is pending deletion. - if (isMoneyRequestReportPendingDeletion(prevReport.parentReportID)) { - return; - } - Navigation.isNavigationReady().then(() => { - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(prevReport.parentReportID)); - }); - return; - } - - Navigation.isNavigationReady().then(() => { - navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas, false); - }); - return; - } - - // If you already have a report open and are deeplinking to a new report on native, - // the ReportScreen never actually unmounts and the reportID in the route also doesn't change. - // Therefore, we need to compare if the existing reportID is the same as the one in the route - // before deciding that we shouldn't call OpenReport. - if (reportIDFromRoute === lastReportIDFromRoute && (!onyxReportID || onyxReportID === reportIDFromRoute)) { - return; - } - - setShouldShowComposeInput(true); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - route.name, - report, - prevReport?.reportID, - prevUserLeavingStatus, - userLeavingStatus, - prevReport?.statusNum, - prevReport?.parentReportID, - prevReport?.chatType, - prevReport, - reportIDFromRoute, - lastReportIDFromRoute, - isFocused, - deletedParentAction, - prevDeletedParentAction, - ]); - - useEffect(() => { - if (!reportWasDeleted) { - return; - } - - // Only redirect if focused - if (!isFocused) { - return; - } - - // Try to navigate to parent report if available - if (deletedReportParentID && !isMoneyRequestReportPendingDeletion(deletedReportParentID)) { - Navigation.isNavigationReady().then(() => { - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(deletedReportParentID)); - }); - return; - } - - // Fallback to Concierge - Navigation.isNavigationReady().then(() => { - navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas); - }); - }, [reportWasDeleted, isFocused, deletedReportParentID, conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas]); - const actionListValue = useActionListContextValue(); // wrapping into useMemo to stabilize children re-renders as reportMetadata is changed frequently @@ -478,6 +299,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { + From 12abeec950c5be49d07887e1b273fa038c29bc17 Mon Sep 17 00:00:00 2001 From: Adam Horodyski Date: Fri, 3 Apr 2026 16:50:06 +0200 Subject: [PATCH 2/2] remove dead reportOnyx alias in ReportNavigateAwayHandler Co-Authored-By: Claude Opus 4.6 (1M context) --- src/pages/inbox/ReportNavigateAwayHandler.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/inbox/ReportNavigateAwayHandler.tsx b/src/pages/inbox/ReportNavigateAwayHandler.tsx index a70b28b55742..1022dcab9fe9 100644 --- a/src/pages/inbox/ReportNavigateAwayHandler.tsx +++ b/src/pages/inbox/ReportNavigateAwayHandler.tsx @@ -62,7 +62,7 @@ function ReportNavigateAwayHandler() { const {currentReportID: currentReportIDValue} = useCurrentReportIDState(); const isTopMostReportId = currentReportIDValue === reportIDFromRoute; - const [reportOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportIDFromRoute}`); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportIDFromRoute}`); const [userLeavingStatus = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportIDFromRoute}`); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [betas] = useOnyx(ONYXKEYS.BETAS); @@ -70,9 +70,7 @@ function ReportNavigateAwayHandler() { const isSelfTourViewed = onboarding?.selfTourViewed; const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); - const report = reportOnyx; - - const parentReportAction = useParentReportAction(reportOnyx); + const parentReportAction = useParentReportAction(report); const deletedParentAction = isDeletedParentAction(parentReportAction); const prevDeletedParentAction = usePrevious(deletedParentAction);