Skip to content

Commit

Permalink
split createCustomStackNavigator
Browse files Browse the repository at this point in the history
  • Loading branch information
kosmydel committed Dec 7, 2023
1 parent 25a909b commit 117b717
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 104 deletions.
3 changes: 1 addition & 2 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import SCREENS from '@src/SCREENS';
import * as OnyxTypes from '@src/types/onyx';
import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails';
import createCustomStackNavigator from './createCustomStackNavigator';
import CustomRouter from './createCustomStackNavigator/CustomRouter';
import defaultScreenOptions from './defaultScreenOptions';
import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions';
import CentralPaneNavigator from './Navigators/CentralPaneNavigator';
Expand Down Expand Up @@ -115,7 +114,7 @@ Onyx.connect({
},
});

const RootStack = createCustomStackNavigator<AuthScreensParamList>(CustomRouter);
const RootStack = createCustomStackNavigator<AuthScreensParamList>();
// We want to delay the re-rendering for components(e.g. ReportActionCompose)
// that depends on modal visibility until Modal is completely closed and its focused
// When modal screen is focused, update modal visibility in Onyx
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React from 'react';
import {View} from 'react-native';
import useWindowDimensions from '@hooks/useWindowDimensions';
import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator';
import CustomFullScreenRouter from '@libs/Navigation/AppNavigator/createCustomStackNavigator/CustomFullScreenRouter';

import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRootNavigatorScreenOptions';
import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators';
import useThemeStyles from '@styles/useThemeStyles';
import SCREENS from '@src/SCREENS';
import createCustomFullScreenNavigator from '@libs/Navigation/AppNavigator/createCustomFullScreenNavigator';

const loadPage = () => require('../../../../pages/settings/InitialSettingsPage').default as React.ComponentType;

const RootStack = createCustomStackNavigator(CustomFullScreenRouter);
const RootStack = createCustomFullScreenNavigator();

function FullScreenNavigator() {
const styles = useThemeStyles();
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack';
import React, {useRef} from 'react';
import useWindowDimensions from '@hooks/useWindowDimensions';
import CustomFullScreenRouter from './CustomFullScreenRouter';
import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types';

function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();

const isSmallScreenWidthRef = useRef(isSmallScreenWidth);

isSmallScreenWidthRef.current = isSmallScreenWidth;

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamListBase>,
StackNavigationOptions,
StackNavigationEventMap
>(CustomFullScreenRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={state}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

export default createNavigatorFactory<StackNavigationState<ParamListBase>, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator);
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack';
import React, {useMemo, useRef} from 'react';
import useWindowDimensions from '@hooks/useWindowDimensions';
import SCREENS from '@src/SCREENS';
import CustomFullScreenRouter from './CustomFullScreenRouter';
import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types';

// TODO: Extract to utils with ./createCustomStackNavigator/index.tsx
type Routes = StackNavigationState<ParamListBase>['routes'];
function reduceReportRoutes(routes: Routes): Routes {
const result: Routes = [];
let count = 0;
const reverseRoutes = [...routes].reverse();

reverseRoutes.forEach((route) => {
if (route.name === SCREENS.SETTINGS_CENTRAL_PANE) {
// Remove all report routes except the last 3. This will improve performance.
if (count < 3) {
result.push(route);
count++;
}
} else {
result.push(route);
}
});

return result.reverse();
}

function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();

const isSmallScreenWidthRef = useRef<boolean>(isSmallScreenWidth);

isSmallScreenWidthRef.current = isSmallScreenWidth;

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamListBase>,
StackNavigationOptions,
StackNavigationEventMap
>(CustomFullScreenRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

const stateToRender = useMemo(() => {
const result = reduceReportRoutes(state.routes);

return {
...state,
index: result.length - 1,
routes: [...result],
};
}, [state]);

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={stateToRender}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

export default createNavigatorFactory<StackNavigationState<ParamListBase>, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {DefaultNavigatorOptions, ParamListBase, StackNavigationState, StackRouterOptions} from '@react-navigation/native';
import {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack';

type ResponsiveStackNavigatorConfig = {
isSmallScreenWidth: boolean;
};

type ResponsiveStackNavigatorRouterOptions = StackRouterOptions;

type ResponsiveStackNavigatorProps = DefaultNavigatorOptions<ParamListBase, StackNavigationState<ParamListBase>, StackNavigationOptions, StackNavigationEventMap> &
ResponsiveStackNavigatorConfig;

export type {ResponsiveStackNavigatorRouterOptions, ResponsiveStackNavigatorProps, ResponsiveStackNavigatorConfig};
Original file line number Diff line number Diff line change
@@ -1,50 +1,42 @@
import {createNavigatorFactory, ParamListBase, RouterFactory, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack';
import React, {useRef} from 'react';
import useWindowDimensions from '@hooks/useWindowDimensions';
import CustomRouter from './CustomRouter';
import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type CustomRouterFactory<ParamList extends ParamListBase> = RouterFactory<StackNavigationState<ParamList>, any, ResponsiveStackNavigatorRouterOptions>;

function ResponsiveStackNavigatorFactory<ParamList extends ParamListBase>(customRouter: CustomRouterFactory<ParamList>) {
function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();

const isSmallScreenWidthRef = useRef(isSmallScreenWidth);

isSmallScreenWidthRef.current = isSmallScreenWidth;

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamListBase>,
StackNavigationOptions,
StackNavigationEventMap
>(customRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={state}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';
return ResponsiveStackNavigator;
function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();

const isSmallScreenWidthRef = useRef(isSmallScreenWidth);

isSmallScreenWidthRef.current = isSmallScreenWidth;

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamListBase>,
StackNavigationOptions,
StackNavigationEventMap
>(CustomRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={state}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

export default <ParamList extends ParamListBase>(customRouter: CustomRouterFactory<ParamList>) =>
createNavigatorFactory<StackNavigationState<ParamList>, StackNavigationOptions, StackNavigationEventMap, (props: ResponsiveStackNavigatorProps) => React.JSX.Element>(
ResponsiveStackNavigatorFactory(customRouter),
)();
ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

export default createNavigatorFactory<StackNavigationState<ParamListBase>, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator);
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {CommonNavigationAction, createNavigatorFactory, ParamListBase, RouterFactory, StackActionHelpers, StackActionType, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native';
import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack';
import React, {useMemo, useRef} from 'react';
import useWindowDimensions from '@hooks/useWindowDimensions';
import NAVIGATORS from '@src/NAVIGATORS';
import CustomRouter from './CustomRouter';
import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types';

type Routes = StackNavigationState<ParamListBase>['routes'];
Expand All @@ -26,65 +27,48 @@ function reduceReportRoutes(routes: Routes): Routes {
return result.reverse();
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type CustomRouterFactory<ParamList extends ParamListBase> = RouterFactory<StackNavigationState<ParamList>, CommonNavigationAction | StackActionType, ResponsiveStackNavigatorRouterOptions>;
function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();

function ResponsiveStackNavigatorFactory<ParamList extends ParamListBase>(customRouter: CustomRouterFactory<ParamList>) {
function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();
const isSmallScreenWidthRef = useRef<boolean>(isSmallScreenWidth);

const isSmallScreenWidthRef = useRef<boolean>(isSmallScreenWidth);
isSmallScreenWidthRef.current = isSmallScreenWidth;

isSmallScreenWidthRef.current = isSmallScreenWidth;

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamList>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamList>,
StackNavigationOptions,
StackNavigationEventMap
>(customRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

const stateToRender = useMemo(() => {
const result = reduceReportRoutes(state.routes);

return {
...state,
index: result.length - 1,
routes: [...result],
};
}, [state]);

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={stateToRender}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

return ResponsiveStackNavigator;
}

function createCustomStackNavigator<ParamList extends ParamListBase>(customRouter: CustomRouterFactory<ParamList>) {

const responsiveStackNavigator = ResponsiveStackNavigatorFactory<ParamList>(customRouter);
const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
ResponsiveStackNavigatorRouterOptions,
StackActionHelpers<ParamListBase>,
StackNavigationOptions,
StackNavigationEventMap
>(CustomRouter, {
children: props.children,
screenOptions: props.screenOptions,
initialRouteName: props.initialRouteName,
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const navigatorFactory = createNavigatorFactory<StackNavigationState<ParamList>, StackNavigationOptions, StackNavigationEventMap, any>(responsiveStackNavigator);
return navigatorFactory<ParamList>();
const stateToRender = useMemo(() => {
const result = reduceReportRoutes(state.routes);

return {
...state,
index: result.length - 1,
routes: [...result],
};
}, [state]);

return (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={stateToRender}
descriptors={descriptors}
navigation={navigation}
/>
</NavigationContent>
);
}

ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator';

export default createCustomStackNavigator;
export default createNavigatorFactory<StackNavigationState<ParamListBase>, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator);

0 comments on commit 117b717

Please sign in to comment.