Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit report routes in the customStackNavigator #30279

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 (
<Stack.Navigator>
<Stack.Screen
name={SCREENS.REPORT}
// We do it this way to avoid adding the url params to url
initialParams={{openOnAdminRoom: openOnAdminRoom === 'true' || undefined}}
options={{
headerShown: false,
title: 'New Expensify',

// Prevent unnecessary scrolling
cardStyle: styles.cardStyleNavigator,
}}
component={ReportScreenWrapper}
/>
</Stack.Navigator>
);
}

export default BaseCentralPaneNavigator;
Original file line number Diff line number Diff line change
@@ -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 <BaseCentralPaneNavigator />;
}

export default CentralPaneNavigator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import FreezeWrapper from '@libs/Navigation/FreezeWrapper';
import BaseCentralPaneNavigator from './BaseCentralPaneNavigator';

function CentralPaneNavigator() {
return (
<FreezeWrapper>
<BaseCentralPaneNavigator />
</FreezeWrapper>
);
}

export default CentralPaneNavigator;
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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();

Expand All @@ -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 (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={state}
state={stateToRender}
descriptors={descriptors}
navigation={navigation}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={state}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.defaultProps = defaultProps;
ResponsiveStackNavigator.propTypes = propTypes;
ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

export default createNavigatorFactory(ResponsiveStackNavigator);
Loading