Skip to content

Commit

Permalink
platform stack navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
chrispader committed Sep 30, 2024
1 parent 300922a commit 6a60a74
Show file tree
Hide file tree
Showing 254 changed files with 793 additions and 1,105 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type {RouteProp} from '@react-navigation/native';
import {useRoute} from '@react-navigation/native';
import lodashSortBy from 'lodash/sortBy';
import truncate from 'lodash/truncate';
Expand Down Expand Up @@ -29,6 +28,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
Expand Down Expand Up @@ -70,7 +70,7 @@ function MoneyRequestPreviewContent({
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {windowWidth} = useWindowDimensions();
const route = useRoute<RouteProp<TransactionDuplicateNavigatorParamList, typeof SCREENS.TRANSACTION_DUPLICATE.REVIEW>>();
const route = useRoute<PlatformStackRouteProp<TransactionDuplicateNavigatorParamList, typeof SCREENS.TRANSACTION_DUPLICATE.REVIEW>>();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || '-1'}`);
Expand Down
6 changes: 3 additions & 3 deletions src/components/ScreenWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {useIsFocused, useNavigation} from '@react-navigation/native';
import type {StackNavigationProp} from '@react-navigation/stack';
import type {ForwardedRef, ReactNode} from 'react';
import React, {createContext, forwardRef, useEffect, useMemo, useRef, useState} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
Expand All @@ -15,6 +14,7 @@ import useTackInputFocus from '@hooks/useTackInputFocus';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {AuthScreensParamList, RootStackParamList} from '@libs/Navigation/types';
import toggleTestToolsModal from '@userActions/TestTool';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -96,7 +96,7 @@ type ScreenWrapperProps = {
*
* This is required because transitionEnd event doesn't trigger in the testing environment.
*/
navigation?: StackNavigationProp<RootStackParamList> | StackNavigationProp<AuthScreensParamList>;
navigation?: PlatformStackNavigationProp<RootStackParamList> | PlatformStackNavigationProp<AuthScreensParamList>;

/** Whether to show offline indicator on wide screens */
shouldShowOfflineIndicatorInWideScreen?: boolean;
Expand Down Expand Up @@ -141,7 +141,7 @@ function ScreenWrapper(
* so in other places where ScreenWrapper is used, we need to
* fallback to useNavigation.
*/
const navigationFallback = useNavigation<StackNavigationProp<RootStackParamList>>();
const navigationFallback = useNavigation<PlatformStackNavigationProp<RootStackParamList>>();
const navigation = navigationProp ?? navigationFallback;
const isFocused = useIsFocused();
const {windowHeight} = useWindowDimensions(shouldUseCachedViewportHeight);
Expand Down
9 changes: 5 additions & 4 deletions src/components/ScrollOffsetContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type {ParamListBase, RouteProp} from '@react-navigation/native';
import type {ParamListBase} from '@react-navigation/native';
import React, {createContext, useCallback, useEffect, useMemo, useRef} from 'react';
import {withOnyx} from 'react-native-onyx';
import usePrevious from '@hooks/usePrevious';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {NavigationPartialRoute, State} from '@libs/Navigation/types';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
Expand All @@ -10,10 +11,10 @@ import type {PriorityMode} from '@src/types/onyx';

type ScrollOffsetContextValue = {
/** Save scroll offset of flashlist on given screen */
saveScrollOffset: (route: RouteProp<ParamListBase>, scrollOffset: number) => void;
saveScrollOffset: (route: PlatformStackRouteProp<ParamListBase>, scrollOffset: number) => void;

/** Get scroll offset value for given screen */
getScrollOffset: (route: RouteProp<ParamListBase>) => number | undefined;
getScrollOffset: (route: PlatformStackRouteProp<ParamListBase>) => number | undefined;

/** Clean scroll offsets of screen that aren't anymore in the state */
cleanStaleScrollOffsets: (state: State) => void;
Expand All @@ -38,7 +39,7 @@ const defaultValue: ScrollOffsetContextValue = {
const ScrollOffsetContext = createContext<ScrollOffsetContextValue>(defaultValue);

/** This function is prepared to work with HOME screens. May need modification if we want to handle other types of screens. */
function getKey(route: RouteProp<ParamListBase> | NavigationPartialRoute): string {
function getKey(route: PlatformStackRouteProp<ParamListBase> | NavigationPartialRoute): string {
if (route.params && 'policyID' in route.params && typeof route.params.policyID === 'string') {
return `${route.name}-${route.params.policyID}`;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {useNavigation} from '@react-navigation/native';
import type {StackNavigationProp} from '@react-navigation/stack';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {View} from 'react-native';
import type {NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewStyle} from 'react-native';
Expand All @@ -20,6 +19,7 @@ import * as SearchActions from '@libs/actions/Search';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import memoize from '@libs/memoize';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import * as SearchUtils from '@libs/SearchUtils';
import Navigation from '@navigation/Navigation';
Expand Down Expand Up @@ -81,7 +81,7 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
const {shouldUseNarrowLayout} = useResponsiveLayout();
const styles = useThemeStyles();
const {isSmallScreenWidth, isLargeScreenWidth} = useResponsiveLayout();
const navigation = useNavigation<StackNavigationProp<AuthScreensParamList>>();
const navigation = useNavigation<PlatformStackNavigationProp<AuthScreensParamList>>();
const lastSearchResultsRef = useRef<OnyxEntry<SearchResults>>();
const {setCurrentSearchHash, setSelectedTransactions, selectedTransactions, clearSelectedTransactions, setShouldShowStatusBarLoading} = useSearchContext();
const {selectionMode} = useMobileSelectionMode();
Expand Down
4 changes: 2 additions & 2 deletions src/components/withNavigationTransitionEnd.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {useNavigation} from '@react-navigation/native';
import type {StackNavigationProp} from '@react-navigation/stack';
import type {ComponentType, ForwardedRef, RefAttributes} from 'react';
import React, {useEffect, useState} from 'react';
import getComponentDisplayName from '@libs/getComponentDisplayName';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {RootStackParamList} from '@libs/Navigation/types';

type WithNavigationTransitionEndProps = {didScreenTransitionEnd: boolean};

export default function <TProps, TRef>(WrappedComponent: ComponentType<TProps & RefAttributes<TRef>>): React.ComponentType<TProps & RefAttributes<TRef>> {
function WithNavigationTransitionEnd(props: TProps, ref: ForwardedRef<TRef>) {
const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false);
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
const navigation = useNavigation<PlatformStackNavigationProp<RootStackParamList>>();

useEffect(() => {
const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', () => {
Expand Down
12 changes: 5 additions & 7 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
import beforeRemoveReportOpenedFromSearchRHP from './beforeRemoveReportOpenedFromSearchRHP';
import CENTRAL_PANE_SCREENS from './CENTRAL_PANE_SCREENS';
import createCustomStackNavigator from './createCustomStackNavigator';
import createResponsiveStackNavigator from './createResponsiveStackNavigator';
import defaultScreenOptions from './defaultScreenOptions';
import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions';
import BottomTabNavigator from './Navigators/BottomTabNavigator';
Expand Down Expand Up @@ -196,7 +196,7 @@ function handleNetworkReconnect() {
}
}

const RootStack = createCustomStackNavigator<AuthScreensParamList>();
const RootStack = createResponsiveStackNavigator<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 Expand Up @@ -227,7 +227,7 @@ const modalScreenListenersWithCancelSearch = {
function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDAppliedToClient}: AuthScreensProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout();
const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout();
const screenOptions = getRootNavigatorScreenOptions(shouldUseNarrowLayout, styles, StyleUtils);
const {canUseDefaultRooms} = usePermissions();
const {activeWorkspaceID} = useActiveWorkspace();
Expand Down Expand Up @@ -410,10 +410,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
return (
<ComposeProviders components={[OptionsListContextProvider, SearchContextProvider]}>
<View style={styles.rootNavigatorContainerStyles(shouldUseNarrowLayout)}>
<RootStack.Navigator
screenOptions={screenOptions.centralPaneNavigator}
isSmallScreenWidth={isSmallScreenWidth}
>
<RootStack.Navigator screenOptions={screenOptions.centralPaneNavigator}>
<RootStack.Screen
name={NAVIGATORS.BOTTOM_TAB_NAVIGATOR}
options={screenOptions.bottomTab}
Expand Down Expand Up @@ -462,6 +459,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
options={{
headerShown: false,
presentation: 'transparentModal',
animation: 'none',
}}
getComponent={loadProfileAvatar}
listeners={modalScreenListeners}
Expand Down
29 changes: 21 additions & 8 deletions src/libs/Navigation/AppNavigator/ModalNavigatorScreenOptions.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import type {StackNavigationOptions} from '@react-navigation/stack';
import {CardStyleInterpolators} from '@react-navigation/stack';
import type {GestureDirection} from '@react-navigation/stack/lib/typescript/src/types';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ThemeStyles} from '@styles/index';

/**
* Modal stack navigator screen options generator function
* @param themeStyles - The styles object
* @returns The screen options object
*/
const ModalNavigatorScreenOptions = (themeStyles: ThemeStyles, gestureDirection: GestureDirection = 'horizontal'): StackNavigationOptions => ({
headerShown: false,
animationEnabled: true,
gestureDirection,
cardStyle: themeStyles.navigationScreenCardStyle,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
});
const ModalNavigatorScreenOptions = (themeStyles: ThemeStyles, gestureDirection: GestureDirection = 'horizontal'): PlatformStackNavigationOptions => {
let universalGestureDirection: PlatformStackNavigationOptions['gestureDirection'] | undefined;
let webGestureDirection: GestureDirection | undefined;
if (gestureDirection === 'horizontal' || gestureDirection === 'vertical') {
universalGestureDirection = gestureDirection;
} else {
webGestureDirection = gestureDirection;
}

return {
headerShown: false,
animation: 'slide_from_right',
gestureDirection: universalGestureDirection,
web: {
cardStyle: themeStyles.navigationScreenCardStyle,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
gestureDirection: webGestureDirection,
},
};
};

export default ModalNavigatorScreenOptions;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type {ParamListBase} from '@react-navigation/routers';
import type {StackNavigationOptions} from '@react-navigation/stack';
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
import type {
AddPersonalBankAccountNavigatorParamList,
DebugParamList,
Expand Down Expand Up @@ -33,10 +32,10 @@ import type {
TravelNavigatorParamList,
WalletStatementNavigatorParamList,
} from '@navigation/types';
import type {ThemeStyles} from '@styles/index';
import type {Screen} from '@src/SCREENS';
import SCREENS from '@src/SCREENS';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
import type {GetModalStackScreenOptions} from './useModalScreenOptions';
import useModalScreenOptions from './useModalScreenOptions';

type Screens = Partial<Record<Screen, () => React.ComponentType>>;
Expand All @@ -47,8 +46,8 @@ type Screens = Partial<Record<Screen, () => React.ComponentType>>;
* @param screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component
* @param getScreenOptions optional function that returns the screen options, override the default options
*/
function createModalStackNavigator<TStackParams extends ParamListBase>(screens: Screens, getScreenOptions?: (styles: ThemeStyles) => StackNavigationOptions): React.ComponentType {
const ModalStackNavigator = createStackNavigator<TStackParams>();
function createModalStackNavigator<ParamList extends ParamListBase>(screens: Screens, getScreenOptions?: GetModalStackScreenOptions): React.ComponentType {
const ModalStackNavigator = createPlatformStackNavigator<ParamList>();

function ModalStack() {
const screenOptions = useModalScreenOptions(getScreenOptions);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import type {StackCardInterpolationProps, StackNavigationOptions} from '@react-navigation/stack';
import type {StackCardInterpolationProps} from '@react-navigation/stack';
import {CardStyleInterpolators} from '@react-navigation/stack';
import {useMemo} from 'react';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import {isSafari} from '@libs/Browser';
import hideKeyboardOnSwipe from '@libs/Navigation/AppNavigator/hideKeyboardOnSwipe';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
import createModalCardStyleInterpolator from '@navigation/AppNavigator/createModalCardStyleInterpolator';
import type {ThemeStyles} from '@src/styles';

function useModalScreenOptions(getScreenOptions?: (styles: ThemeStyles) => StackNavigationOptions) {
type GetModalStackScreenOptions = (styles: ThemeStyles) => PlatformStackNavigationOptions;

function useModalScreenOptions(getScreenOptions?: GetModalStackScreenOptions) {
const styles = useThemeStyles();
const styleUtils = useStyleUtils();
const {shouldUseNarrowLayout} = useResponsiveLayout();
Expand All @@ -21,15 +25,19 @@ function useModalScreenOptions(getScreenOptions?: (styles: ThemeStyles) => Stack
}

const defaultSubRouteOptions = useMemo(
(): StackNavigationOptions => ({
cardStyle: styles.navigationScreenCardStyle,
(): PlatformStackNavigationOptions => ({
...hideKeyboardOnSwipe,
headerShown: false,
cardStyleInterpolator,
web: {
cardStyle: styles.navigationScreenCardStyle,
cardStyleInterpolator,
},
}),
[styles, cardStyleInterpolator],
[cardStyleInterpolator, styles.navigationScreenCardStyle],
);

return getScreenOptions?.(styles) ?? defaultSubRouteOptions;
}

export default useModalScreenOptions;
export type {GetModalStackScreenOptions};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {useNavigationState} from '@react-navigation/native';
import type {StackNavigationOptions} from '@react-navigation/stack';
import React from 'react';
import createCustomBottomTabNavigator from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator';
import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
import type {BottomTabNavigatorParamList, CentralPaneName, NavigationPartialRoute, RootStackParamList} from '@libs/Navigation/types';
import SidebarScreen from '@pages/home/sidebar/SidebarScreen';
import SearchPageBottomTab from '@pages/Search/SearchPageBottomTab';
Expand All @@ -13,9 +13,8 @@ import ActiveCentralPaneRouteContext from './ActiveCentralPaneRouteContext';
const loadInitialSettingsPage = () => require<ReactComponentModule>('../../../../pages/settings/InitialSettingsPage').default;
const Tab = createCustomBottomTabNavigator<BottomTabNavigatorParamList>();

const screenOptions: StackNavigationOptions = {
const screenOptions: PlatformStackNavigationOptions = {
headerShown: false,
animationEnabled: false,
};

function BottomTabNavigator() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
import {View} from 'react-native';
import NoDropZone from '@components/DragAndDrop/NoDropZone';
import ExplanationModal from '@components/ExplanationModal';
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
import type {ExplanationModalNavigatorParamList} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';

const Stack = createStackNavigator<ExplanationModalNavigatorParamList>();
const Stack = createPlatformStackNavigator<ExplanationModalNavigatorParamList>();

function ExplanationModalNavigator() {
return (
<NoDropZone>
<View>
<Stack.Navigator screenOptions={{headerShown: false, animationEnabled: true}}>
<Stack.Navigator screenOptions={{headerShown: false, animation: 'slide_from_right'}}>
<Stack.Screen
name={SCREENS.EXPLANATION_MODAL.ROOT}
component={ExplanationModal}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
import {View} from 'react-native';
import NoDropZone from '@components/DragAndDrop/NoDropZone';
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
import type {FeatureTrainingNavigatorParamList} from '@libs/Navigation/types';
import TrackTrainingPage from '@pages/TrackTrainingPage';
import SCREENS from '@src/SCREENS';

const Stack = createStackNavigator<FeatureTrainingNavigatorParamList>();
const Stack = createPlatformStackNavigator<FeatureTrainingNavigatorParamList>();

function FeatureTrainingModalNavigator() {
return (
<NoDropZone>
<View>
<Stack.Navigator screenOptions={{headerShown: false, animationEnabled: true}}>
<Stack.Navigator screenOptions={{headerShown: false, animation: 'slide_from_right'}}>
<Stack.Screen
name={SCREENS.FEATURE_TRAINING_ROOT}
component={TrackTrainingPage}
Expand Down
Loading

0 comments on commit 6a60a74

Please sign in to comment.