1- import type { NavigationState } from '@react-navigation/native' ;
1+ import type { NavigationState , PartialState } from '@react-navigation/native' ;
22import React , { createContext , startTransition , useCallback , useContext , useMemo , useRef , useState } from 'react' ;
33import Navigation from '@libs/Navigation/Navigation' ;
4+ import NAVIGATORS from '@src/NAVIGATORS' ;
45
56type CurrentReportIDStateContextType = {
67 currentReportID : string | undefined ;
8+ currentRHPReportID ?: string | undefined ;
79} ;
810
911type CurrentReportIDActionsContextType = {
@@ -20,28 +22,46 @@ type CurrentReportIDContextProviderProps = {
2022 onSetCurrentReportID ?: ( reportID : string | undefined ) => void ;
2123} ;
2224
25+ /**
26+ * Traverse the focused route at each level of the navigation state to find a reportID param.
27+ * This handles modal navigators (e.g. RightModalNavigator > ExpenseReport) that carry a reportID
28+ * in their screen params but are not part of the ReportsSplitNavigator hierarchy.
29+ */
30+ function getFocusedRouteReportID ( state : NavigationState | PartialState < NavigationState > ) : string | undefined {
31+ const index = state . index ?? state . routes . length - 1 ;
32+ const focusedRoute = state . routes [ index ] ;
33+ if ( ! focusedRoute ) {
34+ return ;
35+ }
36+ if ( focusedRoute . params && 'reportID' in focusedRoute . params && typeof focusedRoute . params . reportID === 'string' ) {
37+ return focusedRoute . params . reportID ;
38+ }
39+ if ( focusedRoute . state ) {
40+ return getFocusedRouteReportID ( focusedRoute . state ) ;
41+ }
42+ }
43+
2344const defaultCurrentReportIDActionsContext : CurrentReportIDActionsContextType = {
2445 updateCurrentReportID : ( ) => { } ,
2546} ;
2647
27- const CurrentReportIDStateContext = createContext < CurrentReportIDStateContextType > ( { currentReportID : undefined } ) ;
48+ const CurrentReportIDStateContext = createContext < CurrentReportIDStateContextType > ( { currentReportID : undefined , currentRHPReportID : undefined } ) ;
2849
2950const CurrentReportIDActionsContext = createContext < CurrentReportIDActionsContextType > ( defaultCurrentReportIDActionsContext ) ;
3051
3152function CurrentReportIDContextProvider ( props : CurrentReportIDContextProviderProps ) {
3253 const [ currentReportID , setCurrentReportID ] = useState < string | undefined > ( '' ) ;
54+ const [ currentRHPReportID , setCurrentRHPReportID ] = useState < string | undefined > ( undefined ) ;
3355 // Tracks the most recently requested reportID synchronously so the dedupe
3456 // check below stays accurate even while a startTransition is pending.
3557 const pendingReportIDRef = useRef < string | undefined > ( '' ) ;
3658
3759 /**
38- * This function is used to update the currentReportID
60+ * This function is used to update the currentReportID and currentRHPReportID
3961 * @param state root navigation state
4062 */
4163 const updateCurrentReportID = useCallback (
4264 ( state : NavigationState ) => {
43- const reportID = Navigation . getTopmostReportId ( state ) ;
44-
4565 /*
4666 * Make sure we don't make the reportID undefined when switching between the chat list and settings tab.
4767 * This helps prevent unnecessary re-renders.
@@ -50,25 +70,31 @@ function CurrentReportIDContextProvider(props: CurrentReportIDContextProviderPro
5070 if ( params && 'screen' in params && typeof params . screen === 'string' && params . screen . indexOf ( 'Settings_' ) !== - 1 ) {
5171 return ;
5272 }
53- if ( pendingReportIDRef . current === reportID ) {
54- return ;
55- }
5673
57- if ( ! pendingReportIDRef . current && ! reportID ) {
58- return ;
74+ const reportID = Navigation . getTopmostReportId ( state ) ;
75+
76+ if ( pendingReportIDRef . current !== reportID ) {
77+ if ( pendingReportIDRef . current || reportID ) {
78+ pendingReportIDRef . current = reportID ;
79+ props . onSetCurrentReportID ?.( reportID ) ;
80+ // Mark the report ID update as a non-urgent transition so React can keep the
81+ // UI responsive to user input while the (potentially expensive) report screen
82+ // re-render is processed in the background.
83+ startTransition ( ( ) => {
84+ setCurrentReportID ( reportID ) ;
85+ } ) ;
86+ }
5987 }
6088
61- pendingReportIDRef . current = reportID ;
62- props . onSetCurrentReportID ?.( reportID ) ;
63- // Mark the report ID update as a non-urgent transition so React can keep the
64- // UI responsive to user input while the (potentially expensive) report screen
65- // re-render is processed in the background.
66- startTransition ( ( ) => {
67- setCurrentReportID ( reportID ) ;
68- } ) ;
89+ const focusedTopRoute = state . routes [ state . index ] ;
90+ const modalReportID = focusedTopRoute ?. name === NAVIGATORS . RIGHT_MODAL_NAVIGATOR && focusedTopRoute . state ? getFocusedRouteReportID ( focusedTopRoute . state ) : undefined ;
91+
92+ if ( currentRHPReportID !== modalReportID && ( currentRHPReportID || modalReportID ) ) {
93+ setCurrentRHPReportID ( modalReportID ) ;
94+ }
6995 } ,
7096 // eslint-disable-next-line react-hooks/exhaustive-deps -- we don't want to re-render when onSetCurrentReportID changes
71- [ setCurrentReportID ] ,
97+ [ setCurrentReportID , setCurrentRHPReportID , currentRHPReportID ] ,
7298 ) ;
7399
74100 const actionsContextValue = useMemo < CurrentReportIDActionsContextType > (
@@ -81,8 +107,9 @@ function CurrentReportIDContextProvider(props: CurrentReportIDContextProviderPro
81107 const stateContextValue = useMemo < CurrentReportIDStateContextType > (
82108 ( ) => ( {
83109 currentReportID,
110+ currentRHPReportID,
84111 } ) ,
85- [ currentReportID ] ,
112+ [ currentReportID , currentRHPReportID ] ,
86113 ) ;
87114
88115 return (
0 commit comments