diff --git a/src/NAVIGATORS.ts b/src/NAVIGATORS.ts
index c68a950d3501..a3a041e65684 100644
--- a/src/NAVIGATORS.ts
+++ b/src/NAVIGATORS.ts
@@ -4,7 +4,6 @@
* */
export default {
CENTRAL_PANE_NAVIGATOR: 'CentralPaneNavigator',
- LEFT_MODAL_NAVIGATOR: 'LeftModalNavigator',
RIGHT_MODAL_NAVIGATOR: 'RightModalNavigator',
FULL_SCREEN_NAVIGATOR: 'FullScreenNavigator',
} as const;
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 9e52ea0a38ca..2cd263237866 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -81,12 +81,10 @@ const SCREENS = {
SAVE_THE_WORLD: {
ROOT: 'SaveTheWorld_Root',
},
- LEFT_MODAL: {
- SEARCH: 'Search',
- },
RIGHT_MODAL: {
SETTINGS: 'Settings',
NEW_CHAT: 'NewChat',
+ SEARCH: 'Search',
DETAILS: 'Details',
PROFILE: 'Profile',
REPORT_DETAILS: 'Report_Details',
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
index 369a37e09e60..f6572c84709d 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
@@ -36,7 +36,6 @@ import createCustomStackNavigator from './createCustomStackNavigator';
import defaultScreenOptions from './defaultScreenOptions';
import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions';
import CentralPaneNavigator from './Navigators/CentralPaneNavigator';
-import LeftModalNavigator from './Navigators/LeftModalNavigator';
import RightModalNavigator from './Navigators/RightModalNavigator';
type AuthScreensProps = {
@@ -319,12 +318,6 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom
component={RightModalNavigator}
listeners={modalScreenListeners}
/>
-
;
-
-const Stack = createStackNavigator();
-
-function LeftModalNavigator({navigation}: LeftModalNavigatorProps) {
- const styles = useThemeStyles();
- const {isSmallScreenWidth} = useWindowDimensions();
- const screenOptions = useMemo(() => ModalNavigatorScreenOptions(styles), [styles]);
-
- return (
-
- {!isSmallScreenWidth && (
-
- )}
-
-
-
-
-
-
- );
-}
-
-LeftModalNavigator.displayName = 'LeftModalNavigator';
-
-export default LeftModalNavigator;
diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
index a3fe1c657f34..065de8da578b 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
@@ -9,18 +9,15 @@ import CONST from '@src/CONST';
type OverlayProps = {
/* Callback to close the modal */
onPress: () => void;
-
- /* Returns whether a modal is displayed on the left side of the screen. By default, the modal is displayed on the right */
- isModalOnTheLeft?: boolean;
};
-function Overlay({onPress, isModalOnTheLeft = false}: OverlayProps) {
+function Overlay({onPress}: OverlayProps) {
const styles = useThemeStyles();
const {current} = useCardAnimation();
const {translate} = useLocalize();
return (
-
+
{/* In the latest Electron version buttons can't be both clickable and draggable.
That's why we added this workaround. Because of two Pressable components on the desktop app
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
index d7c31bcae7d9..bd790589c8d1 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import NoDropZone from '@components/DragAndDrop/NoDropZone';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import ModalNavigatorScreenOptions from '@libs/Navigation/AppNavigator/ModalNavigatorScreenOptions';
import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators';
+import RHPScreenOptions from '@libs/Navigation/AppNavigator/RHPScreenOptions';
import type {AuthScreensParamList, RightModalNavigatorParamList} from '@navigation/types';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
@@ -18,7 +18,7 @@ const Stack = createStackNavigator();
function RightModalNavigator({navigation}: RightModalNavigatorProps) {
const styles = useThemeStyles();
const {isSmallScreenWidth} = useWindowDimensions();
- const screenOptions = useMemo(() => ModalNavigatorScreenOptions(styles), [styles]);
+ const screenOptions = useMemo(() => RHPScreenOptions(styles), [styles]);
return (
@@ -33,6 +33,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) {
name={SCREENS.RIGHT_MODAL.NEW_CHAT}
component={ModalStackNavigators.NewChatModalStackNavigator}
/>
+
({
+const RHPScreenOptions = (themeStyles: ThemeStyles): StackNavigationOptions => ({
headerShown: false,
animationEnabled: true,
gestureDirection: 'horizontal',
@@ -14,4 +14,4 @@ const ModalNavigatorScreenOptions = (themeStyles: ThemeStyles): StackNavigationO
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
});
-export default ModalNavigatorScreenOptions;
+export default RHPScreenOptions;
diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
index c80ae9914347..379c5281b78f 100644
--- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
+++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
@@ -15,8 +15,6 @@ const commonScreenOptions: StackNavigationOptions = {
animationTypeForReplace: 'push',
};
-const SLIDE_LEFT_OUTPUT_RANGE_MULTIPLIER = -1;
-
export default (isSmallScreenWidth: boolean, themeStyles: ThemeStyles): ScreenOptions => ({
rightModalNavigator: {
...commonScreenOptions,
@@ -34,23 +32,7 @@ export default (isSmallScreenWidth: boolean, themeStyles: ThemeStyles): ScreenOp
right: 0,
},
},
- leftModalNavigator: {
- ...commonScreenOptions,
- cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props, SLIDE_LEFT_OUTPUT_RANGE_MULTIPLIER),
- presentation: 'transparentModal',
-
- // We want pop in LHP since there are some flows that would work weird otherwise
- animationTypeForReplace: 'pop',
- cardStyle: {
- ...getNavigationModalCardStyle(),
-
- // This is necessary to cover translated sidebar with overlay.
- width: isSmallScreenWidth ? '100%' : '200%',
- // LHP should be displayed in place of the sidebar
- left: isSmallScreenWidth ? 0 : -variables.sideBarWidth,
- },
- },
homeScreen: {
title: CONFIG.SITE_TITLE,
...commonScreenOptions,
diff --git a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
index fd59b02e724d..eff88422cc5c 100644
--- a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
+++ b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
@@ -3,16 +3,11 @@ import {Animated} from 'react-native';
import getCardStyles from '@styles/utils/cardStyles';
import variables from '@styles/variables';
-export default (
- isSmallScreenWidth: boolean,
- isFullScreenModal: boolean,
- {current: {progress}, inverted, layouts: {screen}}: StackCardInterpolationProps,
- outputRangeMultiplier = 1,
-): StackCardInterpolatedStyle => {
+export default (isSmallScreenWidth: boolean, isFullScreenModal: boolean, {current: {progress}, inverted, layouts: {screen}}: StackCardInterpolationProps): StackCardInterpolatedStyle => {
const translateX = Animated.multiply(
progress.interpolate({
inputRange: [0, 1],
- outputRange: [outputRangeMultiplier * (isSmallScreenWidth ? screen.width : variables.sideBarWidth), 0],
+ outputRange: [isSmallScreenWidth ? screen.width : variables.sideBarWidth, 0],
extrapolate: 'clamp',
}),
inverted,
diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts
index a3e89a983f98..3552ff9e7410 100644
--- a/src/libs/Navigation/Navigation.ts
+++ b/src/libs/Navigation/Navigation.ts
@@ -1,17 +1,18 @@
-import {findFocusedRoute} from '@react-navigation/core';
+import {findFocusedRoute, getActionFromState} from '@react-navigation/core';
import {CommonActions, EventArg, getPathFromState, NavigationContainerEventMap, NavigationState, PartialState, StackActions} from '@react-navigation/native';
+import findLastIndex from 'lodash/findLastIndex';
import Log from '@libs/Log';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ROUTES, {Route} from '@src/ROUTES';
-import {PROTECTED_SCREENS} from '@src/SCREENS';
-import originalDismissModal from './dismissModal';
+import SCREENS, {PROTECTED_SCREENS} from '@src/SCREENS';
+import getStateFromPath from './getStateFromPath';
import originalGetTopmostReportActionId from './getTopmostReportActionID';
import originalGetTopmostReportId from './getTopmostReportId';
import linkingConfig from './linkingConfig';
import linkTo from './linkTo';
import navigationRef from './navigationRef';
-import {StateOrRoute} from './types';
+import {StackNavigationAction, StateOrRoute} from './types';
let resolveNavigationIsReadyPromise: () => void;
const navigationIsReadyPromise = new Promise((resolve) => {
@@ -43,9 +44,6 @@ const getTopmostReportId = (state = navigationRef.getState()) => originalGetTopm
// Re-exporting the getTopmostReportActionID here to fill in default value for state. The getTopmostReportActionID isn't defined in this file to avoid cyclic dependencies.
const getTopmostReportActionId = (state = navigationRef.getState()) => originalGetTopmostReportActionId(state);
-// Re-exporting the dismissModal here to fill in default value for navigationRef. The dismissModal isn't defined in this file to avoid cyclic dependencies.
-const dismissModal = (targetReportId = '', ref = navigationRef) => originalDismissModal(targetReportId, ref);
-
/** Method for finding on which index in stack we are. */
function getActiveRouteIndex(stateOrRoute: StateOrRoute, index?: number): number | undefined {
if ('routes' in stateOrRoute && stateOrRoute.routes) {
@@ -58,7 +56,7 @@ function getActiveRouteIndex(stateOrRoute: StateOrRoute, index?: number): number
return getActiveRouteIndex(childActiveRoute, stateOrRoute.state.index ?? 0);
}
- if ('name' in stateOrRoute && (stateOrRoute.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR || stateOrRoute.name === NAVIGATORS.LEFT_MODAL_NAVIGATOR)) {
+ if ('name' in stateOrRoute && stateOrRoute.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR) {
return 0;
}
@@ -162,8 +160,8 @@ function goBack(fallbackRoute: Route, shouldEnforceFallback = false, shouldPopTo
if (isFirstRouteInNavigator) {
const rootState = navigationRef.getRootState();
const lastRoute = rootState.routes.at(-1);
- // If the user comes from a different flow (there is more than one route in ModalNavigator) we should go back to the previous flow on UP button press instead of using the fallbackRoute.
- if ((lastRoute?.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR || lastRoute?.name === NAVIGATORS.LEFT_MODAL_NAVIGATOR) && (lastRoute.state?.index ?? 0) > 0) {
+ // If the user comes from a different flow (there is more than one route in RHP) we should go back to the previous flow on UP button press instead of using the fallbackRoute.
+ if (lastRoute?.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR && (lastRoute.state?.index ?? 0) > 0) {
navigationRef.current.goBack();
return;
}
@@ -202,6 +200,45 @@ function setParams(params: Record, routeKey: string) {
});
}
+/**
+ * Dismisses the last modal stack if there is any
+ *
+ * @param targetReportID - The reportID to navigate to after dismissing the modal
+ */
+function dismissModal(targetReportID?: string) {
+ if (!canNavigate('dismissModal')) {
+ return;
+ }
+ const rootState = navigationRef.getRootState();
+ const lastRoute = rootState.routes.at(-1);
+ switch (lastRoute?.name) {
+ case NAVIGATORS.RIGHT_MODAL_NAVIGATOR:
+ case SCREENS.NOT_FOUND:
+ case SCREENS.REPORT_ATTACHMENTS:
+ // if we are not in the target report, we need to navigate to it after dismissing the modal
+ if (targetReportID && targetReportID !== getTopmostReportId(rootState)) {
+ const state = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReportID));
+
+ const action: StackNavigationAction = getActionFromState(state, linkingConfig.config);
+ if (action) {
+ action.type = 'REPLACE';
+ navigationRef.current?.dispatch(action);
+ }
+ // If not-found page is in the route stack, we need to close it
+ } else if (targetReportID && rootState.routes.some((route) => route.name === SCREENS.NOT_FOUND)) {
+ const lastRouteIndex = rootState.routes.length - 1;
+ const centralRouteIndex = findLastIndex(rootState.routes, (route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR);
+ navigationRef.current?.dispatch({...StackActions.pop(lastRouteIndex - centralRouteIndex), target: rootState.key});
+ } else {
+ navigationRef.current?.dispatch({...StackActions.pop(), target: rootState.key});
+ }
+ break;
+ default: {
+ Log.hmmm('[Navigation] dismissModal failed because there is no modal stack to dismiss');
+ }
+ }
+}
+
/**
* Returns the current active route without the URL params
*/
diff --git a/src/libs/Navigation/dismissModal.ts b/src/libs/Navigation/dismissModal.ts
deleted file mode 100644
index 37b4c6d9b9e6..000000000000
--- a/src/libs/Navigation/dismissModal.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import {getActionFromState} from '@react-navigation/core';
-import {NavigationContainerRef, StackActions} from '@react-navigation/native';
-import {findLastIndex} from 'lodash';
-import Log from '@libs/Log';
-import NAVIGATORS from '@src/NAVIGATORS';
-import ROUTES from '@src/ROUTES';
-import SCREENS from '@src/SCREENS';
-import getStateFromPath from './getStateFromPath';
-import getTopmostReportId from './getTopmostReportId';
-import linkingConfig from './linkingConfig';
-import {RootStackParamList, StackNavigationAction} from './types';
-
-// This function is in a separate file than Navigation.js to avoid cyclic dependency.
-
-/**
- * Dismisses the last modal stack if there is any
- *
- * @param targetReportID - The reportID to navigate to after dismissing the modal
- */
-function dismissModal(targetReportID: string, navigationRef: NavigationContainerRef) {
- if (!navigationRef.isReady()) {
- return;
- }
-
- const state = navigationRef.getState();
- const lastRoute = state.routes.at(-1);
- switch (lastRoute?.name) {
- case NAVIGATORS.LEFT_MODAL_NAVIGATOR:
- case NAVIGATORS.RIGHT_MODAL_NAVIGATOR:
- case SCREENS.NOT_FOUND:
- case SCREENS.REPORT_ATTACHMENTS:
- // if we are not in the target report, we need to navigate to it after dismissing the modal
- if (targetReportID && targetReportID !== getTopmostReportId(state)) {
- const reportState = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReportID));
-
- const action: StackNavigationAction = getActionFromState(reportState, linkingConfig.config);
- if (action) {
- action.type = 'REPLACE';
- navigationRef.dispatch(action);
- }
- // If not-found page is in the route stack, we need to close it
- } else if (targetReportID && state.routes.some((route) => route.name === SCREENS.NOT_FOUND)) {
- const lastRouteIndex = state.routes.length - 1;
- const centralRouteIndex = findLastIndex(state.routes, (route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR);
- navigationRef.dispatch({...StackActions.pop(lastRouteIndex - centralRouteIndex), target: state.key});
- } else {
- navigationRef.dispatch({...StackActions.pop(), target: state.key});
- }
- break;
- default: {
- Log.hmmm('[Navigation] dismissModal failed because there is no modal stack to dismiss');
- }
- }
-}
-
-export default dismissModal;
diff --git a/src/libs/Navigation/linkTo.ts b/src/libs/Navigation/linkTo.ts
index 86558765a6e6..9694879f9aae 100644
--- a/src/libs/Navigation/linkTo.ts
+++ b/src/libs/Navigation/linkTo.ts
@@ -4,7 +4,6 @@ import {Writable} from 'type-fest';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import {Route} from '@src/ROUTES';
-import dismissModal from './dismissModal';
import getStateFromPath from './getStateFromPath';
import getTopmostReportId from './getTopmostReportId';
import linkingConfig from './linkingConfig';
@@ -56,10 +55,6 @@ function getMinimalAction(action: NavigationAction, state: NavigationState): Wri
return currentAction;
}
-function isModalNavigator(targetNavigator?: string) {
- return targetNavigator === NAVIGATORS.LEFT_MODAL_NAVIGATOR || targetNavigator === NAVIGATORS.RIGHT_MODAL_NAVIGATOR;
-}
-
export default function linkTo(navigation: NavigationContainerRef | null, path: Route, type?: string, isActiveRoute?: boolean) {
if (!navigation) {
throw new Error("Couldn't find a navigation object. Is your component inside a screen in a navigator?");
@@ -80,9 +75,6 @@ export default function linkTo(navigation: NavigationContainerRef = {
},
},
[SCREENS.NOT_FOUND]: '*',
- [NAVIGATORS.LEFT_MODAL_NAVIGATOR]: {
- screens: {
- [SCREENS.LEFT_MODAL.SEARCH]: {
- screens: {
- [SCREENS.SEARCH_ROOT]: ROUTES.SEARCH,
- },
- },
- },
- },
+
[NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: {
screens: {
[SCREENS.RIGHT_MODAL.SETTINGS]: {
@@ -349,6 +341,11 @@ const linkingConfig: LinkingOptions = {
[SCREENS.I_AM_A_TEACHER]: ROUTES.I_AM_A_TEACHER,
},
},
+ [SCREENS.RIGHT_MODAL.SEARCH]: {
+ screens: {
+ [SCREENS.SEARCH_ROOT]: ROUTES.SEARCH,
+ },
+ },
[SCREENS.RIGHT_MODAL.DETAILS]: {
screens: {
[SCREENS.DETAILS_ROOT]: ROUTES.DETAILS.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 95d5c0f7ff15..7f13640f0e9b 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -334,13 +334,10 @@ type PrivateNotesNavigatorParamList = {
};
};
-type LeftModalNavigatorParamList = {
- [SCREENS.LEFT_MODAL.SEARCH]: NavigatorScreenParams;
-};
-
type RightModalNavigatorParamList = {
[SCREENS.RIGHT_MODAL.SETTINGS]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.NEW_CHAT]: NavigatorScreenParams;
+ [SCREENS.RIGHT_MODAL.SEARCH]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.DETAILS]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.PROFILE]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.REPORT_DETAILS]: NavigatorScreenParams;
@@ -410,7 +407,6 @@ type AuthScreensParamList = {
name: string;
};
[SCREENS.NOT_FOUND]: undefined;
- [NAVIGATORS.LEFT_MODAL_NAVIGATOR]: NavigatorScreenParams;
[NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams;
[SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined;
[CONST.DEMO_PAGES.MONEY2020]: undefined;
@@ -427,7 +423,6 @@ export type {
NavigationStateRoute,
NavigationRoot,
AuthScreensParamList,
- LeftModalNavigatorParamList,
RightModalNavigatorParamList,
PublicScreensParamList,
MoneyRequestNavigatorParamList,
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 905c25f4f7d8..67be7cce1642 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -1415,12 +1415,6 @@ const styles = (theme: ThemeColors) =>
height: variables.lineHeightSizeh1,
},
- LHPNavigatorContainer: (isSmallScreenWidth: boolean) =>
- ({
- ...modalNavigatorContainer(isSmallScreenWidth),
- left: 0,
- } satisfies ViewStyle),
-
RHPNavigatorContainer: (isSmallScreenWidth: boolean) =>
({
...modalNavigatorContainer(isSmallScreenWidth),
@@ -1640,15 +1634,14 @@ const styles = (theme: ThemeColors) =>
marginBottom: 4,
},
- overlayStyles: (current: OverlayStylesParams, isModalOnTheLeft: boolean) =>
+ overlayStyles: (current: OverlayStylesParams) =>
({
...positioning.pFixed,
// We need to stretch the overlay to cover the sidebar and the translate animation distance.
- // The overlay must also cover borderRadius of the LHP component
- left: isModalOnTheLeft ? 0 : -2 * variables.sideBarWidth,
+ left: -2 * variables.sideBarWidth,
top: 0,
bottom: 0,
- right: isModalOnTheLeft ? -2 * variables.sideBarWidth : 0,
+ right: 0,
backgroundColor: theme.overlay,
opacity: current.progress.interpolate({
inputRange: [0, 1],