Skip to content

Commit 3c70896

Browse files
authored
Merge pull request #87756 from callstack-internal/perf-send-message-phase-5
refactor: PureReportActionItem, add ModifiedExpenseContent and ReimbursementDeQueuedContent
2 parents ec523a1 + 55ffc9f commit 3c70896

8 files changed

Lines changed: 174 additions & 87 deletions

src/pages/inbox/report/PureReportActionItem.tsx

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ import {
7777
getIOUReportIDFromReportActionPreview,
7878
getOriginalMessage,
7979
getPlaidBalanceFailureMessage,
80-
getReimbursedMessage,
8180
getRenamedAction,
8281
getReportActionHtml,
8382
getReportActionMessage,
@@ -146,8 +145,11 @@ import ConfirmWhisperContent from './actionContents/ConfirmWhisperContent';
146145
import FraudAlertContent from './actionContents/FraudAlertContent';
147146
import JoinRequestContent from './actionContents/JoinRequestContent';
148147
import MentionWhisperContent from './actionContents/MentionWhisperContent';
148+
import ModifiedExpenseContent from './actionContents/ModifiedExpenseContent';
149149
import PaymentContent from './actionContents/PaymentContent';
150150
import PolicyChangeLogContent, {isHandledPolicyChangeLogAction} from './actionContents/PolicyChangeLogContent';
151+
import ReimbursedContent from './actionContents/ReimbursedContent';
152+
import ReimbursementDeQueuedContent from './actionContents/ReimbursementDeQueuedContent';
151153
import ReportMentionWhisperContent from './actionContents/ReportMentionWhisperContent';
152154
import SimpleMessageContent, {isSimpleMessageAction} from './actionContents/SimpleMessageContent';
153155
import {RestrictedReadOnlyContextMenuActions} from './ContextMenu/ContextMenuActions';
@@ -159,7 +161,6 @@ import ReportActionItemBasicMessage from './ReportActionItemBasicMessage';
159161
import ReportActionItemContentCreated from './ReportActionItemContentCreated';
160162
import ReportActionItemDraft from './ReportActionItemDraft';
161163
import ReportActionItemGrouped from './ReportActionItemGrouped';
162-
import ReportActionItemMessageWithExplain from './ReportActionItemMessageWithExplain';
163164
import ReportActionItemSingle from './ReportActionItemSingle';
164165
import ReportActionItemThread from './ReportActionItemThread';
165166
import TripSummary from './TripSummary';
@@ -306,12 +307,6 @@ type PureReportActionItemProps = {
306307
/** What missing payment method does this report action indicate, if any? */
307308
missingPaymentMethod?: MissingPaymentMethod | undefined;
308309

309-
/** Returns the preview message for `REIMBURSEMENT_DEQUEUED` or `REIMBURSEMENT_ACH_CANCELED` action */
310-
reimbursementDeQueuedOrCanceledActionMessage?: string;
311-
312-
/** The report action message when expense has been modified. */
313-
modifiedExpenseMessage?: string;
314-
315310
/** Gets all transactions on an IOU report with a receipt */
316311
getTransactionsWithReceipts?: (iouReportID: string | undefined) => OnyxTypes.Transaction[];
317312

@@ -406,8 +401,6 @@ function PureReportActionItem({
406401
isClosedExpenseReportWithNoExpenses,
407402
isCurrentUserTheOnlyParticipant = () => false,
408403
missingPaymentMethod,
409-
reimbursementDeQueuedOrCanceledActionMessage = '',
410-
modifiedExpenseMessage = '',
411404
getTransactionsWithReceipts = () => [],
412405
clearError = () => {},
413406
clearAllRelatedReportActionErrors = () => {},
@@ -915,12 +908,17 @@ function PureReportActionItem({
915908
</ReportActionItemBasicMessage>
916909
);
917910
} else if (isReimbursementDeQueuedOrCanceledAction(action)) {
918-
children = <ReportActionItemBasicMessage message={reimbursementDeQueuedOrCanceledActionMessage} />;
911+
children = (
912+
<ReimbursementDeQueuedContent
913+
action={action}
914+
report={report}
915+
/>
916+
);
919917
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) {
920918
children = (
921-
<ReportActionItemMessageWithExplain
922-
message={modifiedExpenseMessage}
919+
<ModifiedExpenseContent
923920
action={action}
921+
report={report}
924922
childReport={childReport}
925923
originalReport={originalReport}
926924
/>
@@ -944,7 +942,12 @@ function PureReportActionItem({
944942
/>
945943
);
946944
} else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.REIMBURSED)) {
947-
children = <ReportActionItemBasicMessage message={getReimbursedMessage(translate, action, report, currentUserAccountID)} />;
945+
children = (
946+
<ReimbursedContent
947+
action={action}
948+
report={report}
949+
/>
950+
);
948951
} else if (isSimpleMessageAction(action)) {
949952
children = <SimpleMessageContent action={action} />;
950953
} else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.FORWARDED)) {
@@ -1023,7 +1026,6 @@ function PureReportActionItem({
10231026
report={report}
10241027
originalReport={originalReport}
10251028
policy={policy}
1026-
currentUserAccountID={currentUserAccountID}
10271029
personalPolicyID={personalPolicyID}
10281030
originalReportID={originalReportID}
10291031
resolveActionableMentionWhisper={resolveActionableMentionWhisper}
@@ -1188,7 +1190,6 @@ function PureReportActionItem({
11881190
accountIDs={oldestFourAccountIDs}
11891191
onSecondaryInteraction={showPopover}
11901192
isActive={isReportActionActive && !isContextMenuActive}
1191-
currentUserAccountID={currentUserAccountID}
11921193
/>
11931194
</View>
11941195
)}
@@ -1501,8 +1502,6 @@ export default memo(PureReportActionItem, (prevProps, nextProps) => {
15011502
prevProps.isChronosReport === nextProps.isChronosReport &&
15021503
prevProps.isClosedExpenseReportWithNoExpenses === nextProps.isClosedExpenseReportWithNoExpenses &&
15031504
deepEqual(prevProps.missingPaymentMethod, nextProps.missingPaymentMethod) &&
1504-
prevProps.reimbursementDeQueuedOrCanceledActionMessage === nextProps.reimbursementDeQueuedOrCanceledActionMessage &&
1505-
prevProps.modifiedExpenseMessage === nextProps.modifiedExpenseMessage &&
15061505
prevProps.userBillingFundID === nextProps.userBillingFundID &&
15071506
deepEqual(prevProps.taskReport, nextProps.taskReport) &&
15081507
prevProps.shouldHighlight === nextProps.shouldHighlight &&

src/pages/inbox/report/ReportActionItem.tsx

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
import React, {useCallback} from 'react';
22
import type {OnyxEntry} from 'react-native-onyx';
33
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
4-
import useLocalize from '@hooks/useLocalize';
54
import useOnyx from '@hooks/useOnyx';
65
import useOriginalReportID from '@hooks/useOriginalReportID';
7-
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
86
import useReportIsArchived from '@hooks/useReportIsArchived';
97
import useReportTransactions from '@hooks/useReportTransactions';
108
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
11-
import {getForReportAction, getMovedReportID} from '@libs/ModifiedExpenseMessage';
129
import {getIOUReportIDFromReportActionPreview, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
1310
import {
1411
chatIncludesChronosWithID,
1512
getIndicatedMissingPaymentMethod,
16-
getReimbursementDeQueuedOrCanceledActionMessage,
1713
getTransactionsWithReceipts,
1814
isArchivedNonExpenseReport,
1915
isChatThread,
@@ -23,9 +19,8 @@ import {
2319
import {clearAllRelatedReportActionErrors} from '@userActions/ClearReportActionErrors';
2420
import {deleteReportActionDraft, resolveActionableMentionWhisper, resolveActionableReportMentionWhisper, toggleEmojiReaction} from '@userActions/Report';
2521
import {clearError} from '@userActions/Transaction';
26-
import CONST from '@src/CONST';
2722
import ONYXKEYS from '@src/ONYXKEYS';
28-
import type {PersonalDetailsList, ReportAction, ReportActionReactions, Transaction} from '@src/types/onyx';
23+
import type {PersonalDetailsList, ReportActionReactions, Transaction} from '@src/types/onyx';
2924
import type {PureReportActionItemProps} from './PureReportActionItem';
3025
import PureReportActionItem from './PureReportActionItem';
3126

@@ -68,27 +63,17 @@ function ReportActionItem({
6863
isTryNewDotNVPDismissed,
6964
...props
7065
}: ReportActionItemProps) {
71-
const {translate} = useLocalize();
7266
const reportID = report?.reportID;
7367
const originalMessage = getOriginalMessage(action);
7468
const originalReportID = useOriginalReportID(reportID, action);
7569
const isOriginalReportArchived = useReportIsArchived(originalReportID);
76-
const {accountID: currentUserAccountID, email: currentUserEmail} = useCurrentUserPersonalDetails();
77-
const {policyForMovingExpensesID} = usePolicyForMovingExpenses();
78-
// When an expense is moved from a self-DM to a workspace, the report's policyID is temporarily
79-
// set to a fake placeholder (CONST.POLICY.OWNER_EMAIL_FAKE). Looking up POLICY_TAGS with that
80-
// fake ID would return nothing, so we fall back to policyForMovingExpensesID (the actual
81-
// destination workspace) to fetch the correct tag list for display.
82-
const policyIDForTags = report?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE && policyForMovingExpensesID ? policyForMovingExpensesID : report?.policyID;
83-
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyIDForTags}`);
70+
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
8471
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
8572
const [betas] = useOnyx(ONYXKEYS.BETAS);
8673
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`);
8774
const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`);
8875
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getIOUReportIDFromReportActionPreview(action)}`);
8976
const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`);
90-
const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(action, CONST.REPORT.MOVE_TYPE.FROM)}`);
91-
const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(action, CONST.REPORT.MOVE_TYPE.TO)}`);
9277

9378
const taskReportID = originalMessage && 'taskReportID' in originalMessage ? originalMessage.taskReportID : undefined;
9479
const [taskReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`);
@@ -149,20 +134,6 @@ function ReportActionItem({
149134
isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses(iouReport, transactionsOnIOUReport)}
150135
isCurrentUserTheOnlyParticipant={isCurrentUserTheOnlyParticipant}
151136
missingPaymentMethod={missingPaymentMethod}
152-
reimbursementDeQueuedOrCanceledActionMessage={getReimbursementDeQueuedOrCanceledActionMessage(
153-
translate,
154-
action as OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_DEQUEUED | typeof CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_ACH_CANCELED>>,
155-
report,
156-
)}
157-
modifiedExpenseMessage={getForReportAction({
158-
translate,
159-
reportAction: action,
160-
policy,
161-
movedFromReport,
162-
movedToReport,
163-
policyTags: policyTags ?? CONST.POLICY.DEFAULT_TAG_LIST,
164-
currentUserLogin: currentUserEmail ?? '',
165-
})}
166137
getTransactionsWithReceipts={getTransactionsWithReceipts}
167138
clearError={clearError}
168139
clearAllRelatedReportActionErrors={clearAllRelatedReportActionErrors}

src/pages/inbox/report/ReportActionItemThread.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {OnyxEntry} from 'react-native-onyx';
55
import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
66
import ReportActionAvatars from '@components/ReportActionAvatars';
77
import Text from '@components/Text';
8+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
89
import useLocalize from '@hooks/useLocalize';
910
import useOnyx from '@hooks/useOnyx';
1011
import useThemeStyles from '@hooks/useThemeStyles';
@@ -37,24 +38,11 @@ type ReportActionItemThreadProps = {
3738

3839
/** The function that should be called when the thread is LongPressed or right-clicked */
3940
onSecondaryInteraction: (event: GestureResponderEvent | MouseEvent) => void;
40-
41-
/** The accountID of the current user, used for creating optimistic report if needed */
42-
currentUserAccountID: number;
4341
};
4442

45-
function ReportActionItemThread({
46-
numberOfReplies,
47-
accountIDs,
48-
mostRecentReply,
49-
report,
50-
reportAction,
51-
isHovered,
52-
onSecondaryInteraction,
53-
isActive,
54-
currentUserAccountID,
55-
}: ReportActionItemThreadProps) {
43+
function ReportActionItemThread({numberOfReplies, accountIDs, mostRecentReply, report, reportAction, isHovered, onSecondaryInteraction, isActive}: ReportActionItemThreadProps) {
5644
const styles = useThemeStyles();
57-
45+
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
5846
const {translate, datetimeToCalendarTime} = useLocalize();
5947
const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportAction.childReportID}`);
6048
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);

src/pages/inbox/report/actionContents/MentionWhisperContent.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {ValueOf} from 'type-fest';
44
import RenderHTML from '@components/RenderHTML';
55
import type {ActionableItem} from '@components/ReportActionItem/ActionableItemButtons';
66
import ActionableItemButtons from '@components/ReportActionItem/ActionableItemButtons';
7+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
78
import useLocalize from '@hooks/useLocalize';
89
import useReportIsArchived from '@hooks/useReportIsArchived';
910
import {isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
@@ -17,7 +18,6 @@ type MentionWhisperContentProps = {
1718
report: OnyxEntry<Report>;
1819
originalReport: OnyxEntry<Report>;
1920
policy: OnyxEntry<Policy>;
20-
currentUserAccountID: number;
2121
personalPolicyID: string | undefined;
2222
originalReportID: string | undefined;
2323
resolveActionableMentionWhisper: (
@@ -28,18 +28,10 @@ type MentionWhisperContentProps = {
2828
) => void;
2929
};
3030

31-
function MentionWhisperContent({
32-
action,
33-
report,
34-
originalReport,
35-
policy,
36-
currentUserAccountID,
37-
personalPolicyID,
38-
originalReportID,
39-
resolveActionableMentionWhisper,
40-
}: MentionWhisperContentProps) {
31+
function MentionWhisperContent({action, report, originalReport, policy, personalPolicyID, originalReportID, resolveActionableMentionWhisper}: MentionWhisperContentProps) {
4132
const {translate} = useLocalize();
4233
const isOriginalReportArchived = useReportIsArchived(originalReportID);
34+
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
4335

4436
const reportActionReport = originalReport ?? report;
4537
const reportPolicyID = report?.policyID;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import type {OnyxEntry} from 'react-native-onyx';
3+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
4+
import useLocalize from '@hooks/useLocalize';
5+
import useOnyx from '@hooks/useOnyx';
6+
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
7+
import {getForReportAction, getMovedReportID} from '@libs/ModifiedExpenseMessage';
8+
import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
9+
import CONST from '@src/CONST';
10+
import ONYXKEYS from '@src/ONYXKEYS';
11+
import type {Report, ReportAction} from '@src/types/onyx';
12+
13+
type ModifiedExpenseContentProps = {
14+
action: ReportAction;
15+
report: OnyxEntry<Report>;
16+
childReport: OnyxEntry<Report>;
17+
originalReport: OnyxEntry<Report>;
18+
};
19+
20+
function ModifiedExpenseContent({action, report, childReport, originalReport}: ModifiedExpenseContentProps) {
21+
const {translate} = useLocalize();
22+
const {email: currentUserEmail} = useCurrentUserPersonalDetails();
23+
const {policyForMovingExpensesID} = usePolicyForMovingExpenses();
24+
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`);
25+
26+
// When expense is moved from self-DM to workspace, policyID is temporarily OWNER_EMAIL_FAKE.
27+
// Fall back to policyForMovingExpensesID (actual destination workspace) for correct tag list.
28+
const policyIDForTags = report?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE && policyForMovingExpensesID ? policyForMovingExpensesID : report?.policyID;
29+
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyIDForTags}`);
30+
const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(action, CONST.REPORT.MOVE_TYPE.FROM)}`);
31+
const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(action, CONST.REPORT.MOVE_TYPE.TO)}`);
32+
33+
const modifiedExpenseMessage = getForReportAction({
34+
translate,
35+
reportAction: action,
36+
policy,
37+
movedFromReport,
38+
movedToReport,
39+
policyTags: policyTags ?? CONST.POLICY.DEFAULT_TAG_LIST,
40+
currentUserLogin: currentUserEmail ?? '',
41+
});
42+
43+
return (
44+
<ReportActionItemMessageWithExplain
45+
message={modifiedExpenseMessage}
46+
action={action}
47+
childReport={childReport}
48+
originalReport={originalReport}
49+
/>
50+
);
51+
}
52+
53+
ModifiedExpenseContent.displayName = 'ModifiedExpenseContent';
54+
55+
export default ModifiedExpenseContent;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import type {OnyxEntry} from 'react-native-onyx';
3+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
4+
import useLocalize from '@hooks/useLocalize';
5+
import {getReimbursedMessage} from '@libs/ReportActionsUtils';
6+
import ReportActionItemBasicMessage from '@pages/inbox/report/ReportActionItemBasicMessage';
7+
import type {Report, ReportAction} from '@src/types/onyx';
8+
9+
type ReimbursedContentProps = {
10+
action: ReportAction;
11+
report: OnyxEntry<Report>;
12+
};
13+
14+
function ReimbursedContent({action, report}: ReimbursedContentProps) {
15+
const {translate} = useLocalize();
16+
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
17+
const message = getReimbursedMessage(translate, action, report, currentUserAccountID);
18+
19+
return <ReportActionItemBasicMessage message={message} />;
20+
}
21+
22+
ReimbursedContent.displayName = 'ReimbursedContent';
23+
24+
export default ReimbursedContent;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import type {OnyxEntry} from 'react-native-onyx';
3+
import useLocalize from '@hooks/useLocalize';
4+
import {getReimbursementDeQueuedOrCanceledActionMessage} from '@libs/ReportUtils';
5+
import ReportActionItemBasicMessage from '@pages/inbox/report/ReportActionItemBasicMessage';
6+
import type CONST from '@src/CONST';
7+
import type {Report, ReportAction} from '@src/types/onyx';
8+
9+
type ReimbursementDeQueuedContentProps = {
10+
action: ReportAction;
11+
report: OnyxEntry<Report>;
12+
};
13+
14+
function ReimbursementDeQueuedContent({action, report}: ReimbursementDeQueuedContentProps) {
15+
const {translate} = useLocalize();
16+
const message = getReimbursementDeQueuedOrCanceledActionMessage(
17+
translate,
18+
action as OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_DEQUEUED | typeof CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_ACH_CANCELED>>,
19+
report,
20+
);
21+
22+
return <ReportActionItemBasicMessage message={message} />;
23+
}
24+
25+
ReimbursementDeQueuedContent.displayName = 'ReimbursementDeQueuedContent';
26+
27+
export default ReimbursementDeQueuedContent;

0 commit comments

Comments
 (0)