-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathRootStackRouter.ts
127 lines (105 loc) · 5.48 KB
/
RootStackRouter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigationState} from '@react-navigation/native';
import {findFocusedRoute, StackRouter} from '@react-navigation/native';
import type {ParamListBase} from '@react-navigation/routers';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import * as Localize from '@libs/Localize';
import {isOnboardingFlowName} from '@libs/Navigation/helpers/isNavigatorName';
import isSideModalNavigator from '@libs/Navigation/helpers/isSideModalNavigator';
import * as Welcome from '@userActions/Welcome';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import {
handleDismissModalAction,
handleNavigatingToModalFromModal,
handleOpenWorkspaceSplitAction,
handlePushReportSplitAction,
handlePushSearchPageAction,
handleReplaceReportsSplitNavigatorAction,
handleSwitchPolicyIDAction,
} from './GetStateForActionHandlers';
import syncBrowserHistory from './syncBrowserHistory';
import type {
DismissModalActionType,
OpenWorkspaceSplitActionType,
PushActionType,
ReplaceActionType,
RootStackNavigatorAction,
RootStackNavigatorRouterOptions,
SwitchPolicyIdActionType,
} from './types';
function isOpenWorkspaceSplitAction(action: RootStackNavigatorAction): action is OpenWorkspaceSplitActionType {
return action.type === CONST.NAVIGATION.ACTION_TYPE.OPEN_WORKSPACE_SPLIT;
}
function isSwitchPolicyIdAction(action: RootStackNavigatorAction): action is SwitchPolicyIdActionType {
return action.type === CONST.NAVIGATION.ACTION_TYPE.SWITCH_POLICY_ID;
}
function isPushAction(action: RootStackNavigatorAction): action is PushActionType {
return action.type === CONST.NAVIGATION.ACTION_TYPE.PUSH;
}
function isReplaceAction(action: RootStackNavigatorAction): action is ReplaceActionType {
return action.type === CONST.NAVIGATION.ACTION_TYPE.REPLACE;
}
function isDismissModalAction(action: RootStackNavigatorAction): action is DismissModalActionType {
return action.type === CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL;
}
function shouldPreventReset(state: StackNavigationState<ParamListBase>, action: CommonActions.Action | StackActionType) {
if (action.type !== CONST.NAVIGATION_ACTIONS.RESET || !action?.payload) {
return false;
}
const currentFocusedRoute = findFocusedRoute(state);
const targetFocusedRoute = findFocusedRoute(action?.payload);
// We want to prevent the user from navigating back to a non-onboarding screen if they are currently on an onboarding screen
if (isOnboardingFlowName(currentFocusedRoute?.name) && !isOnboardingFlowName(targetFocusedRoute?.name)) {
Welcome.setOnboardingErrorMessage(Localize.translateLocal('onboarding.purpose.errorBackButton'));
return true;
}
return false;
}
function isNavigatingToModalFromModal(state: StackNavigationState<ParamListBase>, action: CommonActions.Action | StackActionType): action is PushActionType {
if (action.type !== CONST.NAVIGATION.ACTION_TYPE.PUSH) {
return false;
}
const lastRoute = state.routes.at(-1);
// If the last route is a side modal navigator and the generated minimal action want's to push a new side modal navigator that means they are different ones.
// We want to dismiss the one that is currently on the top.
return isSideModalNavigator(lastRoute?.name) && isSideModalNavigator(action.payload.name);
}
function RootStackRouter(options: RootStackNavigatorRouterOptions) {
const stackRouter = StackRouter(options);
const {setActiveWorkspaceID} = useActiveWorkspace();
return {
...stackRouter,
getStateForAction(state: StackNavigationState<ParamListBase>, action: RootStackNavigatorAction, configOptions: RouterConfigOptions) {
if (isOpenWorkspaceSplitAction(action)) {
return handleOpenWorkspaceSplitAction(state, action, configOptions, stackRouter);
}
if (isSwitchPolicyIdAction(action)) {
return handleSwitchPolicyIDAction(state, action, configOptions, stackRouter, setActiveWorkspaceID);
}
if (isDismissModalAction(action)) {
return handleDismissModalAction(state, configOptions, stackRouter);
}
if (isReplaceAction(action) && action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) {
return handleReplaceReportsSplitNavigatorAction(state, action, configOptions, stackRouter);
}
if (isPushAction(action)) {
if (action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) {
return handlePushReportSplitAction(state, action, configOptions, stackRouter, setActiveWorkspaceID);
}
if (action.payload.name === NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR) {
return handlePushSearchPageAction(state, action, configOptions, stackRouter, setActiveWorkspaceID);
}
}
// Don't let the user navigate back to a non-onboarding screen if they are currently on an onboarding screen and it's not finished.
if (shouldPreventReset(state, action)) {
syncBrowserHistory(state);
return state;
}
if (isNavigatingToModalFromModal(state, action)) {
return handleNavigatingToModalFromModal(state, action, configOptions, stackRouter);
}
return stackRouter.getStateForAction(state, action, configOptions);
},
};
}
export default RootStackRouter;