diff --git a/patches/@react-navigation+stack+6.3.29+002+dontDetachScreen.patch b/patches/@react-navigation+stack+6.3.29+002+dontDetachScreen.patch index 529e9aab0221..8cd2a1c2f7f6 100644 --- a/patches/@react-navigation+stack+6.3.29+002+dontDetachScreen.patch +++ b/patches/@react-navigation+stack+6.3.29+002+dontDetachScreen.patch @@ -43,7 +43,7 @@ index 7558eb3..b7bb75e 100644 }) : STATE_TRANSITIONING_OR_BELOW_TOP; } + -+ const isHomeScreenAndNotOnTop = (route.name === 'BottomTabNavigator' || route.name === 'Workspace_Initial' || route.name === 'Home' || route.name === 'Search_Bottom_Tab' || route.name === 'Settings_Root') && isScreenActive !== STATE_ON_TOP; ++ const isHomeScreenAndNotOnTop = (route.name === 'BottomTabNavigator' || route.name === 'Workspace_Initial' || route.name === 'Home' || route.name === 'Search_Bottom_Tab' || route.name === 'Settings_Root' || route.name === 'ReportsSplitNavigator' || route.name === 'Search_Central_Pane') && isScreenActive !== STATE_ON_TOP; + const { headerShown = true, diff --git a/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred.ts b/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred.ts new file mode 100644 index 000000000000..beae98460c1a --- /dev/null +++ b/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred.ts @@ -0,0 +1,9 @@ +import type {NavigationState} from '@react-navigation/native'; +import {isFullScreenName} from '@libs/NavigationUtils'; + +function getIsScreenBlurred(state: NavigationState, currentRouteKey: string) { + const lastFullScreenRoute = state.routes.findLast((route) => isFullScreenName(route.name)); + return lastFullScreenRoute?.key !== currentRouteKey; +} + +export default getIsScreenBlurred; diff --git a/src/libs/Navigation/AppNavigator/FreezeWrapper/index.native.tsx b/src/libs/Navigation/AppNavigator/FreezeWrapper/index.native.tsx new file mode 100644 index 000000000000..bb8b070f4545 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/FreezeWrapper/index.native.tsx @@ -0,0 +1,28 @@ +import {useNavigation, useRoute} from '@react-navigation/native'; +import React, {useEffect, useState} from 'react'; +import {Freeze} from 'react-freeze'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import getIsScreenBlurred from './getIsScreenBlurred'; + +type FreezeWrapperProps = ChildrenProps & { + /** Prop to disable freeze */ + keepVisible?: boolean; +}; + +function FreezeWrapper({keepVisible = false, children}: FreezeWrapperProps) { + const navigation = useNavigation(); + const currentRoute = useRoute(); + + const [isScreenBlurred, setIsScreenBlurred] = useState(false); + + useEffect(() => { + const unsubscribe = navigation.addListener('state', (e) => setIsScreenBlurred(getIsScreenBlurred(e.data.state, currentRoute.key))); + return () => unsubscribe(); + }, [currentRoute.key, navigation]); + + return {children}; +} + +FreezeWrapper.displayName = 'FreezeWrapper'; + +export default FreezeWrapper; diff --git a/src/libs/Navigation/AppNavigator/FreezeWrapper/index.tsx b/src/libs/Navigation/AppNavigator/FreezeWrapper/index.tsx new file mode 100644 index 000000000000..98133c3f7796 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/FreezeWrapper/index.tsx @@ -0,0 +1,35 @@ +import {useNavigation, useRoute} from '@react-navigation/native'; +import React, {useEffect, useLayoutEffect, useState} from 'react'; +import {Freeze} from 'react-freeze'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import getIsScreenBlurred from './getIsScreenBlurred'; + +type FreezeWrapperProps = ChildrenProps & { + /** Prop to disable freeze */ + keepVisible?: boolean; +}; + +function FreezeWrapper({keepVisible = false, children}: FreezeWrapperProps) { + const navigation = useNavigation(); + const currentRoute = useRoute(); + + const [isScreenBlurred, setIsScreenBlurred] = useState(false); + const [freezed, setFreezed] = useState(false); + + useEffect(() => { + const unsubscribe = navigation.addListener('state', (e) => setIsScreenBlurred(getIsScreenBlurred(e.data.state, currentRoute.key))); + return () => unsubscribe(); + }, [currentRoute.key, navigation]); + + // Decouple the Suspense render task so it won't be interrupted by React's concurrent mode + // and stuck in an infinite loop + useLayoutEffect(() => { + setFreezed(isScreenBlurred && !keepVisible); + }, [isScreenBlurred, keepVisible]); + + return {children}; +} + +FreezeWrapper.displayName = 'FreezeWrapper'; + +export default FreezeWrapper; diff --git a/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx index daaabf1094b4..c83816a21b5d 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx @@ -1,42 +1,19 @@ -import {useNavigationState, useRoute} from '@react-navigation/native'; import React, {useRef} from 'react'; -import {Freeze} from 'react-freeze'; import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import usePermissions from '@hooks/usePermissions'; -import memoize from '@libs/memoize'; import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator'; +import FreezeWrapper from '@libs/Navigation/AppNavigator/FreezeWrapper'; import getCurrentUrl from '@libs/Navigation/currentUrl'; import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom'; import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types'; -import {isFullScreenName} from '@libs/NavigationUtils'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; import SCREENS from '@src/SCREENS'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; -function FrozenScreen(WrappedComponent: React.ComponentType, freeze: boolean) { - return (props: TProps) => ( - - - - ); -} - -function freezeScreenWithLazyLoading(lazyComponent: () => React.ComponentType, freeze: boolean) { - return memoize( - () => { - const Component = lazyComponent(); - return FrozenScreen(Component, freeze); - }, - {monitoringName: 'freezeScreenWithLazyLoading'}, - ); -} - const loadReportScreen = () => require('../../../../pages/home/ReportScreen').default; +const loadSidebarScreen = () => require('@pages/home/sidebar/SidebarScreen').default; const Stack = createSplitStackNavigator(); @@ -47,8 +24,8 @@ function ReportsSplitNavigator() { let initialReportID: string | undefined; const isInitialRender = useRef(true); - const currentRoute = useRoute(); - + // TODO: Figure out if compiler affects this code. + // eslint-disable-next-line react-compiler/react-compiler if (isInitialRender.current) { const currentURL = getCurrentUrl(); if (currentURL) { @@ -60,18 +37,12 @@ function ReportsSplitNavigator() { initialReportID = initialReport?.reportID ?? ''; } + // eslint-disable-next-line react-compiler/react-compiler isInitialRender.current = false; } - const shouldFreeze = useNavigationState((state) => { - const lastFullScreenRoute = state.routes.findLast((route) => isFullScreenName(route.name)); - return lastFullScreenRoute?.key !== currentRoute.key; - }); - - const getSidebarScreen = freezeScreenWithLazyLoading(() => require('@pages/home/sidebar/SidebarScreen').default, shouldFreeze); - return ( - + - + ); } diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 11c7a45f33b3..df425c23562f 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -15,6 +15,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; import BottomTabBar from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar'; import TopBar from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar'; +import FreezeWrapper from '@libs/Navigation/AppNavigator/FreezeWrapper'; import Navigation from '@libs/Navigation/Navigation'; import type {AuthScreensParamList} from '@libs/Navigation/types'; import * as SearchQueryUtils from '@libs/SearchQueryUtils'; @@ -58,54 +59,56 @@ function SearchPage({route}: SearchPageProps) { } return ( - - {!!queryJSON && ( - - - {/* {!selectionMode?.isEnabled && queryJSON ? ( */} - {queryJSON ? ( - - + + {!!queryJSON && ( + + + {/* {!selectionMode?.isEnabled && queryJSON ? ( */} + {queryJSON ? ( + + + + + ) : ( + { + clearSelectedTransactions(); + turnOffMobileSelectionMode(); + }} /> - - - ) : ( - { - clearSelectedTransactions(); - turnOffMobileSelectionMode(); - }} + )} + + + + - )} - + + + - - - - - - - )} - + )} + + ); }