Skip to content

Commit 588f7ca

Browse files
committed
Remove reportID param from dismissModal function
1 parent 76140d4 commit 588f7ca

21 files changed

+162
-46
lines changed

contributingGuides/NAVIGATION.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ When creating RHP flows, you have to remember a couple of things:
3434

3535
- We use a custom `goBack` function to handle the browser and the `react-navigation` history stack. Under the hood, it resolves to either replacing the current screen with the one we navigate to (deeplinking scenario) or just going back if we reached the current page by navigating in App (pops the screen). It ensures the requested behaviors on web, which is navigating back to the place from where you deeplinked when going into the RHP flow by it.
3636

37-
- If you want to navigate to a certain report after completing a flow related to it, e.g. `RequestMoney` flow with a certain group/user, you should use `Navigation.dismissModal` with this `reportID` as an argument. If, in the future, we would like to navigate to something different than the report after such flows, the API should be rather easy to change. We do it like that in order to replace the RHP flow with the new report instead of pushing it, so pressing the back button does not navigate back to the ending page of the flow. If we were to navigate to the same report, we just pop the RHP modal.
37+
- If you want to navigate to a certain report after completing a flow related to it, e.g. `RequestMoney` flow with a certain group/user, you should use `Navigation.dismissModalWithReport` with this `reportID` as an argument. If, in the future, we would like to navigate to something different than the report after such flows, the API should be rather easy to change. We do it like that in order to replace the RHP flow with the new report instead of pushing it, so pressing the back button does not navigate back to the ending page of the flow. If we were to navigate to the same report, we just pop the RHP modal.
3838

3939
### Example of usage
4040

src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {RootNavigatorParamList, State} from '@libs/Navigation/types';
77
import * as SearchQueryUtils from '@libs/SearchQueryUtils';
88
import NAVIGATORS from '@src/NAVIGATORS';
99
import SCREENS from '@src/SCREENS';
10-
import type {OpenWorkspaceSplitActionType, PushActionType, SwitchPolicyIdActionType} from './types';
10+
import type {OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, SwitchPolicyIdActionType} from './types';
1111

1212
const MODAL_ROUTES_TO_DISMISS: string[] = [
1313
NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR,
@@ -237,6 +237,29 @@ function handlePushSearchPageAction(
237237
return stackRouter.getStateForAction(state, updatedAction, configOptions);
238238
}
239239

240+
function handleReplaceReportsSplitNavigatorAction(
241+
state: StackNavigationState<ParamListBase>,
242+
action: ReplaceActionType,
243+
configOptions: RouterConfigOptions,
244+
stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
245+
) {
246+
const stateWithReportsSplitNavigator = stackRouter.getStateForAction(state, action, configOptions);
247+
248+
if (!stateWithReportsSplitNavigator) {
249+
Log.hmmm('[handleReplaceReportsSplitNavigatorAction] ReportsSplitNavigator has not been found in the navigation state.');
250+
return null;
251+
}
252+
253+
const lastReportsSplitNavigator = stateWithReportsSplitNavigator.routes.at(-1);
254+
255+
// ReportScreen should always be opened with an animation when replacing the navigator
256+
if (lastReportsSplitNavigator?.key) {
257+
reportsSplitsWithEnteringAnimation.add(lastReportsSplitNavigator.key);
258+
}
259+
260+
return stateWithReportsSplitNavigator;
261+
}
262+
240263
/**
241264
* Handles the DISMISS_MODAL action.
242265
* If the last route is a modal route, it has to be popped from the navigation stack.
@@ -275,6 +298,7 @@ export {
275298
handleDismissModalAction,
276299
handlePushReportSplitAction,
277300
handlePushSearchPageAction,
301+
handleReplaceReportsSplitNavigatorAction,
278302
handleSwitchPolicyIDAction,
279303
handleSwitchPolicyIDFromSearchAction,
280304
handleNavigatingToModalFromModal,

src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,19 @@ import {
1414
handleOpenWorkspaceSplitAction,
1515
handlePushReportSplitAction,
1616
handlePushSearchPageAction,
17+
handleReplaceReportsSplitNavigatorAction,
1718
handleSwitchPolicyIDAction,
1819
} from './GetStateForActionHandlers';
1920
import syncBrowserHistory from './syncBrowserHistory';
20-
import type {DismissModalActionType, OpenWorkspaceSplitActionType, PushActionType, RootStackNavigatorAction, RootStackNavigatorRouterOptions, SwitchPolicyIdActionType} from './types';
21+
import type {
22+
DismissModalActionType,
23+
OpenWorkspaceSplitActionType,
24+
PushActionType,
25+
ReplaceActionType,
26+
RootStackNavigatorAction,
27+
RootStackNavigatorRouterOptions,
28+
SwitchPolicyIdActionType,
29+
} from './types';
2130

2231
function isOpenWorkspaceSplitAction(action: RootStackNavigatorAction): action is OpenWorkspaceSplitActionType {
2332
return action.type === CONST.NAVIGATION.ACTION_TYPE.OPEN_WORKSPACE_SPLIT;
@@ -31,6 +40,10 @@ function isPushAction(action: RootStackNavigatorAction): action is PushActionTyp
3140
return action.type === CONST.NAVIGATION.ACTION_TYPE.PUSH;
3241
}
3342

43+
function isReplaceAction(action: RootStackNavigatorAction): action is ReplaceActionType {
44+
return action.type === CONST.NAVIGATION.ACTION_TYPE.REPLACE;
45+
}
46+
3447
function isDismissModalAction(action: RootStackNavigatorAction): action is DismissModalActionType {
3548
return action.type === CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL;
3649
}
@@ -82,6 +95,10 @@ function RootStackRouter(options: RootStackNavigatorRouterOptions) {
8295
return handleDismissModalAction(state, configOptions, stackRouter);
8396
}
8497

98+
if (isReplaceAction(action) && action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) {
99+
return handleReplaceReportsSplitNavigatorAction(state, action, configOptions, stackRouter);
100+
}
101+
85102
if (isPushAction(action)) {
86103
if (action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) {
87104
return handlePushReportSplitAction(state, action, configOptions, stackRouter, setActiveWorkspaceID);

src/libs/Navigation/AppNavigator/createRootStackNavigator/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type SwitchPolicyIdActionType = RootStackNavigatorActionType & {
2929

3030
type PushActionType = StackActionType & {type: typeof CONST.NAVIGATION.ACTION_TYPE.PUSH};
3131

32+
type ReplaceActionType = StackActionType & {type: typeof CONST.NAVIGATION.ACTION_TYPE.REPLACE};
33+
3234
type DismissModalActionType = RootStackNavigatorActionType & {
3335
type: typeof CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL;
3436
};
@@ -49,6 +51,7 @@ export type {
4951
OpenWorkspaceSplitActionType,
5052
SwitchPolicyIdActionType,
5153
PushActionType,
54+
ReplaceActionType,
5255
DismissModalActionType,
5356
RootStackNavigatorAction,
5457
RootStackNavigatorActionType,

src/libs/Navigation/Navigation.ts

+31-11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import originalCloseRHPFlow from './helpers/closeRHPFlow';
2424
import getPolicyIDFromState from './helpers/getPolicyIDFromState';
2525
import getStateFromPath from './helpers/getStateFromPath';
2626
import getTopmostReportParams from './helpers/getTopmostReportParams';
27+
import {isFullScreenName} from './helpers/isNavigatorName';
2728
import isReportOpenInRHP from './helpers/isReportOpenInRHP';
2829
import linkTo from './helpers/linkTo';
2930
import getMinimalAction from './helpers/linkTo/getMinimalAction';
@@ -468,20 +469,20 @@ function waitForProtectedRoutes() {
468469
});
469470
}
470471

471-
type NavigateToReportWithPolicyCheckPayload = {report?: OnyxEntry<Report>; reportID?: string; reportActionID?: string; referrer?: string; policyIDToCheck?: string};
472+
type NavigateToReportWithPolicyCheckPayload = {report?: OnyxEntry<Report>; reportID?: string; reportActionID?: string; referrer?: string; policyIDToCheck?: string; forceReplace?: boolean};
472473

473474
/**
474475
* Navigates to a report passed as a param (as an id or report object) and checks whether the target object belongs to the currently selected workspace.
475476
* If not, the current workspace is set to global.
476477
*/
477-
function navigateToReportWithPolicyCheck({report, reportID, reportActionID, referrer, policyIDToCheck}: NavigateToReportWithPolicyCheckPayload, ref = navigationRef) {
478+
function navigateToReportWithPolicyCheck({report, reportID, reportActionID, referrer, policyIDToCheck}: NavigateToReportWithPolicyCheckPayload, forceReplace = false, ref = navigationRef) {
478479
const targetReport = reportID ? {reportID, ...allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]} : report;
479480
const policyID = policyIDToCheck ?? getPolicyIDFromState(navigationRef.getRootState() as State<RootNavigatorParamList>);
480481
const policyMemberAccountIDs = getPolicyEmployeeAccountIDs(policyID);
481482
const shouldOpenAllWorkspace = isEmptyObject(targetReport) ? true : !doesReportBelongToWorkspace(targetReport, policyMemberAccountIDs, policyID);
482483

483484
if ((shouldOpenAllWorkspace && !policyID) || !shouldOpenAllWorkspace) {
484-
linkTo(ref.current, ROUTES.REPORT_WITH_ID.getRoute(targetReport?.reportID, reportActionID, referrer));
485+
linkTo(ref.current, ROUTES.REPORT_WITH_ID.getRoute(targetReport?.reportID, reportActionID, referrer), {forceReplace: !!forceReplace});
485486
return;
486487
}
487488

@@ -497,6 +498,17 @@ function navigateToReportWithPolicyCheck({report, reportID, reportActionID, refe
497498
params.referrer = referrer;
498499
}
499500

501+
if (forceReplace) {
502+
ref.dispatch(
503+
StackActions.replace(NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, {
504+
policyID: undefined,
505+
screen: SCREENS.REPORT,
506+
params,
507+
}),
508+
);
509+
return;
510+
}
511+
500512
ref.dispatch(
501513
StackActions.push(NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, {
502514
policyID: undefined,
@@ -527,23 +539,31 @@ function getReportRouteByID(reportID?: string, routes: NavigationRoute[] = navig
527539
/**
528540
* Closes the modal navigator (RHP, LHP, onboarding).
529541
*/
530-
const dismissModal = (reportID?: string, ref = navigationRef) => {
542+
const dismissModal = (ref = navigationRef) => {
531543
isNavigationReady().then(() => {
532544
ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL});
533-
if (!reportID) {
534-
return;
535-
}
536-
navigateToReportWithPolicyCheck({reportID});
537545
});
538546
};
539547

540548
/**
541549
* Dismisses the modal and opens the given report.
542550
*/
543-
const dismissModalWithReport = (report: OnyxEntry<Report>, ref = navigationRef) => {
551+
const dismissModalWithReport = (navigateToReportPayload: NavigateToReportWithPolicyCheckPayload, ref = navigationRef) => {
544552
isNavigationReady().then(() => {
545-
ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL});
546-
navigateToReportWithPolicyCheck({report});
553+
if (getIsNarrowLayout()) {
554+
const topmostReportID = getTopmostReportId();
555+
const areReportsIDsDefined = !!topmostReportID && !!navigateToReportPayload.reportID;
556+
const isReportsSplitTopmostFullScreen = ref.getRootState().routes.findLast((route) => isFullScreenName(route.name))?.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR;
557+
if (topmostReportID === navigateToReportPayload.reportID && areReportsIDsDefined && isReportsSplitTopmostFullScreen) {
558+
dismissModal();
559+
return;
560+
}
561+
const forceReplace = true;
562+
navigateToReportWithPolicyCheck(navigateToReportPayload, forceReplace);
563+
return;
564+
}
565+
dismissModal();
566+
navigateToReportWithPolicyCheck(navigateToReportPayload);
547567
});
548568
};
549569

src/libs/actions/IOU.ts

+49-11
Original file line numberDiff line numberDiff line change
@@ -4717,7 +4717,11 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
47174717
}
47184718

47194719
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
4720-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID);
4720+
if (isSearchTopmostFullScreenRoute()) {
4721+
Navigation.dismissModal();
4722+
} else {
4723+
Navigation.dismissModalWithReport({reportID: activeReportID});
4724+
}
47214725

47224726
const trackReport = Navigation.getReportRouteByID(linkedTrackedExpenseReportAction?.childReportID);
47234727
if (trackReport?.key) {
@@ -4801,7 +4805,12 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
48014805
API.write(WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST, parameters, onyxData);
48024806

48034807
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
4804-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID);
4808+
if (isSearchTopmostFullScreenRoute()) {
4809+
Navigation.dismissModal();
4810+
} else {
4811+
Navigation.dismissModalWithReport({reportID: activeReportID});
4812+
}
4813+
48054814
if (activeReportID) {
48064815
notifyNewAction(activeReportID, payeeAccountID);
48074816
}
@@ -4868,7 +4877,7 @@ function sendInvoice(
48684877
if (isSearchTopmostFullScreenRoute()) {
48694878
Navigation.dismissModal();
48704879
} else {
4871-
Navigation.dismissModalWithReport(invoiceRoom);
4880+
Navigation.dismissModalWithReport({report: invoiceRoom});
48724881
}
48734882

48744883
notifyNewAction(invoiceRoom.reportID, receiver.accountID);
@@ -5094,7 +5103,11 @@ function trackExpense(params: CreateTrackExpenseParams) {
50945103
}
50955104
}
50965105
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
5097-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID);
5106+
if (isSearchTopmostFullScreenRoute()) {
5107+
Navigation.dismissModal();
5108+
} else {
5109+
Navigation.dismissModalWithReport({reportID: activeReportID});
5110+
}
50985111

50995112
if (action === CONST.IOU.ACTION.SHARE) {
51005113
if (isSearchTopmostFullScreenRoute() && activeReportID) {
@@ -5676,7 +5689,12 @@ function splitBill({
56765689
API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData);
56775690
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
56785691

5679-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : existingSplitChatReportID);
5692+
if (isSearchTopmostFullScreenRoute()) {
5693+
Navigation.dismissModal();
5694+
} else {
5695+
Navigation.dismissModalWithReport({reportID: existingSplitChatReportID});
5696+
}
5697+
56805698
notifyNewAction(splitData.chatReportID, currentUserAccountID);
56815699
}
56825700

@@ -5749,7 +5767,11 @@ function splitBillAndOpenReport({
57495767
API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData);
57505768
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
57515769

5752-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : splitData.chatReportID);
5770+
if (isSearchTopmostFullScreenRoute()) {
5771+
Navigation.dismissModal();
5772+
} else {
5773+
Navigation.dismissModalWithReport({reportID: splitData.chatReportID});
5774+
}
57535775
notifyNewAction(splitData.chatReportID, currentUserAccountID);
57545776
}
57555777

@@ -6072,7 +6094,7 @@ function startSplitBill({
60726094

60736095
API.write(WRITE_COMMANDS.START_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
60746096

6075-
Navigation.dismissModalWithReport(splitChatReport);
6097+
Navigation.dismissModalWithReport({report: splitChatReport});
60766098
notifyNewAction(splitChatReport.reportID, currentUserAccountID);
60776099
}
60786100

@@ -6331,7 +6353,11 @@ function completeSplitBill(
63316353

63326354
API.write(WRITE_COMMANDS.COMPLETE_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
63336355
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
6334-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : chatReportID);
6356+
if (isSearchTopmostFullScreenRoute()) {
6357+
Navigation.dismissModal();
6358+
} else {
6359+
Navigation.dismissModalWithReport({reportID: chatReportID});
6360+
}
63356361
notifyNewAction(chatReportID, sessionAccountID);
63366362
}
63376363

@@ -6514,7 +6540,11 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest
65146540
API.write(WRITE_COMMANDS.CREATE_DISTANCE_REQUEST, parameters, onyxData);
65156541
InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID));
65166542
const activeReportID = isMoneyRequestReport && report?.reportID ? report.reportID : parameters.chatReportID;
6517-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID);
6543+
if (isSearchTopmostFullScreenRoute()) {
6544+
Navigation.dismissModal();
6545+
} else {
6546+
Navigation.dismissModalWithReport({reportID: activeReportID});
6547+
}
65186548
notifyNewAction(activeReportID, userAccountID);
65196549
}
65206550

@@ -8202,7 +8232,11 @@ function sendMoneyElsewhere(report: OnyxEntry<OnyxTypes.Report>, amount: number,
82028232

82038233
API.write(WRITE_COMMANDS.SEND_MONEY_ELSEWHERE, params, {optimisticData, successData, failureData});
82048234

8205-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : params.chatReportID);
8235+
if (isSearchTopmostFullScreenRoute()) {
8236+
Navigation.dismissModal();
8237+
} else {
8238+
Navigation.dismissModalWithReport({reportID: params.chatReportID});
8239+
}
82068240
notifyNewAction(params.chatReportID, managerID);
82078241
}
82088242

@@ -8215,7 +8249,11 @@ function sendMoneyWithWallet(report: OnyxEntry<OnyxTypes.Report>, amount: number
82158249

82168250
API.write(WRITE_COMMANDS.SEND_MONEY_WITH_WALLET, params, {optimisticData, successData, failureData});
82178251

8218-
Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : params.chatReportID);
8252+
if (isSearchTopmostFullScreenRoute()) {
8253+
Navigation.dismissModal();
8254+
} else {
8255+
Navigation.dismissModalWithReport({reportID: params.chatReportID});
8256+
}
82198257
notifyNewAction(params.chatReportID, managerID);
82208258
}
82218259

src/libs/actions/Report.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import getEnvironment from '@libs/Environment/getEnvironment';
6262
import type EnvironmentType from '@libs/Environment/getEnvironment/types';
6363
import * as ErrorUtils from '@libs/ErrorUtils';
6464
import fileDownload from '@libs/fileDownload';
65+
import getIsNarrowLayout from '@libs/getIsNarrowLayout';
6566
import HttpUtils from '@libs/HttpUtils';
6667
import isPublicScreenRoute from '@libs/isPublicScreenRoute';
6768
import * as Localize from '@libs/Localize';
@@ -1187,6 +1188,11 @@ function navigateToAndOpenReport(
11871188
// We want to pass newChat here because if anything is passed in that param (even an existing chat), we will try to create a chat on the server
11881189
openReport(report?.reportID, '', userLogins, newChat, undefined, undefined, undefined, avatarFile);
11891190
if (shouldDismissModal) {
1191+
if (getIsNarrowLayout()) {
1192+
Navigation.dismissModalWithReport({report});
1193+
return;
1194+
}
1195+
11901196
Navigation.dismissModal();
11911197
}
11921198

@@ -2394,7 +2400,7 @@ function navigateToConciergeChat(shouldDismissModal = false, checkIfCurrentPageA
23942400
navigateToAndOpenReport([CONST.EMAIL.CONCIERGE], shouldDismissModal);
23952401
});
23962402
} else if (shouldDismissModal) {
2397-
Navigation.dismissModal(conciergeChatReportID);
2403+
Navigation.dismissModalWithReport({reportID: conciergeChatReportID});
23982404
} else {
23992405
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeChatReportID), linkToOptions);
24002406
}
@@ -2503,7 +2509,7 @@ function addPolicyReport(policyReport: OptimisticChatReport) {
25032509
};
25042510

25052511
API.write(WRITE_COMMANDS.ADD_WORKSPACE_ROOM, parameters, {optimisticData, successData, failureData});
2506-
Navigation.dismissModalWithReport(policyReport);
2512+
Navigation.dismissModalWithReport({report: policyReport});
25072513
}
25082514

25092515
/** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */

src/libs/actions/Task.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ function createTaskAndNavigate(
339339
InteractionManager.runAfterInteractions(() => {
340340
clearOutTaskInfo();
341341
});
342-
Navigation.dismissModal(parentReportID);
342+
Navigation.dismissModalWithReport({reportID: parentReportID});
343343
}
344344
notifyNewAction(parentReportID, currentUserAccountID);
345345
}

0 commit comments

Comments
 (0)