diff --git a/src/pages/iou/request/step/DiscardChangesConfirmation/index.tsx b/src/pages/iou/request/step/DiscardChangesConfirmation/index.tsx index 2bab543c737f2..cd7ec60211485 100644 --- a/src/pages/iou/request/step/DiscardChangesConfirmation/index.tsx +++ b/src/pages/iou/request/step/DiscardChangesConfirmation/index.tsx @@ -4,12 +4,13 @@ import React, {memo, useCallback, useEffect, useRef, useState} from 'react'; import ConfirmModal from '@components/ConfirmModal'; import useBeforeRemove from '@hooks/useBeforeRemove'; import useLocalize from '@hooks/useLocalize'; +import navigateAfterInteraction from '@libs/Navigation/navigateAfterInteraction'; import navigationRef from '@libs/Navigation/navigationRef'; import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types'; import type {RootNavigatorParamList} from '@libs/Navigation/types'; import type DiscardChangesConfirmationProps from './types'; -function DiscardChangesConfirmation({getHasUnsavedChanges}: DiscardChangesConfirmationProps) { +function DiscardChangesConfirmation({getHasUnsavedChanges, onCancel}: DiscardChangesConfirmationProps) { const navigation = useNavigation>(); const {translate} = useLocalize(); const [isVisible, setIsVisible] = useState(false); @@ -25,7 +26,7 @@ function DiscardChangesConfirmation({getHasUnsavedChanges}: DiscardChangesConfir e.preventDefault(); blockedNavigationAction.current = e.data.action; - setIsVisible(true); + navigateAfterInteraction(() => setIsVisible((prev) => !prev)); }, [getHasUnsavedChanges], ), @@ -39,16 +40,19 @@ function DiscardChangesConfirmation({getHasUnsavedChanges}: DiscardChangesConfir useEffect(() => { // transitionStart is triggered before the previous page is fully loaded so RHP sliding animation // could be less "glitchy" when going back and forth between the previous and current pages - const unsubscribe = navigation.addListener('transitionStart', () => { + const unsubscribe = navigation.addListener('transitionStart', ({data: {closing}}) => { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - if (!getHasUnsavedChanges() || blockedNavigationAction.current || shouldNavigateBack.current) { + if (!getHasUnsavedChanges()) { + return; + } + shouldNavigateBack.current = true; + if (closing) { + window.history.go(1); return; } - // Navigation.navigate() rerenders the current page and resets its states window.history.go(1); - setIsVisible(true); - shouldNavigateBack.current = true; + navigateAfterInteraction(() => setIsVisible((prev) => !prev)); }); return unsubscribe; @@ -78,6 +82,10 @@ function DiscardChangesConfirmation({getHasUnsavedChanges}: DiscardChangesConfir blockedNavigationAction.current = undefined; shouldNavigateBack.current = false; }} + onModalHide={() => { + shouldNavigateBack.current = false; + onCancel?.(); + }} /> ); } diff --git a/src/pages/iou/request/step/DiscardChangesConfirmation/types.ts b/src/pages/iou/request/step/DiscardChangesConfirmation/types.ts index 45cbf520c7d47..2fdd9d24b5f26 100644 --- a/src/pages/iou/request/step/DiscardChangesConfirmation/types.ts +++ b/src/pages/iou/request/step/DiscardChangesConfirmation/types.ts @@ -1,5 +1,6 @@ type DiscardChangesConfirmationProps = { getHasUnsavedChanges: () => boolean; + onCancel?: () => void; }; export default DiscardChangesConfirmationProps; diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index 4dc02d78632ff..71355420497ce 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -1,6 +1,6 @@ import lodashIsEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo, useRef} from 'react'; -import {View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -64,7 +64,7 @@ function IOURequestStepDescription({ const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const styles = useThemeStyles(); const {translate} = useLocalize(); - const {inputCallbackRef} = useAutoFocusInput(true); + const {inputCallbackRef, inputRef} = useAutoFocusInput(true); const isEditing = action === CONST.IOU.ACTION.EDIT; // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; @@ -200,6 +200,11 @@ function IOURequestStepDescription({ { + InteractionManager.runAfterInteractions(() => { + inputRef.current?.focus(); + }); + }} getHasUnsavedChanges={() => { if (isSavedRef.current) { return false; diff --git a/src/pages/iou/request/step/IOURequestStepMerchant.tsx b/src/pages/iou/request/step/IOURequestStepMerchant.tsx index 9baa0b1e21708..b128b265d6d66 100644 --- a/src/pages/iou/request/step/IOURequestStepMerchant.tsx +++ b/src/pages/iou/request/step/IOURequestStepMerchant.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useRef} from 'react'; -import {View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -41,7 +41,7 @@ function IOURequestStepMerchant({ const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true}); const styles = useThemeStyles(); const {translate} = useLocalize(); - const {inputCallbackRef} = useAutoFocusInput(); + const {inputCallbackRef, inputRef} = useAutoFocusInput(); const isEditing = action === CONST.IOU.ACTION.EDIT; // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value @@ -141,6 +141,11 @@ function IOURequestStepMerchant({ { + InteractionManager.runAfterInteractions(() => { + inputRef.current?.focus(); + }); + }} getHasUnsavedChanges={() => { if (isSavedRef.current) { return false;