Skip to content

Commit 4672791

Browse files
authored
Merge pull request Expensify#88324 from callstack-internal/perf-send-message-phase-12
refactor: PureReportActionItem, ReportActionItemEmojiReactions
2 parents 43b4bf2 + 52ec734 commit 4672791

9 files changed

Lines changed: 62 additions & 151 deletions

src/components/Reactions/ReactionTooltipContent.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import React, {useMemo} from 'react';
1+
import React from 'react';
22
import {View} from 'react-native';
33
import Text from '@components/Text';
4-
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
54
import useLocalize from '@hooks/useLocalize';
65
import useThemeStyles from '@hooks/useThemeStyles';
6+
import {getLocalizedEmojiName} from '@libs/EmojiUtils';
77
import {getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
88

9-
type ReactionTooltipContentProps = Pick<WithCurrentUserPersonalDetailsProps, 'currentUserPersonalDetails'> & {
9+
type ReactionTooltipContentProps = {
1010
/**
1111
* A list of emoji codes to display in the tooltip.
1212
*/
@@ -21,15 +21,18 @@ type ReactionTooltipContentProps = Pick<WithCurrentUserPersonalDetailsProps, 'cu
2121
* A list of account IDs to display in the tooltip.
2222
*/
2323
accountIDs: number[];
24+
25+
/**
26+
* The account ID of the current user.
27+
*/
28+
currentUserAccountID: number;
2429
};
2530

26-
function ReactionTooltipContent({accountIDs, currentUserPersonalDetails, emojiCodes, emojiName}: ReactionTooltipContentProps) {
31+
function ReactionTooltipContent({accountIDs, emojiCodes, emojiName, currentUserAccountID}: ReactionTooltipContentProps) {
2732
const styles = useThemeStyles();
28-
const {translate} = useLocalize();
29-
const users = useMemo(
30-
() => getPersonalDetailsByIDs({accountIDs, currentUserAccountID: currentUserPersonalDetails.accountID, shouldChangeUserDisplayName: true}),
31-
[currentUserPersonalDetails.accountID, accountIDs],
32-
);
33+
const {translate, preferredLocale} = useLocalize();
34+
const users = getPersonalDetailsByIDs({accountIDs, currentUserAccountID, shouldChangeUserDisplayName: true});
35+
const localizedEmojiName = getLocalizedEmojiName(emojiName, preferredLocale);
3336

3437
const namesString = users
3538
.map((user) => user?.displayName)
@@ -51,7 +54,7 @@ function ReactionTooltipContent({accountIDs, currentUserPersonalDetails, emojiCo
5154

5255
<Text style={[styles.mt1, styles.textMicroBold, styles.textReactionSenders, styles.textAlignCenter]}>{namesString}</Text>
5356

54-
<Text style={[styles.textMicro, styles.fontColorReactionLabel]}>{`${translate('emojiReactions.reactedWith')} :${emojiName}:`}</Text>
57+
<Text style={[styles.textMicro, styles.fontColorReactionLabel]}>{`${translate('emojiReactions.reactedWith')} :${localizedEmojiName}:`}</Text>
5558
</View>
5659
);
5760
}

src/components/Reactions/ReportActionItemEmojiReactions.tsx

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,36 @@
11
import sortBy from 'lodash/sortBy';
22
import React, {useContext, useRef} from 'react';
3-
import {View} from 'react-native';
4-
import type {OnyxEntry} from 'react-native-onyx';
3+
import {InteractionManager, View} from 'react-native';
4+
import {importEmojiLocale} from '@assets/emojis';
55
import type {Emoji} from '@assets/emojis/types';
66
import OfflineWithFeedback from '@components/OfflineWithFeedback';
77
import Tooltip from '@components/Tooltip/PopoverAnchorTooltip';
8-
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
9-
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
8+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
9+
import useLocalize from '@hooks/useLocalize';
1010
import useOnyx from '@hooks/useOnyx';
1111
import useThemeStyles from '@hooks/useThemeStyles';
12-
import {getEmojiReactionDetails, getLocalizedEmojiName} from '@libs/EmojiUtils';
12+
import {getEmojiReactionDetails} from '@libs/EmojiUtils';
13+
import {hideContextMenu} from '@pages/inbox/report/ContextMenu/ReportActionContextMenu';
1314
import {ReactionListContext} from '@pages/inbox/ReportScreenContext';
1415
import type {ReactionListAnchor, ReactionListEvent} from '@pages/inbox/ReportScreenContext';
16+
import {toggleEmojiReaction} from '@userActions/Report';
17+
import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session';
1518
import CONST from '@src/CONST';
19+
import {isFullySupportedLocale} from '@src/CONST/LOCALES';
1620
import ONYXKEYS from '@src/ONYXKEYS';
17-
import type {Locale, ReportAction, ReportActionReactions} from '@src/types/onyx';
21+
import type {ReportAction, ReportActionReactions} from '@src/types/onyx';
1822
import type {PendingAction} from '@src/types/onyx/OnyxCommon';
23+
import {getEmptyObject} from '@src/types/utils/EmptyObject';
1924
import AddReactionBubble from './AddReactionBubble';
2025
import EmojiReactionBubble from './EmojiReactionBubble';
2126
import ReactionTooltipContent from './ReactionTooltipContent';
2227

23-
type ReportActionItemEmojiReactionsProps = WithCurrentUserPersonalDetailsProps & {
24-
/** All the emoji reactions for the report action. */
25-
emojiReactions: OnyxEntry<ReportActionReactions>;
26-
27-
/** The user's preferred locale. */
28-
preferredLocale?: OnyxEntry<Locale>;
29-
28+
type ReportActionItemEmojiReactionsProps = {
3029
/** The report action that these reactions are for */
3130
reportAction: ReportAction;
3231

33-
/**
34-
* Function to call when the user presses on an emoji.
35-
* This can also be an emoji the user already reacted with,
36-
* hence this function asks to toggle the reaction by emoji.
37-
*/
38-
toggleReaction: (emoji: Emoji, preferredSkinTone: number, ignoreSkinToneOnCompare?: boolean) => void;
32+
/** The ID of the chat report this action belongs to */
33+
reportID: string | undefined;
3934

4035
/** We disable reacting with emojis on report actions that have errors */
4136
shouldBlockReactions?: boolean;
@@ -77,30 +72,40 @@ type FormattedReaction = {
7772
setIsEmojiPickerActive?: (state: boolean) => void;
7873
};
7974

80-
function ReportActionItemEmojiReactions({
81-
reportAction,
82-
currentUserPersonalDetails,
83-
toggleReaction,
84-
emojiReactions = {},
85-
shouldBlockReactions = false,
86-
preferredLocale = CONST.LOCALES.DEFAULT,
87-
setIsEmojiPickerActive,
88-
}: ReportActionItemEmojiReactionsProps) {
75+
function ReportActionItemEmojiReactions({reportAction, reportID, shouldBlockReactions = false, setIsEmojiPickerActive}: ReportActionItemEmojiReactionsProps) {
8976
const styles = useThemeStyles();
77+
const {preferredLocale} = useLocalize();
78+
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
9079
const reactionListRef = useContext(ReactionListContext);
9180
const popoverReactionListAnchors = useRef<PopoverReactionListAnchors>({});
9281
const [preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE] = useOnyx(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE);
9382

9483
const reportActionID = reportAction.reportActionID;
84+
const [emojiReactions = getEmptyObject<ReportActionReactions>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
85+
86+
// Prime the locale emoji table when this action has reactions.
87+
// Skip the default locale since getLocalizedEmojiName never reads localeEmojis for it.
88+
if (preferredLocale && preferredLocale !== CONST.LOCALES.DEFAULT && emojiReactions !== CONST.EMPTY_OBJECT && isFullySupportedLocale(preferredLocale)) {
89+
importEmojiLocale(preferredLocale);
90+
}
91+
92+
const toggleReaction = (emoji: Emoji, skinTone: number, ignoreSkinToneOnCompare?: boolean) => {
93+
if (isAnonymousUser()) {
94+
hideContextMenu(false);
95+
96+
// eslint-disable-next-line @typescript-eslint/no-deprecated
97+
InteractionManager.runAfterInteractions(() => {
98+
signOutAndRedirectToSignIn();
99+
});
100+
return;
101+
}
102+
toggleEmojiReaction(reportID, reportAction, emoji, emojiReactions, skinTone, currentUserAccountID, ignoreSkinToneOnCompare);
103+
};
95104

96105
// Each emoji is sorted by the oldest timestamp of user reactions so that they will always appear in the same order for everyone
97106
const formattedReactions: Array<FormattedReaction | null> = sortBy(
98107
Object.entries(emojiReactions ?? {}).map(([emojiName, emojiReaction]) => {
99-
const {emoji, emojiCodes, reactionCount, hasUserReacted, userAccountIDs, oldestTimestamp} = getEmojiReactionDetails(
100-
emojiName,
101-
emojiReaction,
102-
currentUserPersonalDetails.accountID,
103-
);
108+
const {emoji, emojiCodes, reactionCount, hasUserReacted, userAccountIDs, oldestTimestamp} = getEmojiReactionDetails(emojiName, emojiReaction, currentUserAccountID);
104109

105110
if (reactionCount === 0) {
106111
return null;
@@ -138,14 +143,15 @@ function ReportActionItemEmojiReactions({
138143
if (reaction === null) {
139144
return;
140145
}
146+
141147
return (
142148
<Tooltip
143149
renderTooltipContent={() => (
144150
<ReactionTooltipContent
145-
emojiName={getLocalizedEmojiName(reaction.reactionEmojiName, preferredLocale)}
151+
emojiName={reaction.reactionEmojiName}
146152
emojiCodes={reaction.emojiCodes}
147153
accountIDs={reaction.userAccountIDs}
148-
currentUserPersonalDetails={currentUserPersonalDetails}
154+
currentUserAccountID={currentUserAccountID}
149155
/>
150156
)}
151157
renderTooltipContentKey={[...reaction.userAccountIDs.map(String), ...reaction.emojiCodes]}
@@ -184,4 +190,4 @@ function ReportActionItemEmojiReactions({
184190
);
185191
}
186192

187-
export default withCurrentUserPersonalDetails(ReportActionItemEmojiReactions);
193+
export default ReportActionItemEmojiReactions;

src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ function DuplicateTransactionItem({transaction, index, onPreviewPressed}: Duplic
4545

4646
const [draftMessage] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`);
4747

48-
const [emojiReactions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${action?.reportActionID}`);
49-
5048
const [linkedTransactionRouteError] = useOnyx(
5149
`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUTransactionID : undefined)}`,
5250
{
@@ -81,7 +79,6 @@ function DuplicateTransactionItem({transaction, index, onPreviewPressed}: Duplic
8179
isUserValidated={isUserValidated}
8280
personalDetails={personalDetails}
8381
draftMessage={matchingDraftMessage}
84-
emojiReactions={emojiReactions}
8582
linkedTransactionRouteError={linkedTransactionRouteError}
8683
userBillingFundID={userBillingFundID}
8784
isTryNewDotNVPDismissed={isTryNewDotNVPDismissed}

src/pages/inbox/report/PureReportActionItem.tsx

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import {deepEqual} from 'fast-equals';
44
import mapValues from 'lodash/mapValues';
55
import React, {memo, use, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
66
import type {GestureResponderEvent, TextInput} from 'react-native';
7-
import {InteractionManager, Keyboard, View} from 'react-native';
7+
import {Keyboard, View} from 'react-native';
88
import type {OnyxEntry} from 'react-native-onyx';
99
import type {ValueOf} from 'type-fest';
10-
import type {Emoji} from '@assets/emojis/types';
1110
import * as ActionSheetAwareScrollView from '@components/ActionSheetAwareScrollView';
1211
import Button from '@components/Button';
1312
import DisplayNames from '@components/DisplayNames';
@@ -128,7 +127,6 @@ import {openPersonalBankAccountSetupView} from '@userActions/BankAccounts';
128127
import type {IgnoreDirection} from '@userActions/ClearReportActionErrors';
129128
import {hideEmojiPicker, isActive} from '@userActions/EmojiPickerAction';
130129
import {createTransactionThreadReport, expandURLPreview} from '@userActions/Report';
131-
import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session';
132130
import CONST from '@src/CONST';
133131
import ONYXKEYS from '@src/ONYXKEYS';
134132
import ROUTES from '@src/ROUTES';
@@ -239,9 +237,6 @@ type PureReportActionItemProps = {
239237
/** The iou report associated with the linked report, if any */
240238
iouReportOfLinkedReport: OnyxEntry<OnyxTypes.Report>;
241239

242-
/** All the emoji reactions for the report action. */
243-
emojiReactions?: OnyxTypes.ReportActionReactions;
244-
245240
/** Linked transaction route error */
246241
linkedTransactionRouteError?: Errors;
247242

@@ -269,17 +264,6 @@ type PureReportActionItemProps = {
269264
/** Whether the room is a chronos report */
270265
isChronosReport?: boolean;
271266

272-
/** Function to toggle emoji reaction */
273-
toggleEmojiReaction?: (
274-
reportID: string | undefined,
275-
reportAction: OnyxTypes.ReportAction,
276-
reactionObject: Emoji,
277-
existingReactions: OnyxEntry<OnyxTypes.ReportActionReactions>,
278-
paramSkinTone: number,
279-
currentUserAccountID: number,
280-
ignoreSkinToneOnCompare: boolean | undefined,
281-
) => void;
282-
283267
/** Function to resolve actionable report mention whisper */
284268
resolveActionableReportMentionWhisper?: (
285269
report: OnyxEntry<OnyxTypes.Report>,
@@ -332,9 +316,6 @@ type PureReportActionItemProps = {
332316
/** Did the user dismiss trying out NewDot? If true, it means they prefer using OldDot */
333317
isTryNewDotNVPDismissed?: boolean;
334318

335-
/** Current user's account id */
336-
currentUserAccountID: number;
337-
338319
/** The bank account list */
339320
bankAccountList?: OnyxTypes.BankAccountList | undefined;
340321

@@ -379,7 +360,6 @@ function PureReportActionItem({
379360
taskReport,
380361
linkedReport,
381362
iouReportOfLinkedReport,
382-
emojiReactions,
383363
linkedTransactionRouteError,
384364
isUserValidated,
385365
parentReport,
@@ -389,7 +369,6 @@ function PureReportActionItem({
389369
deleteReportActionDraft = () => {},
390370
isArchivedRoom,
391371
isChronosReport,
392-
toggleEmojiReaction = () => {},
393372
resolveActionableReportMentionWhisper = () => {},
394373
resolveActionableMentionWhisper = () => {},
395374
isClosedExpenseReportWithNoExpenses,
@@ -402,7 +381,6 @@ function PureReportActionItem({
402381
shouldShowBorder,
403382
shouldHighlight = false,
404383
isTryNewDotNVPDismissed = false,
405-
currentUserAccountID,
406384
bankAccountList,
407385
reportNameValuePairsOrigin,
408386
reportNameValuePairsOriginalID,
@@ -684,13 +662,6 @@ function PureReportActionItem({
684662
],
685663
);
686664

687-
const toggleReaction = useCallback(
688-
(emoji: Emoji, preferredSkinTone: number, ignoreSkinToneOnCompare?: boolean) => {
689-
toggleEmojiReaction(reportID, action, emoji, emojiReactions, preferredSkinTone, currentUserAccountID, ignoreSkinToneOnCompare);
690-
},
691-
[reportID, action, emojiReactions, toggleEmojiReaction, currentUserAccountID],
692-
);
693-
694665
const contextMenuStateValue = useMemo(
695666
() => ({
696667
anchor: popoverAnchorRef.current,
@@ -1140,24 +1111,12 @@ function PureReportActionItem({
11401111
<LinkPreviewer linkMetadata={action.linkMetadata?.filter((item) => !isEmptyObject(item))} />
11411112
</View>
11421113
)}
1143-
{!isMessageDeleted(action) && (
1114+
{!isOnSearch && !isMessageDeleted(action) && (
11441115
<View style={draftMessageRightAlign}>
11451116
<ReportActionItemEmojiReactions
11461117
reportAction={action}
1147-
emojiReactions={isOnSearch ? {} : emojiReactions}
1118+
reportID={reportID}
11481119
shouldBlockReactions={hasErrors}
1149-
toggleReaction={(emoji, preferredSkinTone, ignoreSkinToneOnCompare) => {
1150-
if (isAnonymousUser()) {
1151-
hideContextMenu(false);
1152-
1153-
// eslint-disable-next-line @typescript-eslint/no-deprecated
1154-
InteractionManager.runAfterInteractions(() => {
1155-
signOutAndRedirectToSignIn();
1156-
});
1157-
} else {
1158-
toggleReaction(emoji, preferredSkinTone, ignoreSkinToneOnCompare);
1159-
}
1160-
}}
11611120
setIsEmojiPickerActive={setIsEmojiPickerActive}
11621121
/>
11631122
</View>
@@ -1473,7 +1432,6 @@ export default memo(PureReportActionItem, (prevProps, nextProps) => {
14731432
deepEqual(prevParentReportAction, nextParentReportAction) &&
14741433
prevProps.draftMessage === nextProps.draftMessage &&
14751434
prevProps.iouReport?.reportID === nextProps.iouReport?.reportID &&
1476-
deepEqual(prevProps.emojiReactions, nextProps.emojiReactions) &&
14771435
deepEqual(prevProps.linkedTransactionRouteError, nextProps.linkedTransactionRouteError) &&
14781436
prevProps.isUserValidated === nextProps.isUserValidated &&
14791437
prevProps.parentReport?.reportID === nextProps.parentReport?.reportID &&

0 commit comments

Comments
 (0)