Skip to content
21 changes: 15 additions & 6 deletions src/components/Reactions/ReactionTooltipContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my K2

import useThemeStyles from '@hooks/useThemeStyles';
import {getLocalizedEmojiName} from '@libs/EmojiUtils';
import {getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import {personalDetailsWithCustomNameSelector} from '@src/selectors/PersonalDetails';

type ReactionTooltipContentProps = {
/**
Expand All @@ -31,13 +33,20 @@ type ReactionTooltipContentProps = {
function ReactionTooltipContent({accountIDs, emojiCodes, emojiName, currentUserAccountID}: ReactionTooltipContentProps) {
const styles = useThemeStyles();
const {translate, preferredLocale} = useLocalize();
const users = getPersonalDetailsByIDs({accountIDs, currentUserAccountID, shouldChangeUserDisplayName: true});
const [users] = useOnyx(
ONYXKEYS.PERSONAL_DETAILS_LIST,
{
selector: personalDetailsWithCustomNameSelector({accountIDs, shouldChangeUserDisplayName: true, currentUserAccountID, translate}),
},
[accountIDs, currentUserAccountID, translate],
);
const localizedEmojiName = getLocalizedEmojiName(emojiName, preferredLocale);

const namesString = users
.map((user) => user?.displayName)
.filter((name) => name)
.join(', ');
const namesString =
users
?.map((user) => user?.displayName)
.filter((name) => name)
.join(', ') ?? '';

return (
<View style={[styles.alignItemsCenter, styles.ph2]}>
Expand Down
46 changes: 42 additions & 4 deletions src/libs/PersonalDetailsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Str} from 'expensify-common';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {LocaleContextProps} from '@components/LocaleContextProvider';
import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxInputOrEntry, PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx';
Expand All @@ -19,15 +19,15 @@ type FirstAndLastName = {
lastName: string;
};

let personalDetails: Array<PersonalDetails | null> = [];
let deprecatedPersonalDetails: Array<PersonalDetails | null> = [];
let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
let emailToPersonalDetailsCache: Record<string, PersonalDetails> = {};
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (val) => {
personalDetails = Object.values(val ?? {});
deprecatedPersonalDetails = Object.values(val ?? {});
allPersonalDetails = val;
emailToPersonalDetailsCache = personalDetails.reduce((acc: Record<string, PersonalDetails>, detail) => {
emailToPersonalDetailsCache = deprecatedPersonalDetails.reduce((acc: Record<string, PersonalDetails>, detail) => {
if (detail?.login) {
acc[detail.login.toLowerCase()] = detail;
}
Expand Down Expand Up @@ -136,6 +136,43 @@ function getPersonalDetailsByIDs({
return result;
}

function newGetPersonalDetailsByIDs(params: {
accountIDs: number[];
personalDetails: OnyxEntry<PersonalDetailsList>;
shouldChangeUserDisplayName: true;
currentUserAccountID: number | undefined;
translate: LocalizedTranslate;
}): PersonalDetails[];
function newGetPersonalDetailsByIDs(params: {accountIDs: number[]; personalDetails: OnyxEntry<PersonalDetailsList>; shouldChangeUserDisplayName?: false}): PersonalDetails[];
function newGetPersonalDetailsByIDs({
accountIDs,
personalDetails,
currentUserAccountID,
shouldChangeUserDisplayName = false,
translate,
}: {
accountIDs: number[];
personalDetails: OnyxEntry<PersonalDetailsList>;
currentUserAccountID?: number;
shouldChangeUserDisplayName?: boolean;
translate?: LocalizedTranslate;
}): PersonalDetails[] {
const result: PersonalDetails[] = [];
for (const accountID of accountIDs) {
const detail = personalDetails?.[accountID];
if (!detail) {
continue;
}

if (shouldChangeUserDisplayName && currentUserAccountID === detail.accountID && translate) {
result.push({...detail, displayName: translate('common.you')});
} else {
result.push(detail);
}
}
return result;
}

function getPersonalDetailByEmail(email: string | undefined): PersonalDetails | undefined {
if (!email) {
return undefined;
Expand Down Expand Up @@ -458,6 +495,7 @@ function areTravelPersonalDetailsMissing(privatePersonalDetails: OnyxEntry<Priva
export {
getDisplayNameOrDefault,
getPersonalDetailsByIDs,
newGetPersonalDetailsByIDs,
getPersonalDetailByEmail,
getAccountIDsByLogins,
getLoginsByAccountIDs,
Expand Down
7 changes: 5 additions & 2 deletions src/pages/ReportParticipantsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ParticipantsNavigatorParamList} from '@libs/Navigation/types';
import {isSearchStringMatchUserDetails} from '@libs/OptionsListUtils';
import {getDisplayNameOrDefault, getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
import {getReportName} from '@libs/ReportNameUtils';
import {
getReportPersonalDetailsParticipants,
Expand All @@ -56,6 +56,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import {personalDetailsSelector} from '@src/selectors/PersonalDetails';
import type {PersonalDetails} from '@src/types/onyx';
import type {WithReportOrNotFoundProps} from './inbox/report/withReportOrNotFound';
import withReportOrNotFound from './inbox/report/withReportOrNotFound';
Expand Down Expand Up @@ -106,6 +107,8 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) {
};

const [selectedMembers, setSelectedMembers] = useFilteredSelection(personalDetailsParticipants, filterParticipants);
const firstSelectedMember = selectedMembers?.at(0);
const [firstSelectedMemberDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: personalDetailsSelector(firstSelectedMember)});

// Get the active chat members by filtering out the pending members with delete action
const activeParticipants = participantsForDisplay.filter((participant) => isOffline || !participant.isPendingDelete);
Expand Down Expand Up @@ -183,7 +186,7 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) {
title: translate('workspace.people.removeMembersTitle', {count: selectedMembers.length}),
prompt: translate('workspace.people.removeMembersPrompt', {
count: selectedMembers.length,
memberName: formatPhoneNumber(getPersonalDetailsByIDs({accountIDs: selectedMembers, currentUserAccountID}).at(0)?.displayName ?? ''),
memberName: formatPhoneNumber(firstSelectedMemberDetails?.displayName ?? ''),
}),
confirmText: translate('common.remove'),
cancelText: translate('common.cancel'),
Expand Down
16 changes: 8 additions & 8 deletions src/pages/RoomMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import TableListItem from '@components/SelectionList/ListItem/TableListItem';
import type {ListItem} from '@components/SelectionList/types';
import SelectionListWithModal from '@components/SelectionListWithModal';
import Text from '@components/Text';
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import useConfirmModal from '@hooks/useConfirmModal';
import useFilteredSelection from '@hooks/useFilteredSelection';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
Expand All @@ -36,7 +34,7 @@ import type {PlatformStackRouteProp, PlatformStackScreenProps} from '@libs/Navig
import type {RoomMembersNavigatorParamList} from '@libs/Navigation/types';
import {isPersonalDetailsReady, isSearchStringMatchUserDetails} from '@libs/OptionsListUtils';
import Parser from '@libs/Parser';
import {getDisplayNameOrDefault, getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
import {isPolicyAdmin, isPolicyEmployee as isPolicyEmployeeUtils} from '@libs/PolicyUtils';
import {getReportAction} from '@libs/ReportActionsUtils';
import {getReportName} from '@libs/ReportNameUtils';
Expand All @@ -55,12 +53,13 @@ import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import {personalDetailsSelector} from '@src/selectors/PersonalDetails';
import type {PersonalDetails} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {WithReportOrNotFoundProps} from './inbox/report/withReportOrNotFound';
import withReportOrNotFound from './inbox/report/withReportOrNotFound';

type RoomMembersPageProps = WithReportOrNotFoundProps & WithCurrentUserPersonalDetailsProps & PlatformStackScreenProps<RoomMembersNavigatorParamList, typeof SCREENS.ROOM_MEMBERS.ROOT>;
type RoomMembersPageProps = WithReportOrNotFoundProps & PlatformStackScreenProps<RoomMembersNavigatorParamList, typeof SCREENS.ROOM_MEMBERS.ROOT>;

function RoomMembersPage({report, policy}: RoomMembersPageProps) {
const route = useRoute<PlatformStackRouteProp<RoomMembersNavigatorParamList, typeof SCREENS.ROOM_MEMBERS.ROOT>>();
Expand All @@ -71,7 +70,6 @@ function RoomMembersPage({report, policy}: RoomMembersPageProps) {
const reportAttributes = useReportAttributes();
const [session] = useOnyx(ONYXKEYS.SESSION);
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`);
const currentUserAccountID = Number(session?.accountID);
const {formatPhoneNumber, translate, localeCompare} = useLocalize();
const {showConfirmModal} = useConfirmModal();
const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE);
Expand Down Expand Up @@ -105,6 +103,8 @@ function RoomMembersPage({report, policy}: RoomMembersPageProps) {
);

const [selectedMembers, setSelectedMembers] = useFilteredSelection(personalDetailsParticipants, shouldIncludeMember);
const firstSelectedMember = selectedMembers?.at(0);
const [firstSelectedMemberDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: personalDetailsSelector(firstSelectedMember)});

const isFocusedScreen = useIsFocused();
const {isOffline} = useNetwork();
Expand Down Expand Up @@ -163,7 +163,7 @@ function RoomMembersPage({report, policy}: RoomMembersPageProps) {
title: translate('workspace.people.removeMembersTitle', {count: selectedMembers.length}),
prompt: translate('roomMembersPage.removeMembersPrompt', {
count: selectedMembers.length,
memberName: formatPhoneNumber(getPersonalDetailsByIDs({accountIDs: selectedMembers, currentUserAccountID}).at(0)?.displayName ?? ''),
memberName: formatPhoneNumber(firstSelectedMemberDetails?.displayName ?? ''),
}),
confirmText: translate('common.remove'),
cancelText: translate('common.cancel'),
Expand All @@ -173,7 +173,7 @@ function RoomMembersPage({report, policy}: RoomMembersPageProps) {
return;
}
removeUsers();
}, [showConfirmModal, translate, selectedMembers, formatPhoneNumber, currentUserAccountID, removeUsers]);
}, [showConfirmModal, translate, selectedMembers.length, formatPhoneNumber, firstSelectedMemberDetails?.displayName, removeUsers]);

/**
* Add user from the selectedMembers list
Expand Down Expand Up @@ -481,4 +481,4 @@ function RoomMembersPage({report, policy}: RoomMembersPageProps) {
);
}

export default withReportOrNotFound()(withCurrentUserPersonalDetails(RoomMembersPage));
export default withReportOrNotFound()(RoomMembersPage);
6 changes: 3 additions & 3 deletions src/pages/domain/Members/DomainAddMemberPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {addErrorMessage} from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import {getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import {isValidEmail} from '@libs/ValidationUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
import DomainNotFoundPageWrapper from '@pages/domain/DomainNotFoundPageWrapper';
Expand All @@ -23,6 +22,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import {defaultSecurityGroupIDSelector, domainNameSelector, memberAccountIDsSelector} from '@src/selectors/Domain';
import {personalDetailsWithCustomNameSelector} from '@src/selectors/PersonalDetails';
import INPUT_IDS from '@src/types/form/AddDomainMemberForm';
import type {Errors} from '@src/types/onyx/OnyxCommon';
import getEmptyArray from '@src/types/utils/getEmptyArray';
Expand Down Expand Up @@ -53,7 +53,7 @@ function DomainAddMemberPage({route}: DomainAddMemberProps) {
const [memberIDs = getEmptyArray<number>()] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${domainAccountID}`, {
selector: memberAccountIDsSelector,
});
const personalDetails = getPersonalDetailsByIDs({accountIDs: memberIDs});
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: personalDetailsWithCustomNameSelector({accountIDs: memberIDs})}, [memberIDs]);
const [domainName] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${domainAccountID}`, {selector: domainNameSelector});
const [defaultSecurityGroupID] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${domainAccountID}`, {selector: defaultSecurityGroupIDSelector});

Expand All @@ -80,7 +80,7 @@ function DomainAddMemberPage({route}: DomainAddMemberProps) {
addErrorMessage(errors, 'email', translate('common.error.characterLimitExceedCounter', fullEmail.length, CONST.LOGIN_CHARACTER_LIMIT));
}

const isUserAlreadyAMember = !!values.email && personalDetails.some(({login}) => login?.toLowerCase() === fullEmail.toLowerCase());
const isUserAlreadyAMember = !!values.email && personalDetails?.some(({login}) => login?.toLowerCase() === fullEmail.toLowerCase());
const isEmailInvalid = !!domainName && !!values.email && !isValidEmail(fullEmail);

if (isEmailInvalid) {
Expand Down
15 changes: 13 additions & 2 deletions src/pages/inbox/report/ReactionList/PopoverReactionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import React, {useEffect} from 'react';
import type {RefObject} from 'react';
import PopoverWithMeasuredContent from '@components/PopoverWithMeasuredContent';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import {getEmojiReactionDetails} from '@libs/EmojiUtils';
import {getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import type {ReactionListAnchor} from '@pages/inbox/ReportScreenContext';
import ONYXKEYS from '@src/ONYXKEYS';
import {personalDetailsWithCustomNameSelector} from '@src/selectors/PersonalDetails';
import type {PersonalDetails} from '@src/types/onyx';
import getEmptyArray from '@src/types/utils/getEmptyArray';
import BaseReactionList from './BaseReactionList';

type PopoverReactionListProps = {
Expand All @@ -19,14 +22,22 @@ type PopoverReactionListProps = {
};

function PopoverReactionList({isVisible, emojiName, reportActionID, anchorPosition, anchorRef, onClose}: PopoverReactionListProps) {
const {translate} = useLocalize();
const {accountID} = useCurrentUserPersonalDetails();

const [emojiReactions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);

const selectedReaction = emojiReactions?.[emojiName];
const isReady = !!selectedReaction;
const {emojiCodes = [], reactionCount = 0, hasUserReacted = false, userAccountIDs = []} = selectedReaction ? getEmojiReactionDetails(emojiName, selectedReaction, accountID) : {};
const users = isReady ? getPersonalDetailsByIDs({accountIDs: userAccountIDs, currentUserAccountID: accountID, shouldChangeUserDisplayName: true}) : [];

const [users = getEmptyArray<PersonalDetails>()] = useOnyx(
ONYXKEYS.PERSONAL_DETAILS_LIST,
{
selector: isReady ? personalDetailsWithCustomNameSelector({accountIDs: userAccountIDs, currentUserAccountID: accountID, shouldChangeUserDisplayName: true, translate}) : () => [],
},
[userAccountIDs, accountID, translate],
);

// Hide the list when all reactions are removed
useEffect(() => {
Expand Down
7 changes: 3 additions & 4 deletions src/pages/workspace/WorkspaceMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
import {isPersonalDetailsReady, sortAlphabetically} from '@libs/OptionsListUtils';
import {getDisplayNameOrDefault, getPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import {getDisplayNameOrDefault, newGetPersonalDetailsByIDs} from '@libs/PersonalDetailsUtils';
import {
canEditWorkspaceSettings,
getConnectionExporters,
Expand Down Expand Up @@ -168,7 +168,6 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
const [invitedEmailsToAccountIDsDraft] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT}${route.params.policyID.toString()}`);
const isMobileSelectionModeEnabled = useMobileSelectionMode();
const [session] = useOnyx(ONYXKEYS.SESSION);
const currentUserAccountID = Number(session?.accountID);
const selectionListRef = useRef<SelectionListHandle<MemberOption>>(null);
const isFocused = useIsFocused();
const policyID = route.params.policyID;
Expand Down Expand Up @@ -214,9 +213,9 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
const firstSelectedEmployeeAccountID = policyMemberEmailsToAccountIDs[selectedEmployees[0]];
return translate('workspace.people.removeMembersPrompt', {
count: selectedEmployees.length,
memberName: formatPhoneNumber(getPersonalDetailsByIDs({accountIDs: [firstSelectedEmployeeAccountID], currentUserAccountID}).at(0)?.displayName ?? ''),
memberName: formatPhoneNumber(newGetPersonalDetailsByIDs({accountIDs: [firstSelectedEmployeeAccountID], personalDetails}).at(0)?.displayName ?? ''),
});
}, [selectedEmployees, policyMemberEmailsToAccountIDs, translate, policy, formatPhoneNumber, currentUserAccountID]);
}, [selectedEmployees, policyMemberEmailsToAccountIDs, translate, policy, formatPhoneNumber, personalDetails]);
/**
* Get members for the current workspace
*/
Expand Down
Loading
Loading