diff --git a/src/CONST/index.ts b/src/CONST/index.ts index d058e4f21f1c..85d1baa38463 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7460,6 +7460,10 @@ const CONST = { INVITE_ACCOUNTANT: 'inviteAccountant', ADD_EXPENSE_APPROVALS: 'addExpenseApprovals', }, + + MODAL_EVENTS: { + CLOSED: 'modalClosed', + }, } as const; const CONTINUATION_DETECTION_SEARCH_FILTER_KEYS = [ diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index a997f8ae1ab3..597293716f4b 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -1,9 +1,9 @@ import type {NavigatorScreenParams} from '@react-navigation/native'; import {useFocusEffect} from '@react-navigation/native'; import type {StackCardInterpolationProps} from '@react-navigation/stack'; -import React, {useCallback, useContext, useMemo, useRef} from 'react'; +import React, {useCallback, useContext, useEffect, useMemo, useRef} from 'react'; // eslint-disable-next-line no-restricted-imports -import {Animated, InteractionManager} from 'react-native'; +import {Animated, DeviceEventEmitter, InteractionManager} from 'react-native'; import NoDropZone from '@components/DragAndDrop/NoDropZone'; import {animatedWideRHPWidth, expandedRHPProgress, innerRHPProgress, secondOverlayProgress, thirdOverlayProgress, WideRHPContext} from '@components/WideRHPContextProvider'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -111,6 +111,8 @@ function RightModalNavigator({navigation, route}: RightModalNavigatorProps) { }, [syncWideRHPKeys, syncSuperWideRHPKeys, clearWideRHPKeysAfterTabChanged]), ); + useEffect(() => () => DeviceEventEmitter.emit(CONST.MODAL_EVENTS.CLOSED), []); + return ( diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 908fc34d465d..c27160c6c6b1 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -4,7 +4,7 @@ import {CommonActions, getPathFromState, StackActions} from '@react-navigation/n import {Str} from 'expensify-common'; // eslint-disable-next-line you-dont-need-lodash-underscore/omit import omit from 'lodash/omit'; -import {InteractionManager} from 'react-native'; +import {DeviceEventEmitter, InteractionManager} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {Writable} from 'type-fest'; @@ -35,7 +35,7 @@ import setNavigationActionToMicrotaskQueue from './helpers/setNavigationActionTo import {linkingConfig} from './linkingConfig'; import {SPLIT_TO_SIDEBAR} from './linkingConfig/RELATIONS'; import navigationRef from './navigationRef'; -import type {NavigationPartialRoute, NavigationRoute, NavigationStateRoute, ReportsSplitNavigatorParamList, RootNavigatorParamList, State} from './types'; +import type {NavigationPartialRoute, NavigationRef, NavigationRoute, NavigationStateRoute, ReportsSplitNavigatorParamList, RootNavigatorParamList, State} from './types'; // Routes which are part of the flow to set up 2FA const SET_UP_2FA_ROUTES = new Set([ @@ -569,11 +569,24 @@ function getReportRouteByID(reportID?: string, routes: NavigationRoute[] = navig /** * Closes the modal navigator (RHP, onboarding). + * + * @param options - Configuration object + * @param options.ref - Navigation ref to use (defaults to navigationRef) + * @param options.callback - Optional callback to execute after the modal has finished closing. + * The callback fires when RightModalNavigator unmounts. + * * For detailed information about dismissing modals, * see the NAVIGATION.md documentation. */ -const dismissModal = (ref = navigationRef) => { +const dismissModal = ({ref = navigationRef, callback}: {ref?: NavigationRef; callback?: () => void} = {}) => { isNavigationReady().then(() => { + if (callback) { + const subscription = DeviceEventEmitter.addListener(CONST.MODAL_EVENTS.CLOSED, () => { + subscription.remove(); + callback(); + }); + } + ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL}); // Let React Navigation finish modal transition // eslint-disable-next-line @typescript-eslint/no-deprecated diff --git a/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx b/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx index 598d105c2866..9f321afddbbf 100644 --- a/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx +++ b/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {InteractionManager, Keyboard, View} from 'react-native'; +import {Keyboard, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {GestureResponderEvent} from 'react-native/Libraries/Types/CoreEventTypes'; import FormProvider from '@components/Form/FormProvider'; @@ -157,11 +157,7 @@ function WorkspaceInviteMessageComponent({ } Navigation.setNavigationActionToMicrotaskQueue(() => { - Navigation.dismissModal(); - // eslint-disable-next-line @typescript-eslint/no-deprecated - InteractionManager.runAfterInteractions(() => { - Navigation.navigate(ROUTES.WORKSPACE_MEMBERS.getRoute(policyID)); - }); + Navigation.dismissModal({callback: () => Navigation.navigate(ROUTES.WORKSPACE_MEMBERS.getRoute(policyID))}); }); };