diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js deleted file mode 100644 index 20baf44b23f4..000000000000 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js +++ /dev/null @@ -1,36 +0,0 @@ -import {createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper'; -import getCurrentUrl from '@libs/Navigation/currentUrl'; -import FreezeWrapper from '@libs/Navigation/FreezeWrapper'; -import styles from '@styles/styles'; -import SCREENS from '@src/SCREENS'; - -const Stack = createStackNavigator(); - -const url = getCurrentUrl(); -const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; - -function CentralPaneNavigator() { - return ( - - - - - - ); -} - -export default CentralPaneNavigator; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js new file mode 100644 index 000000000000..a1646011e560 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js @@ -0,0 +1,33 @@ +import {createStackNavigator} from '@react-navigation/stack'; +import React from 'react'; +import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper'; +import getCurrentUrl from '@libs/Navigation/currentUrl'; +import styles from '@styles/styles'; +import SCREENS from '@src/SCREENS'; + +const Stack = createStackNavigator(); + +const url = getCurrentUrl(); +const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; + +function BaseCentralPaneNavigator() { + return ( + + + + ); +} + +export default BaseCentralPaneNavigator; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.js new file mode 100644 index 000000000000..711dd468c77d --- /dev/null +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import BaseCentralPaneNavigator from './BaseCentralPaneNavigator'; + +// We don't need to use freeze wraper on web because we don't render all report routes anyway. +// You can see this optimalization in the customStackNavigator. +function CentralPaneNavigator() { + return ; +} + +export default CentralPaneNavigator; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.js new file mode 100644 index 000000000000..45ab2f070717 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.js @@ -0,0 +1,13 @@ +import React from 'react'; +import FreezeWrapper from '@libs/Navigation/FreezeWrapper'; +import BaseCentralPaneNavigator from './BaseCentralPaneNavigator'; + +function CentralPaneNavigator() { + return ( + + + + ); +} + +export default CentralPaneNavigator; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index ae36f4aff9ad..194b86259107 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -1,8 +1,9 @@ import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; import {StackView} from '@react-navigation/stack'; import PropTypes from 'prop-types'; -import React, {useRef} from 'react'; +import React, {useMemo, useRef} from 'react'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import NAVIGATORS from '@src/NAVIGATORS'; import CustomRouter from './CustomRouter'; const propTypes = { @@ -25,6 +26,24 @@ const defaultProps = { screenOptions: undefined, }; +function splitRoutes(routes) { + const reportRoutes = []; + const rhpRoutes = []; + const otherRoutes = []; + + routes.forEach((route) => { + if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { + reportRoutes.push(route); + } else if (route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR) { + rhpRoutes.push(route); + } else { + otherRoutes.push(route); + } + }); + + return {reportRoutes, rhpRoutes, otherRoutes}; +} + function ResponsiveStackNavigator(props) { const {isSmallScreenWidth} = useWindowDimensions(); @@ -40,12 +59,25 @@ function ResponsiveStackNavigator(props) { getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, }); + const stateToRender = useMemo(() => { + const {reportRoutes, rhpRoutes, otherRoutes} = splitRoutes(state.routes); + + // Remove all report routes except the last 3. This will improve performance. + const limitedReportRoutes = reportRoutes.slice(-3); + + return { + ...state, + index: otherRoutes.length + limitedReportRoutes.length + rhpRoutes.length - 1, + routes: [...otherRoutes, ...limitedReportRoutes, ...rhpRoutes], + }; + }, [state]); + return ( diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js new file mode 100644 index 000000000000..ae36f4aff9ad --- /dev/null +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js @@ -0,0 +1,60 @@ +import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; +import {StackView} from '@react-navigation/stack'; +import PropTypes from 'prop-types'; +import React, {useRef} from 'react'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import CustomRouter from './CustomRouter'; + +const propTypes = { + /* Determines if the navigator should render the StackView (narrow) or ThreePaneView (wide) */ + isSmallScreenWidth: PropTypes.bool.isRequired, + + /* Children for the useNavigationBuilder hook */ + children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired, + + /* initialRouteName for this navigator */ + initialRouteName: PropTypes.oneOf([PropTypes.string, PropTypes.undefined]), + + /* Screen options defined for this navigator */ + // eslint-disable-next-line react/forbid-prop-types + screenOptions: PropTypes.object, +}; + +const defaultProps = { + initialRouteName: undefined, + screenOptions: undefined, +}; + +function ResponsiveStackNavigator(props) { + const {isSmallScreenWidth} = useWindowDimensions(); + + const isSmallScreenWidthRef = useRef(isSmallScreenWidth); + + isSmallScreenWidthRef.current = isSmallScreenWidth; + + const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, { + children: props.children, + screenOptions: props.screenOptions, + initialRouteName: props.initialRouteName, + // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. + getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, + }); + + return ( + + + + ); +} + +ResponsiveStackNavigator.defaultProps = defaultProps; +ResponsiveStackNavigator.propTypes = propTypes; +ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; + +export default createNavigatorFactory(ResponsiveStackNavigator);