From 61b2f6a8f06d93fb6036475e00981f0526b3be20 Mon Sep 17 00:00:00 2001 From: Faizan Shoukat Abbasi Date: Thu, 18 Dec 2025 03:27:27 +0500 Subject: [PATCH 1/3] refactored ConfirmModal usage to useConfirmModal --- src/pages/home/HeaderView.tsx | 31 ---- .../PopoverReportActionContextMenu.tsx | 132 ++++++++---------- .../ContextMenu/ReportActionContextMenu.ts | 2 +- .../home/report/PureReportActionItem.tsx | 41 +++--- .../home/report/ReportDetailsExportPage.tsx | 76 +++++----- 5 files changed, 123 insertions(+), 159 deletions(-) diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 52176f7d5e42c..aace344ba0513 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -5,7 +5,6 @@ import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import Button from '@components/Button'; import CaretWrapper from '@components/CaretWrapper'; -import ConfirmModal from '@components/ConfirmModal'; import DisplayNames from '@components/DisplayNames'; import Icon from '@components/Icon'; // eslint-disable-next-line no-restricted-imports @@ -22,9 +21,6 @@ import HelpButton from '@components/SidePanel/HelpComponents/HelpButton'; import TaskHeaderActionButton from '@components/TaskHeaderActionButton'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; -import useAncestors from '@hooks/useAncestors'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useHasOutstandingChildTask from '@hooks/useHasOutstandingChildTask'; import useHasTeam2025Pricing from '@hooks/useHasTeam2025Pricing'; import useLoadingBarVisibility from '@hooks/useLoadingBarVisibility'; import useLocalize from '@hooks/useLocalize'; @@ -75,7 +71,6 @@ import EarlyDiscountBanner from '@pages/settings/Subscription/CardSection/Billin import FreeTrial from '@pages/settings/Subscription/FreeTrial'; import {joinRoom} from '@userActions/Report'; import {callFunctionIfActionIsAllowed} from '@userActions/Session'; -import {deleteTask} from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; @@ -103,7 +98,6 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth} = useResponsiveLayout(); const route = useRoute(); - const [isDeleteTaskConfirmModalVisible, setIsDeleteTaskConfirmModalVisible] = React.useState(false); const invoiceReceiverPolicyID = report?.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : undefined; const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`, {canBeMissing: true}); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID) ?? getNonEmptyStringOnyxID(report?.reportID)}`, {canBeMissing: true}); @@ -116,11 +110,9 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, const [firstDayFreeTrial] = useOnyx(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, {canBeMissing: true}); const [lastDayFreeTrial] = useOnyx(ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL, {canBeMissing: true}); const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: true}); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {canBeMissing: true}); const isReportArchived = isArchivedReport(reportNameValuePairs); - const hasOutstandingChildTask = useHasOutstandingChildTask(report); const {translate, localeCompare} = useLocalize(); const theme = useTheme(); @@ -158,7 +150,6 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, // This is used to ensure that we display the text exactly as the user entered it when displaying thread header text, instead of parsing their text to HTML. const shouldParseFullTitle = parentReportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT && !isGroupChat; const subscriptionPlan = useSubscriptionPlan(); - const ancestors = useAncestors(report); const shouldShowSubtitle = () => { if (!subtitle) { @@ -375,28 +366,6 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, {shouldDisplaySearchRouter && } - { - setIsDeleteTaskConfirmModalVisible(false); - deleteTask( - report, - parentReport, - isReportArchived, - currentUserPersonalDetails.accountID, - hasOutstandingChildTask, - parentReportAction ?? undefined, - ancestors, - ); - }} - onCancel={() => setIsDeleteTaskConfirmModalVisible(false)} - title={translate('task.deleteTask')} - prompt={translate('task.deleteConfirmation')} - confirmText={translate('common.delete')} - cancelText={translate('common.cancel')} - danger - shouldEnableNewFocusManagement - /> )} diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx index ce5f68b5ecf04..21fee979ba1f0 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -7,10 +7,11 @@ import type {EmitterSubscription, GestureResponderEvent, NativeTouchEvent, View} import {DeviceEventEmitter, Dimensions, InteractionManager} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {Actions, ActionSheetAwareScrollViewContext} from '@components/ActionSheetAwareScrollView'; -import ConfirmModal from '@components/ConfirmModal'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import PopoverWithMeasuredContent from '@components/PopoverWithMeasuredContent'; import {useSearchContext} from '@components/Search/SearchContext'; import useAncestors from '@hooks/useAncestors'; +import useConfirmModal from '@hooks/useConfirmModal'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDeleteTransactions from '@hooks/useDeleteTransactions'; import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations'; @@ -49,6 +50,7 @@ type PopoverReportActionContextMenuProps = { function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuProps) { const {translate} = useLocalize(); + const {showConfirmModal} = useConfirmModal(); const reportIDRef = useRef(undefined); const typeRef = useRef(undefined); const reportActionRef = useRef> | null>(null); @@ -75,8 +77,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const {email} = useCurrentUserPersonalDetails(); const [isPopoverVisible, setIsPopoverVisible] = useState(false); - const [isDeleteCommentConfirmModalVisible, setIsDeleteCommentConfirmModalVisible] = useState(false); - const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); const [isChronosReportEnabled, setIsChronosReportEnabled] = useState(false); @@ -104,7 +104,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const onPopoverHide = useRef(() => {}); const onEmojiPickerToggle = useRef void)>(undefined); const onCancelDeleteModal = useRef(() => {}); - const onConfirmDeleteModal = useRef(() => {}); const onPopoverHideActionCallback = useRef(() => {}); const callbackWhenDeleteModalHide = useRef(() => {}); @@ -342,8 +341,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro } ancestorsRef.current = ancestors; }, [originalReport, ancestors]); - const confirmDeleteAndHideModal = useCallback(() => { - callbackWhenDeleteModalHide.current = runAndResetCallback(onConfirmDeleteModal.current); + const performDelete = useCallback(() => { const reportAction = reportActionRef.current; if (isMoneyRequestAction(reportAction)) { const originalMessage = getOriginalMessage(reportAction); @@ -374,7 +372,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro } DeviceEventEmitter.emit(`deletedReportAction_${reportIDRef.current}`, reportAction?.reportActionID); - setIsDeleteCommentConfirmModalVisible(false); }, [ report, iouReport, @@ -389,27 +386,41 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro email, ]); - const hideDeleteModal = () => { + const hideDeleteModal = useCallback(() => { callbackWhenDeleteModalHide.current = () => (onCancelDeleteModal.current = runAndResetCallback(onCancelDeleteModal.current)); - setIsDeleteCommentConfirmModalVisible(false); - setShouldSetModalVisibilityForDeleteConfirmation(true); setIsRoomArchived(false); setIsChronosReportEnabled(false); setIsChatPinned(false); setHasUnreadMessages(false); - }; + }, []); /** Opens the Confirm delete action modal */ - const showDeleteModal: ReportActionContextMenu['showDeleteModal'] = (reportID, reportAction, shouldSetModalVisibility = true, onConfirm = () => {}, onCancel = () => {}) => { - onCancelDeleteModal.current = onCancel; + const showDeleteModal: ReportActionContextMenu['showDeleteModal'] = useCallback( + async (reportID, reportAction, shouldSetModalVisibility = true, onConfirm = () => {}, onCancel = () => {}) => { + reportIDRef.current = reportID; + reportActionRef.current = reportAction ?? null; + + const result = await showConfirmModal({ + title: translate('reportActionContextMenu.deleteAction', {action: reportAction}), + prompt: translate('reportActionContextMenu.deleteConfirmation', {action: reportAction}), + confirmText: translate('common.delete'), + cancelText: translate('common.cancel'), + danger: true, + shouldSetModalVisibility, + }); - onConfirmDeleteModal.current = onConfirm; - reportIDRef.current = reportID; - reportActionRef.current = reportAction ?? null; + clearActiveReportAction(); + callbackWhenDeleteModalHide.current(); - setShouldSetModalVisibilityForDeleteConfirmation(shouldSetModalVisibility); - setIsDeleteCommentConfirmModalVisible(true); - }; + if (result.action === ModalActions.CONFIRM) { + onConfirm(); + performDelete(); + } else { + onCancel(); + } + }, + [showConfirmModal, translate, performDelete], + ); useImperativeHandle(ref, () => ({ showContextMenu, @@ -425,60 +436,41 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro composerToRefocusOnCloseEmojiPicker: composerToRefocusOnClose, })); - const reportAction = reportActionRef.current; - return ( - <> - hideContextMenu()} + onModalShow={runAndResetOnPopoverShow} + onModalHide={runAndResetOnPopoverHide} + anchorPosition={popoverAnchorPosition.current} + animationIn="fadeIn" + disableAnimation={false} + shouldSetModalVisibility={false} + fullscreen + withoutOverlay={isWithoutOverlay} + anchorDimensions={contextMenuDimensions.current} + anchorRef={anchorRef} + shouldSwitchPositionIfOverflow={shouldSwitchPositionIfOverflow} + > + hideContextMenu()} - onModalShow={runAndResetOnPopoverShow} - onModalHide={runAndResetOnPopoverHide} - anchorPosition={popoverAnchorPosition.current} - animationIn="fadeIn" - disableAnimation={false} - shouldSetModalVisibility={false} - fullscreen - withoutOverlay={isWithoutOverlay} - anchorDimensions={contextMenuDimensions.current} - anchorRef={anchorRef} - shouldSwitchPositionIfOverflow={shouldSwitchPositionIfOverflow} - > - - - { - clearActiveReportAction(); - callbackWhenDeleteModalHide.current(); - }} - prompt={translate('reportActionContextMenu.deleteConfirmation', {action: reportAction})} - confirmText={translate('common.delete')} - cancelText={translate('common.cancel')} - danger + type={typeRef.current} + reportID={reportIDRef.current} + reportActionID={reportActionIDRef.current} + draftMessage={reportActionDraftMessageRef.current} + selection={selectionRef.current} + isArchivedRoom={isRoomArchived} + isChronosReport={isChronosReportEnabled} + isPinnedChat={isChatPinned} + isUnreadChat={hasUnreadMessages} + isThreadReportParentAction={isThreadReportParentAction} + anchor={contextMenuTargetNode} + contentRef={contentRef} + originalReportID={originalReportIDRef.current} + disabledActions={disabledActions} + setIsEmojiPickerActive={onEmojiPickerToggle.current} /> - + ); } diff --git a/src/pages/home/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/home/report/ContextMenu/ReportActionContextMenu.ts index 2da4ac2bbffc8..10c53353cd110 100644 --- a/src/pages/home/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/home/report/ContextMenu/ReportActionContextMenu.ts @@ -58,7 +58,7 @@ type HideContextMenu = (params?: HideContextMenuParams) => void; type ReportActionContextMenu = { showContextMenu: ShowContextMenu; hideContextMenu: HideContextMenu; - showDeleteModal: (reportID: string, reportAction: OnyxEntry, shouldSetModalVisibility?: boolean, onConfirm?: OnConfirm, onCancel?: OnCancel) => void; + showDeleteModal: (reportID: string, reportAction: OnyxEntry, shouldSetModalVisibility?: boolean, onConfirm?: OnConfirm, onCancel?: OnCancel) => Promise; hideDeleteModal: () => void; isActiveReportAction: (accountID: string | number) => boolean; instanceIDRef: RefObject; diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index 9ddbc89046861..9554472e834f7 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -10,7 +10,6 @@ import type {Emoji} from '@assets/emojis/types'; import * as ActionSheetAwareScrollView from '@components/ActionSheetAwareScrollView'; import {AttachmentContext} from '@components/AttachmentContext'; import Button from '@components/Button'; -import ConfirmModal from '@components/ConfirmModal'; import DisplayNames from '@components/DisplayNames'; import Hoverable from '@components/Hoverable'; import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; @@ -18,6 +17,7 @@ import Icon from '@components/Icon'; import InlineSystemMessage from '@components/InlineSystemMessage'; import KYCWall from '@components/KYCWall'; import {KYCWallContext} from '@components/KYCWall/KYCWallContext'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; import ReportActionItemEmojiReactions from '@components/Reactions/ReportActionItemEmojiReactions'; @@ -39,6 +39,7 @@ import {ShowContextMenuContext} from '@components/ShowContextMenuContext'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import UnreadActionIndicator from '@components/UnreadActionIndicator'; +import useConfirmModal from '@hooks/useConfirmModal'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -490,6 +491,7 @@ function PureReportActionItem({ }: PureReportActionItemProps) { const actionSheetAwareScrollViewContext = useContext(ActionSheetAwareScrollView.ActionSheetAwareScrollViewContext); const {translate, formatPhoneNumber, localeCompare, formatTravelDate, getLocalDateFromDatetime} = useLocalize(); + const {showConfirmModal} = useConfirmModal(); const personalDetail = useCurrentUserPersonalDetails(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const reportID = report?.reportID ?? action?.reportID; @@ -552,7 +554,6 @@ function PureReportActionItem({ currentSearchHash = searchContextCurrentSearchHash; } - const [showConfirmDismissReceiptError, setShowConfirmDismissReceiptError] = useState(false); const dismissError = useCallback(() => { const transactionID = isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUTransactionID : undefined; if (transactionID) { @@ -561,18 +562,32 @@ function PureReportActionItem({ clearAllRelatedReportActionErrors(reportID, action); }, [reportID, clearError, clearAllRelatedReportActionErrors, action]); - const onClose = () => { + const showDismissReceiptErrorModal = useCallback(async () => { + const result = await showConfirmModal({ + title: translate('iou.dismissReceiptError'), + prompt: translate('iou.dismissReceiptErrorConfirmation'), + confirmText: translate('common.dismiss'), + cancelText: translate('common.cancel'), + shouldShowCancelButton: true, + danger: true, + }); + if (result.action === ModalActions.CONFIRM) { + dismissError(); + } + }, [showConfirmModal, translate, dismissError]); + + const onClose = useCallback(() => { const errors = linkedTransactionRouteError ?? getLatestErrorMessageField(action as OnyxDataWithErrors); const errorEntries = Object.entries(errors ?? {}); const errorMessages = mapValues(Object.fromEntries(errorEntries), (error) => error); const hasReceiptError = Object.values(errorMessages).some((error) => isReceiptError(error)); if (hasReceiptError) { - setShowConfirmDismissReceiptError(true); + showDismissReceiptErrorModal(); } else { dismissError(); } - }; + }, [linkedTransactionRouteError, action, showDismissReceiptErrorModal, dismissError]); useEffect( () => () => { // ReportActionContextMenu, EmojiPicker and PopoverReactionList are global components, @@ -1890,22 +1905,6 @@ function PureReportActionItem({ - { - dismissError(); - setShowConfirmDismissReceiptError(false); - }} - onCancel={() => { - setShowConfirmDismissReceiptError(false); - }} - title={translate('iou.dismissReceiptError')} - prompt={translate('iou.dismissReceiptErrorConfirmation')} - confirmText={translate('common.dismiss')} - cancelText={translate('common.cancel')} - shouldShowCancelButton - danger - /> ); diff --git a/src/pages/home/report/ReportDetailsExportPage.tsx b/src/pages/home/report/ReportDetailsExportPage.tsx index d19d33da74ff8..13be42d70a539 100644 --- a/src/pages/home/report/ReportDetailsExportPage.tsx +++ b/src/pages/home/report/ReportDetailsExportPage.tsx @@ -1,12 +1,13 @@ -import React, {useCallback, useState} from 'react'; +import React, {useCallback} from 'react'; import type {ValueOf} from 'type-fest'; import ConfirmationPage from '@components/ConfirmationPage'; -import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import ScreenWrapper from '@components/ScreenWrapper'; import UserListItem from '@components/SelectionListWithSections/UserListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; +import useConfirmModal from '@hooks/useConfirmModal'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -36,7 +37,7 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { const policyID = report?.policyID; const {translate} = useLocalize(); - const [modalStatus, setModalStatus] = useState(null); + const {showConfirmModal} = useConfirmModal(); const styles = useThemeStyles(); const lazyIllustrations = useMemoizedLazyIllustrations(['LaptopWithSecondScreenAndHourglass']); const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare']); @@ -46,16 +47,30 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { const isExported = isExportedUtil(reportActions); const confirmExport = useCallback( - (type = modalStatus) => { + (type: ExportType) => { if (type === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) { exportToIntegration(reportID, connectionName); } else if (type === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) { markAsManuallyExported(reportID, connectionName); } - setModalStatus(null); Navigation.dismissModal(); }, - [connectionName, modalStatus, reportID], + [connectionName, reportID], + ); + + const showExportAgainModal = useCallback( + async (type: ExportType) => { + const result = await showConfirmModal({ + title: translate('workspace.exportAgainModal.title'), + prompt: translate('workspace.exportAgainModal.description', {reportName: report?.reportName ?? '', connectionName}), + confirmText: translate('workspace.exportAgainModal.confirmText'), + cancelText: translate('workspace.exportAgainModal.cancelText'), + }); + if (result.action === ModalActions.CONFIRM) { + confirmExport(type); + } + }, + [showConfirmModal, translate, report?.reportName, connectionName, confirmExport], ); const exportSelectorOptions: ExportSelectorType[] = [ @@ -105,36 +120,25 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { } return ( - <> - - policyID={policyID} - accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]} - featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} - displayName="ReportDetailsExportPage" - sections={[{data: exportSelectorOptions}]} - listItem={UserListItem} - shouldBeBlocked={false} - onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo))} - title="common.export" - connectionName={connectionName} - onSelectRow={({value}) => { - if (isExported) { - setModalStatus(value); - } else { - confirmExport(value); - } - }} - /> - setModalStatus(null)} - prompt={translate('workspace.exportAgainModal.description', {reportName: report?.reportName ?? '', connectionName})} - confirmText={translate('workspace.exportAgainModal.confirmText')} - cancelText={translate('workspace.exportAgainModal.cancelText')} - isVisible={!!modalStatus} - /> - + + policyID={policyID} + accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]} + featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} + displayName="ReportDetailsExportPage" + sections={[{data: exportSelectorOptions}]} + listItem={UserListItem} + shouldBeBlocked={false} + onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo))} + title="common.export" + connectionName={connectionName} + onSelectRow={({value}) => { + if (isExported) { + showExportAgainModal(value); + } else { + confirmExport(value); + } + }} + /> ); } From 913d06395657c0afe17af778e25c4d74e891e071 Mon Sep 17 00:00:00 2001 From: Faizan Shoukat Abbasi Date: Sat, 3 Jan 2026 05:48:13 +0500 Subject: [PATCH 2/3] Fixed order of operations in showDeleteModal - refs were being cleared before performDelete() was called --- .../report/ContextMenu/PopoverReportActionContextMenu.tsx | 8 ++++---- src/pages/home/report/PureReportActionItem.tsx | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx index 21fee979ba1f0..c31daa6bb9083 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -1,7 +1,6 @@ /* eslint-disable react-compiler/react-compiler */ import type {ForwardedRef} from 'react'; import React, {useCallback, useContext, useEffect, useImperativeHandle, useRef, useState} from 'react'; - /* eslint-disable no-restricted-imports */ import type {EmitterSubscription, GestureResponderEvent, NativeTouchEvent, View} from 'react-native'; import {DeviceEventEmitter, Dimensions, InteractionManager} from 'react-native'; @@ -409,15 +408,16 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro shouldSetModalVisibility, }); - clearActiveReportAction(); - callbackWhenDeleteModalHide.current(); - if (result.action === ModalActions.CONFIRM) { onConfirm(); performDelete(); } else { onCancel(); } + + // Clear refs and run callbacks AFTER the action is performed + clearActiveReportAction(); + callbackWhenDeleteModalHide.current(); }, [showConfirmModal, translate, performDelete], ); diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index 9554472e834f7..b0319833ab1b2 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -588,6 +588,7 @@ function PureReportActionItem({ dismissError(); } }, [linkedTransactionRouteError, action, showDismissReceiptErrorModal, dismissError]); + useEffect( () => () => { // ReportActionContextMenu, EmojiPicker and PopoverReactionList are global components, From 5af21660718e24c1211ca39611e146bde0582d01 Mon Sep 17 00:00:00 2001 From: Faizan Shoukat Abbasi Date: Sat, 3 Jan 2026 06:01:39 +0500 Subject: [PATCH 3/3] Fixed prettier issues --- src/pages/home/report/PureReportActionItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index b0319833ab1b2..ac15e9fd987a2 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -588,7 +588,7 @@ function PureReportActionItem({ dismissError(); } }, [linkedTransactionRouteError, action, showDismissReceiptErrorModal, dismissError]); - + useEffect( () => () => { // ReportActionContextMenu, EmojiPicker and PopoverReactionList are global components,