-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ideal nav LHP #32473
Ideal nav LHP #32473
Changes from 26 commits
379ac08
3af4938
b2130bb
bdb17ef
e0cc1c7
a0806cb
33108e3
456eff6
ca645b6
6a315f6
f32a907
e180b99
9677a22
152c136
0c7d7b8
4b875bb
7694af7
062f969
4ccba51
6f5fab2
7753b91
3bbad0e
c959ad8
fb9e622
4d45639
02953bf
b54996f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import {createStackNavigator, StackScreenProps} from '@react-navigation/stack'; | ||
import React, {useMemo} from 'react'; | ||
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 {AuthScreensParamList, LeftModalNavigatorParamList} from '@libs/Navigation/types'; | ||
import NAVIGATORS from '@src/NAVIGATORS'; | ||
import SCREENS from '@src/SCREENS'; | ||
import Overlay from './Overlay'; | ||
|
||
type LeftModalNavigatorProps = StackScreenProps<AuthScreensParamList, typeof NAVIGATORS.LEFT_MODAL_NAVIGATOR>; | ||
|
||
const Stack = createStackNavigator<LeftModalNavigatorParamList>(); | ||
|
||
function LeftModalNavigator({navigation}: LeftModalNavigatorProps) { | ||
const styles = useThemeStyles(); | ||
const {isSmallScreenWidth} = useWindowDimensions(); | ||
const screenOptions = useMemo(() => ModalNavigatorScreenOptions(styles), [styles]); | ||
|
||
return ( | ||
<NoDropZone> | ||
{!isSmallScreenWidth && ( | ||
<Overlay | ||
isModalOnTheLeft | ||
onPress={navigation.goBack} | ||
/> | ||
)} | ||
<View style={styles.LHPNavigatorContainer(isSmallScreenWidth)}> | ||
<Stack.Navigator screenOptions={screenOptions}> | ||
<Stack.Screen | ||
name={SCREENS.LEFT_MODAL.SEARCH} | ||
component={ModalStackNavigators.SearchModalStackNavigator} | ||
/> | ||
</Stack.Navigator> | ||
</View> | ||
</NoDropZone> | ||
); | ||
} | ||
|
||
LeftModalNavigator.displayName = 'LeftModalNavigator'; | ||
|
||
export default LeftModalNavigator; |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,17 @@ | ||
import {findFocusedRoute, getActionFromState} from '@react-navigation/core'; | ||
import {findFocusedRoute} 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 SCREENS, {PROTECTED_SCREENS} from '@src/SCREENS'; | ||
import getStateFromPath from './getStateFromPath'; | ||
import {PROTECTED_SCREENS} from '@src/SCREENS'; | ||
import originalDismissModal from './dismissModal'; | ||
import originalGetTopmostReportActionId from './getTopmostReportActionID'; | ||
import originalGetTopmostReportId from './getTopmostReportId'; | ||
import linkingConfig from './linkingConfig'; | ||
import linkTo from './linkTo'; | ||
import navigationRef from './navigationRef'; | ||
import {StackNavigationAction, StateOrRoute} from './types'; | ||
import {StateOrRoute} from './types'; | ||
|
||
let resolveNavigationIsReadyPromise: () => void; | ||
const navigationIsReadyPromise = new Promise<void>((resolve) => { | ||
|
@@ -44,6 +43,9 @@ 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) { | ||
|
@@ -56,7 +58,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) { | ||
if ('name' in stateOrRoute && (stateOrRoute.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR || stateOrRoute.name === NAVIGATORS.LEFT_MODAL_NAVIGATOR)) { | ||
return 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@s77rt I've modified this condition to check it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that does not seem enough. In goBack there is another check for the root name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added the additional check |
||
} | ||
|
||
|
@@ -160,8 +162,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 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) { | ||
// 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) { | ||
navigationRef.current.goBack(); | ||
return; | ||
} | ||
|
@@ -200,45 +202,6 @@ function setParams(params: Record<string, unknown>, 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 | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
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<RootStackParamList>) { | ||
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments above this function are outdated. Please update