From c7c315e2deab70fab3f7307d903c39fcdacecbe4 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Mon, 2 Dec 2024 14:08:09 +0100 Subject: [PATCH] Adjust split router to native stack --- .../Navigation/AppNavigator/AuthScreens.tsx | 2 +- .../Navigators/ReportsSplitNavigator.tsx | 8 +- .../Navigators/SettingsSplitNavigator.tsx | 21 ++-- .../Navigators/WorkspaceSplitNavigator.tsx | 8 ++ .../CustomRouter.ts | 4 +- .../createResponsiveStackNavigator/index.tsx | 21 ++-- .../createSplitStackNavigator/index.tsx | 105 ++++++------------ .../AppNavigator/useRootNavigatorOptions.ts | 17 ++- .../index.native.tsx | 17 ++- .../index.tsx | 17 ++- 10 files changed, 124 insertions(+), 96 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 2c750ddbcb6b..058355f53388 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -398,7 +398,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie /> diff --git a/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx index c83816a21b5d..f5e90411722d 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx @@ -1,9 +1,11 @@ +import {useRoute} from '@react-navigation/native'; import React, {useRef} from 'react'; import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import usePermissions from '@hooks/usePermissions'; import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator'; import FreezeWrapper from '@libs/Navigation/AppNavigator/FreezeWrapper'; +import useRootNavigatorOptions from '@libs/Navigation/AppNavigator/useRootNavigatorOptions'; import getCurrentUrl from '@libs/Navigation/currentUrl'; import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom'; import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types'; @@ -20,7 +22,8 @@ const Stack = createSplitStackNavigator(); function ReportsSplitNavigator() { const {canUseDefaultRooms} = usePermissions(); const {activeWorkspaceID} = useActiveWorkspace(); - + const rootNavigatorOptions = useRootNavigatorOptions(); + const route = useRoute(); let initialReportID: string | undefined; const isInitialRender = useRef(true); @@ -47,10 +50,13 @@ function ReportsSplitNavigator() { (); function SettingsSplitNavigator() { - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); + const screenOptions = useRootNavigatorOptions(); + const route = useRoute(); + const rootNavigatorOptions = useRootNavigatorOptions(); return ( {Object.entries(CENTRAL_PANE_SETTINGS_SCREENS).map(([screenName, componentGetter]) => { - // const options = {...screenOptions.centralPaneNavigator}; + const options = {...screenOptions.fullScreen}; - // if (screenName === SCREENS.SETTINGS.WORKSPACES) { - // options.animationEnabled = false; - // } + if (screenName === SCREENS.SETTINGS.WORKSPACES) { + options.animation = 'none'; + } return ( ); })} diff --git a/src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx index 9c1b6c8087ca..fd0c91757fa4 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx @@ -1,6 +1,8 @@ +import {useRoute} from '@react-navigation/native'; import React from 'react'; import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator'; +import useRootNavigatorOptions from '@libs/Navigation/AppNavigator/useRootNavigatorOptions'; import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types'; import SCREENS from '@src/SCREENS'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; @@ -30,15 +32,21 @@ const CENTRAL_PANE_WORKSPACE_SCREENS = { const Stack = createSplitStackNavigator(); function WorkspaceNavigator() { + const route = useRoute(); + const rootNavigatorOptions = useRootNavigatorOptions(); + return ( {Object.entries(CENTRAL_PANE_WORKSPACE_SCREENS).map(([screenName, componentGetter]) => ( ('@libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter').default; + +function useCustomRouterState({state}: CustomStateHookProps) { + const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name)); + const routesToRender = state.routes.slice(Math.max(0, lastSplitIndex - 1), state.routes.length); + + return {stateToRender: {...state, routes: routesToRender, index: routesToRender.length - 1}}; +} const ResponsiveStackNavigatorComponent = createPlatformStackNavigatorComponent('ResponsiveStackNavigator', { - createRouter: CustomRouter, + createRouter: loadCustomRouter, defaultScreenOptions: defaultPlatformStackScreenOptions, - useCustomState: useStateWithSearch, useCustomEffects: useNavigationResetOnLayoutChange, - ExtraContent: RenderSearchRoute, + useCustomState: useCustomRouterState, }); function createResponsiveStackNavigator() { diff --git a/src/libs/Navigation/AppNavigator/createSplitStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createSplitStackNavigator/index.tsx index fe48e754893b..7071e85eb6ed 100644 --- a/src/libs/Navigation/AppNavigator/createSplitStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createSplitStackNavigator/index.tsx @@ -1,21 +1,27 @@ -import type {ParamListBase, StackActionHelpers, StackNavigationState} from '@react-navigation/native'; -import {createNavigatorFactory, useNavigationBuilder, useRoute} from '@react-navigation/native'; -import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; -import {StackView} from '@react-navigation/stack'; -import React, {useMemo} from 'react'; -import {View} from 'react-native'; -import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; +import type {ParamListBase} from '@react-navigation/native'; +import {createNavigatorFactory} from '@react-navigation/native'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useThemeStyles from '@hooks/useThemeStyles'; -import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRootNavigatorScreenOptions'; +import useNavigationResetOnLayoutChange from '@libs/Navigation/AppNavigator/useNavigationResetOnLayoutChange'; +import createPlatformStackNavigatorComponent from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent'; +import defaultPlatformStackScreenOptions from '@libs/Navigation/PlatformStackNavigation/defaultPlatformStackScreenOptions'; +import type { + CustomEffectsHookProps, + CustomStateHookProps, + PlatformStackNavigationEventMap, + PlatformStackNavigationOptions, + PlatformStackNavigationState, +} from '@libs/Navigation/PlatformStackNavigation/types'; import SplitStackRouter from './SplitStackRouter'; -import type {SplitStackNavigatorProps, SplitStackNavigatorRouterOptions} from './types'; -import useHandleScreenResize from './useHandleScreenResize'; -import usePrepareSplitStackNavigatorChildren from './usePrepareSplitStackNavigatorChildren'; import usePreserveSplitNavigatorState from './usePreserveSplitNavigatorState'; -function getStateToRender(state: StackNavigationState, isSmallScreenWidth: boolean): StackNavigationState { +function useCustomEffects(props: CustomEffectsHookProps, route) { + useNavigationResetOnLayoutChange(props); + usePreserveSplitNavigatorState(route, props.navigation.getState()); +} + +function useCustomSplitNavigatorState({state}: CustomStateHookProps) { + const {shouldUseNarrowLayout} = useResponsiveLayout(); + const sidebarScreenRoute = state.routes.at(0); if (!sidebarScreenRoute) { @@ -23,67 +29,22 @@ function getStateToRender(state: StackNavigationState, isSmallScr } const centralScreenRoutes = state.routes.slice(1); - const routes = isSmallScreenWidth ? state.routes.slice(-2) : [sidebarScreenRoute, ...centralScreenRoutes.slice(-2)]; + const routesToRender = shouldUseNarrowLayout ? state.routes.slice(-2) : [sidebarScreenRoute, ...centralScreenRoutes.slice(-2)]; - return { - ...state, - routes, - index: routes.length - 1, - }; + return {stateToRender: {...state, routes: routesToRender, index: routesToRender.length - 1}}; } -function SplitStackNavigator(props: SplitStackNavigatorProps) { - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - - - // const children = usePrepareSplitStackNavigatorChildren(props.children, props.sidebarScreen, screenOptions.homeScreen); - - const route = useRoute(); +const CustomFullScreenNavigatorComponent = createPlatformStackNavigatorComponent('CustomFullScreenNavigator', { + createRouter: SplitStackRouter, + useCustomEffects, + defaultScreenOptions: defaultPlatformStackScreenOptions, + useCustomState: useCustomSplitNavigatorState, +}); - const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder< - StackNavigationState, - SplitStackNavigatorRouterOptions, - StackActionHelpers, - StackNavigationOptions, - StackNavigationEventMap - >(SplitStackRouter, { - children: props.children, - // screenOptions: screenOptions.centralPaneNavigator, - initialRouteName: props.initialRouteName, - sidebarScreen: props.sidebarScreen, - defaultCentralScreen: props.defaultCentralScreen, - parentRoute: route, - }); - - // We need to copy the state to the params so that the state is preserved when the root navigator unmount this route for performance reasons. - usePreserveSplitNavigatorState(route, state); - useHandleScreenResize(navigation); - - const stateToRender = useMemo(() => getStateToRender(state, shouldUseNarrowLayout), [state, shouldUseNarrowLayout]); - - return ( - - - - - - - - ); -} - -SplitStackNavigator.displayName = 'SplitStackNavigator'; - -export default function () { - return createNavigatorFactory, StackNavigationOptions, StackNavigationEventMap, React.ComponentType>>( - SplitStackNavigator, +function createCustomFullScreenNavigator() { + return createNavigatorFactory, PlatformStackNavigationOptions, PlatformStackNavigationEventMap, typeof CustomFullScreenNavigatorComponent>( + CustomFullScreenNavigatorComponent, )(); } + +export default createCustomFullScreenNavigator; diff --git a/src/libs/Navigation/AppNavigator/useRootNavigatorOptions.ts b/src/libs/Navigation/AppNavigator/useRootNavigatorOptions.ts index de7971213526..32bd0dd10de6 100644 --- a/src/libs/Navigation/AppNavigator/useRootNavigatorOptions.ts +++ b/src/libs/Navigation/AppNavigator/useRootNavigatorOptions.ts @@ -109,7 +109,22 @@ const useRootNavigatorOptions = () => { fullScreen: { ...commonScreenOptions, // We need to turn off animation for the full screen to avoid delay when closing screens. - animation: shouldUseNarrowLayout ? Animations.SLIDE_FROM_RIGHT : Animations.NONE, + animation: Animations.NONE, + web: { + cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator({props, isFullScreenModal: true}), + cardStyle: { + ...StyleUtils.getNavigationModalCardStyle(), + + // This is necessary to cover whole screen. Including translated sidebar. + // marginLeft: shouldUseNarrowLayout ? 0 : -variables.sideBarWidth, + }, + }, + }, + + searchPage: { + ...commonScreenOptions, + // We need to turn off animation for the full screen to avoid delay when closing screens. + animation: Animations.NONE, web: { cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator({props, isFullScreenModal: true}), cardStyle: { diff --git a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx index 35076c8ca6b6..3794ec2d3834 100644 --- a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx +++ b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx @@ -25,7 +25,17 @@ function createPlatformStackNavigatorComponent) { + function PlatformNavigator({ + id, + initialRouteName, + screenOptions, + screenListeners, + children, + sidebarScreen, + defaultCentralScreen, + parentRoute, + ...props + }: PlatformStackNavigatorProps) { const { navigation, state: originalState, @@ -47,6 +57,9 @@ function createPlatformStackNavigatorComponent, convertToNativeNavigationOptions, ); @@ -73,7 +86,7 @@ function createPlatformStackNavigatorComponent ( diff --git a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx index 2e3c99a6cb0d..8cd35fdab2b7 100644 --- a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx +++ b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx @@ -25,7 +25,17 @@ function createPlatformStackNavigatorComponent undefined); - function PlatformNavigator({id, initialRouteName, screenOptions, screenListeners, children, ...props}: PlatformStackNavigatorProps) { + function PlatformNavigator({ + id, + initialRouteName, + screenOptions, + screenListeners, + children, + sidebarScreen, + defaultCentralScreen, + parentRoute, + ...props + }: PlatformStackNavigatorProps) { const { navigation, state: originalState, @@ -47,6 +57,9 @@ function createPlatformStackNavigatorComponent, convertToWebNavigationOptions, ); @@ -73,7 +86,7 @@ function createPlatformStackNavigatorComponent (