Skip to content

Commit 8506820

Browse files
authored
Merge pull request Expensify#57566 from FitseTLT/fix-opening-another-report-while-context-menu-is-opening
Fix - Android - Chat - Context menu opened on expense report if tapping on expense before it opens
2 parents 88e5db7 + 392e3c4 commit 8506820

File tree

6 files changed

+40
-25
lines changed

6 files changed

+40
-25
lines changed

src/components/ReportActionItem/MoneyRequestAction.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
isSplitBillAction as isSplitBillActionReportActionsUtils,
1414
isTrackExpenseAction as isTrackExpenseActionReportActionsUtils,
1515
} from '@libs/ReportActionsUtils';
16+
import {contextMenuRef} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
1617
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
1718
import CONST from '@src/CONST';
1819
import type {TranslationPaths} from '@src/languages/types';
@@ -81,6 +82,9 @@ function MoneyRequestAction({
8182
const isTrackExpenseAction = isTrackExpenseActionReportActionsUtils(action);
8283

8384
const onMoneyRequestPreviewPressed = () => {
85+
if (contextMenuRef.current?.isContextMenuOpening) {
86+
return;
87+
}
8488
if (isSplitBillAction) {
8589
Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(chatReportID, action.reportActionID, Navigation.getReportRHPActiveRoute()));
8690
return;

src/components/ReportActionItem/ReportPreview.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import {
8080
isReceiptBeingScanned,
8181
shouldShowBrokenConnectionViolationForMultipleTransactions,
8282
} from '@libs/TransactionUtils';
83+
import {contextMenuRef} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
8384
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
8485
import variables from '@styles/variables';
8586
import {approveMoneyRequest, canApproveIOU, canIOUBePaid as canIOUBePaidIOUActions, canSubmitReport, payInvoice, payMoneyRequest, submitReport} from '@userActions/IOU';
@@ -501,7 +502,7 @@ function ReportPreview({
501502
}, [isApproved, isApprovedAnimationRunning, thumbsUpScale]);
502503

503504
const openReportFromPreview = useCallback(() => {
504-
if (!iouReportID) {
505+
if (!iouReportID || contextMenuRef.current?.isContextMenuOpening) {
505506
return;
506507
}
507508
Performance.markStart(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW);

src/libs/actions/Report.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1585,11 +1585,11 @@ function handleReportChanged(report: OnyxEntry<Report>) {
15851585
}
15861586

15871587
/** Deletes a comment from the report, basically sets it as empty string */
1588-
function deleteReportComment(reportID: string, reportAction: ReportAction) {
1588+
function deleteReportComment(reportID: string | undefined, reportAction: ReportAction) {
15891589
const originalReportID = getOriginalReportID(reportID, reportAction);
15901590
const reportActionID = reportAction.reportActionID;
15911591

1592-
if (!reportActionID || !originalReportID) {
1592+
if (!reportActionID || !originalReportID || !reportID) {
15931593
return;
15941594
}
15951595

src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ type BaseReportActionContextMenuProps = {
4646
reportID: string | undefined;
4747

4848
/** The ID of the report action this context menu is attached to. */
49-
reportActionID: string;
49+
reportActionID: string | undefined;
5050

5151
/** The ID of the original report from which the given reportAction is first created. */
5252
// originalReportID is used in withOnyx to get the reportActions for the original report
5353
// eslint-disable-next-line react/no-unused-prop-types
54-
originalReportID: string;
54+
originalReportID: string | undefined;
5555

5656
/**
5757
* If true, this component will be a small, row-oriented menu that displays icons but not text.
@@ -151,7 +151,7 @@ function BaseReportActionContextMenu({
151151
const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`);
152152

153153
const reportAction: OnyxEntry<ReportAction> = useMemo(() => {
154-
if (isEmptyObject(reportActions) || reportActionID === '0' || reportActionID === '-1') {
154+
if (isEmptyObject(reportActions) || reportActionID === '0' || reportActionID === '-1' || !reportActionID) {
155155
return;
156156
}
157157
return reportActions[reportActionID];

src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx

+28-19
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import type {OnyxEntry} from 'react-native-onyx';
99
import ConfirmModal from '@components/ConfirmModal';
1010
import PopoverWithMeasuredContent from '@components/PopoverWithMeasuredContent';
1111
import useLocalize from '@hooks/useLocalize';
12+
import {deleteMoneyRequest, deleteTrackExpense} from '@libs/actions/IOU';
13+
import {deleteReportComment} from '@libs/actions/Report';
1214
import calculateAnchorPosition from '@libs/calculateAnchorPosition';
13-
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
14-
import * as IOU from '@userActions/IOU';
15-
import * as Report from '@userActions/Report';
15+
import {getOriginalMessage, isMoneyRequestAction, isTrackExpenseAction} from '@libs/ReportActionsUtils';
16+
import CONST from '@src/CONST';
1617
import type {AnchorDimensions} from '@src/styles';
1718
import type {ReportAction} from '@src/types/onyx';
1819
import BaseReportActionContextMenu from './BaseReportActionContextMenu';
@@ -33,11 +34,11 @@ function extractPointerEvent(event: GestureResponderEvent | MouseEvent): MouseEv
3334

3435
function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<ReportActionContextMenu>) {
3536
const {translate} = useLocalize();
36-
const reportIDRef = useRef('-1');
37+
const reportIDRef = useRef<string | undefined>();
3738
const typeRef = useRef<ContextMenuType>();
3839
const reportActionRef = useRef<NonNullable<OnyxEntry<ReportAction>> | null>(null);
39-
const reportActionIDRef = useRef('-1');
40-
const originalReportIDRef = useRef('-1');
40+
const reportActionIDRef = useRef<string | undefined>();
41+
const originalReportIDRef = useRef<string | undefined>();
4142
const selectionRef = useRef('');
4243
const reportActionDraftMessageRef = useRef<string>();
4344

@@ -77,6 +78,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
7778
});
7879

7980
const onPopoverShow = useRef(() => {});
81+
const [isContextMenuOpening, setIsContextMenuOpening] = useState(false);
8082
const onPopoverHide = useRef(() => {});
8183
const onEmojiPickerToggle = useRef<undefined | ((state: boolean) => void)>();
8284
const onCancelDeleteModal = useRef(() => {});
@@ -132,7 +134,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
132134
!!actionID && (reportActionIDRef.current === actionID || reportActionRef.current?.reportActionID === actionID);
133135

134136
const clearActiveReportAction = () => {
135-
reportActionIDRef.current = '-1';
137+
reportActionIDRef.current = undefined;
136138
reportActionRef.current = null;
137139
};
138140

@@ -175,6 +177,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
175177
isOverflowMenu = false,
176178
isThreadReportParentActionParam = false,
177179
) => {
180+
setIsContextMenuOpening(true);
178181
const {pageX = 0, pageY = 0} = extractPointerEvent(event);
179182
contextMenuAnchorRef.current = contextMenuAnchor;
180183
contextMenuTargetNode.current = event.target as HTMLDivElement;
@@ -211,10 +214,10 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
211214
}).then(() => {
212215
setDisabledActions(disabledOptions);
213216
typeRef.current = type;
214-
reportIDRef.current = reportID ?? '-1';
215-
reportActionIDRef.current = reportActionID ?? '-1';
217+
reportIDRef.current = reportID;
218+
reportActionIDRef.current = reportActionID;
216219
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
217-
originalReportIDRef.current = originalReportID || '-1';
220+
originalReportIDRef.current = originalReportID || undefined;
218221
selectionRef.current = selection;
219222
setIsPopoverVisible(true);
220223
reportActionDraftMessageRef.current = draftMessage;
@@ -234,6 +237,11 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
234237

235238
// After we have called the action, reset it.
236239
onPopoverShow.current = () => {};
240+
241+
// After the context menu opening animation ends reset isContextMenuOpening.
242+
setTimeout(() => {
243+
setIsContextMenuOpening(false);
244+
}, CONST.ANIMATED_TRANSITION);
237245
};
238246

239247
/** Run the callback and return a noop function to reset it */
@@ -244,9 +252,9 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
244252

245253
/** After Popover hides, call the registered onPopoverHide & onPopoverHideActionCallback callback and reset it */
246254
const runAndResetOnPopoverHide = () => {
247-
reportIDRef.current = '-1';
248-
reportActionIDRef.current = '-1';
249-
originalReportIDRef.current = '-1';
255+
reportIDRef.current = undefined;
256+
reportActionIDRef.current = undefined;
257+
originalReportIDRef.current = undefined;
250258
setInstanceID('');
251259

252260
onPopoverHide.current = runAndResetCallback(onPopoverHide.current);
@@ -270,15 +278,15 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
270278
const confirmDeleteAndHideModal = useCallback(() => {
271279
callbackWhenDeleteModalHide.current = runAndResetCallback(onConfirmDeleteModal.current);
272280
const reportAction = reportActionRef.current;
273-
if (ReportActionsUtils.isMoneyRequestAction(reportAction)) {
274-
const originalMessage = ReportActionsUtils.getOriginalMessage(reportAction);
275-
if (ReportActionsUtils.isTrackExpenseAction(reportAction)) {
276-
IOU.deleteTrackExpense(reportIDRef.current, originalMessage?.IOUTransactionID ?? '-1', reportAction);
281+
if (isMoneyRequestAction(reportAction)) {
282+
const originalMessage = getOriginalMessage(reportAction);
283+
if (isTrackExpenseAction(reportAction)) {
284+
deleteTrackExpense(reportIDRef.current, originalMessage?.IOUTransactionID, reportAction);
277285
} else {
278-
IOU.deleteMoneyRequest(originalMessage?.IOUTransactionID ?? '-1', reportAction);
286+
deleteMoneyRequest(originalMessage?.IOUTransactionID, reportAction);
279287
}
280288
} else if (reportAction) {
281-
Report.deleteReportComment(reportIDRef.current, reportAction);
289+
deleteReportComment(reportIDRef.current, reportAction);
282290
}
283291

284292
DeviceEventEmitter.emit(`deletedReportAction_${reportIDRef.current}`, reportAction?.reportActionID);
@@ -317,6 +325,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
317325
runAndResetOnPopoverHide,
318326
clearActiveReportAction,
319327
contentRef,
328+
isContextMenuOpening,
320329
}));
321330

322331
const reportAction = reportActionRef.current;

src/pages/home/report/ContextMenu/ReportActionContextMenu.ts

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type ReportActionContextMenu = {
5050
runAndResetOnPopoverHide: () => void;
5151
clearActiveReportAction: () => void;
5252
contentRef: RefObject<View>;
53+
isContextMenuOpening: boolean;
5354
};
5455

5556
const contextMenuRef = React.createRef<ReportActionContextMenu>();

0 commit comments

Comments
 (0)