Skip to content

Commit 7fffd19

Browse files
authored
Merge pull request #30279 from adamgrzybowski/@swm/limit-report-routes-number
Limit report routes in the customStackNavigator
2 parents becbeb6 + b9c613e commit 7fffd19

File tree

6 files changed

+150
-38
lines changed

6 files changed

+150
-38
lines changed

src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js

-36
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {createStackNavigator} from '@react-navigation/stack';
2+
import React from 'react';
3+
import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper';
4+
import getCurrentUrl from '@libs/Navigation/currentUrl';
5+
import styles from '@styles/styles';
6+
import SCREENS from '@src/SCREENS';
7+
8+
const Stack = createStackNavigator();
9+
10+
const url = getCurrentUrl();
11+
const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined;
12+
13+
function BaseCentralPaneNavigator() {
14+
return (
15+
<Stack.Navigator>
16+
<Stack.Screen
17+
name={SCREENS.REPORT}
18+
// We do it this way to avoid adding the url params to url
19+
initialParams={{openOnAdminRoom: openOnAdminRoom === 'true' || undefined}}
20+
options={{
21+
headerShown: false,
22+
title: 'New Expensify',
23+
24+
// Prevent unnecessary scrolling
25+
cardStyle: styles.cardStyleNavigator,
26+
}}
27+
component={ReportScreenWrapper}
28+
/>
29+
</Stack.Navigator>
30+
);
31+
}
32+
33+
export default BaseCentralPaneNavigator;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import BaseCentralPaneNavigator from './BaseCentralPaneNavigator';
3+
4+
// We don't need to use freeze wraper on web because we don't render all report routes anyway.
5+
// You can see this optimalization in the customStackNavigator.
6+
function CentralPaneNavigator() {
7+
return <BaseCentralPaneNavigator />;
8+
}
9+
10+
export default CentralPaneNavigator;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
import FreezeWrapper from '@libs/Navigation/FreezeWrapper';
3+
import BaseCentralPaneNavigator from './BaseCentralPaneNavigator';
4+
5+
function CentralPaneNavigator() {
6+
return (
7+
<FreezeWrapper>
8+
<BaseCentralPaneNavigator />
9+
</FreezeWrapper>
10+
);
11+
}
12+
13+
export default CentralPaneNavigator;

src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js

+34-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native';
22
import {StackView} from '@react-navigation/stack';
33
import PropTypes from 'prop-types';
4-
import React, {useRef} from 'react';
4+
import React, {useMemo, useRef} from 'react';
55
import useWindowDimensions from '@hooks/useWindowDimensions';
6+
import NAVIGATORS from '@src/NAVIGATORS';
67
import CustomRouter from './CustomRouter';
78

89
const propTypes = {
@@ -25,6 +26,24 @@ const defaultProps = {
2526
screenOptions: undefined,
2627
};
2728

29+
function splitRoutes(routes) {
30+
const reportRoutes = [];
31+
const rhpRoutes = [];
32+
const otherRoutes = [];
33+
34+
routes.forEach((route) => {
35+
if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) {
36+
reportRoutes.push(route);
37+
} else if (route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR) {
38+
rhpRoutes.push(route);
39+
} else {
40+
otherRoutes.push(route);
41+
}
42+
});
43+
44+
return {reportRoutes, rhpRoutes, otherRoutes};
45+
}
46+
2847
function ResponsiveStackNavigator(props) {
2948
const {isSmallScreenWidth} = useWindowDimensions();
3049

@@ -40,12 +59,25 @@ function ResponsiveStackNavigator(props) {
4059
getIsSmallScreenWidth: () => isSmallScreenWidthRef.current,
4160
});
4261

62+
const stateToRender = useMemo(() => {
63+
const {reportRoutes, rhpRoutes, otherRoutes} = splitRoutes(state.routes);
64+
65+
// Remove all report routes except the last 3. This will improve performance.
66+
const limitedReportRoutes = reportRoutes.slice(-3);
67+
68+
return {
69+
...state,
70+
index: otherRoutes.length + limitedReportRoutes.length + rhpRoutes.length - 1,
71+
routes: [...otherRoutes, ...limitedReportRoutes, ...rhpRoutes],
72+
};
73+
}, [state]);
74+
4375
return (
4476
<NavigationContent>
4577
<StackView
4678
// eslint-disable-next-line react/jsx-props-no-spreading
4779
{...props}
48-
state={state}
80+
state={stateToRender}
4981
descriptors={descriptors}
5082
navigation={navigation}
5183
/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native';
2+
import {StackView} from '@react-navigation/stack';
3+
import PropTypes from 'prop-types';
4+
import React, {useRef} from 'react';
5+
import useWindowDimensions from '@hooks/useWindowDimensions';
6+
import CustomRouter from './CustomRouter';
7+
8+
const propTypes = {
9+
/* Determines if the navigator should render the StackView (narrow) or ThreePaneView (wide) */
10+
isSmallScreenWidth: PropTypes.bool.isRequired,
11+
12+
/* Children for the useNavigationBuilder hook */
13+
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
14+
15+
/* initialRouteName for this navigator */
16+
initialRouteName: PropTypes.oneOf([PropTypes.string, PropTypes.undefined]),
17+
18+
/* Screen options defined for this navigator */
19+
// eslint-disable-next-line react/forbid-prop-types
20+
screenOptions: PropTypes.object,
21+
};
22+
23+
const defaultProps = {
24+
initialRouteName: undefined,
25+
screenOptions: undefined,
26+
};
27+
28+
function ResponsiveStackNavigator(props) {
29+
const {isSmallScreenWidth} = useWindowDimensions();
30+
31+
const isSmallScreenWidthRef = useRef(isSmallScreenWidth);
32+
33+
isSmallScreenWidthRef.current = isSmallScreenWidth;
34+
35+
const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, {
36+
children: props.children,
37+
screenOptions: props.screenOptions,
38+
initialRouteName: props.initialRouteName,
39+
// 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.
40+
getIsSmallScreenWidth: () => isSmallScreenWidthRef.current,
41+
});
42+
43+
return (
44+
<NavigationContent>
45+
<StackView
46+
// eslint-disable-next-line react/jsx-props-no-spreading
47+
{...props}
48+
state={state}
49+
descriptors={descriptors}
50+
navigation={navigation}
51+
/>
52+
</NavigationContent>
53+
);
54+
}
55+
56+
ResponsiveStackNavigator.defaultProps = defaultProps;
57+
ResponsiveStackNavigator.propTypes = propTypes;
58+
ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';
59+
60+
export default createNavigatorFactory(ResponsiveStackNavigator);

0 commit comments

Comments
 (0)