Skip to content

Commit

Permalink
Merge pull request #32792 from paultsimura/fix/32127-merged-account
Browse files Browse the repository at this point in the history
fix: Handle merged account display name
  • Loading branch information
roryabraham authored Jan 3, 2024
2 parents a34c8cc + 13edc94 commit 5049f8c
Show file tree
Hide file tree
Showing 14 changed files with 52 additions and 40 deletions.
6 changes: 3 additions & 3 deletions src/components/ArchivedReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}}

const originalMessage = reportClosedAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED ? reportClosedAction.originalMessage : null;
const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT;
let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]?.displayName);
let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]);

let oldDisplayName: string | undefined;
if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) {
const newAccountID = originalMessage?.newAccountID;
const oldAccountID = originalMessage?.oldAccountID;
displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]?.displayName);
oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]?.displayName);
displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]);
oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]);
}

const shouldRenderHTML = archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT;
Expand Down
20 changes: 13 additions & 7 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ function isPersonalDetailsReady(personalDetails) {
function getParticipantsOption(participant, personalDetails) {
const detail = getPersonalDetailsForAccountIDs([participant.accountID], personalDetails)[participant.accountID];
const login = detail.login || participant.login;
const displayName = detail.displayName || LocalePhoneNumber.formatPhoneNumber(login);
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(detail, LocalePhoneNumber.formatPhoneNumber(login));
return {
keyForList: String(detail.accountID),
login,
Expand Down Expand Up @@ -247,7 +247,7 @@ function getParticipantNames(personalDetailList) {
participantNames.add(participant.lastName.toLowerCase());
}
if (participant.displayName) {
participantNames.add(participant.displayName.toLowerCase());
participantNames.add(PersonalDetailsUtils.getDisplayNameOrDefault(participant).toLowerCase());
}
});
return participantNames;
Expand Down Expand Up @@ -300,7 +300,11 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic
// The regex below is used to remove dots only from the local part of the user email (local-part@domain)
// so that we can match emails that have dots without explicitly writing the dots (e.g: fistlast@domain will match first.last@domain)
// More info https://github.com/Expensify/App/issues/8007
searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\.(?=[^\s@]*@)/g, '')]);
searchTerms = searchTerms.concat([
PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, '', false),
personalDetail.login,
personalDetail.login.replace(/\.(?=[^\s@]*@)/g, ''),
]);
}
}
}
Expand Down Expand Up @@ -512,15 +516,17 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
const lastMessageTextFromReport = getLastMessageTextForReport(report);
const lastActorDetails = personalDetailMap[report.lastActorAccountID] || null;
const lastActorDisplayName =
hasMultipleParticipants && lastActorDetails && lastActorDetails.accountID !== currentUserAccountID ? lastActorDetails.firstName || lastActorDetails.displayName : '';
hasMultipleParticipants && lastActorDetails && lastActorDetails.accountID !== currentUserAccountID
? lastActorDetails.firstName || PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails)
: '';
let lastMessageText = lastActorDisplayName ? `${lastActorDisplayName}: ${lastMessageTextFromReport}` : lastMessageTextFromReport;

if (result.isArchivedRoom) {
const archiveReason =
(lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason) ||
CONST.REPORT.ARCHIVE_REASON.DEFAULT;
lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, {
displayName: archiveReason.displayName || PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(lastActorDetails, 'displayName')),
displayName: archiveReason.displayName || PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails),
policyName: ReportUtils.getPolicyName(report),
});
}
Expand Down Expand Up @@ -1439,8 +1445,8 @@ function getSearchOptions(reports, personalDetails, searchValue = '', betas) {
function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail, amountText) {
const formattedLogin = LocalePhoneNumber.formatPhoneNumber(personalDetail.login);
return {
text: personalDetail.displayName || formattedLogin,
alternateText: formattedLogin || personalDetail.displayName,
text: PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, formattedLogin),
alternateText: formattedLogin || PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, '', false),
icons: [
{
source: UserUtils.getAvatar(personalDetail.avatar, personalDetail.accountID),
Expand Down
14 changes: 5 additions & 9 deletions src/libs/PersonalDetailsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Onyx, {OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import * as OnyxTypes from '@src/types/onyx';
import {PersonalDetails, PersonalDetailsList} from '@src/types/onyx';
Expand All @@ -16,15 +17,10 @@ Onyx.connect({
},
});

/**
* @param [defaultValue] optional default display name value
*/
function getDisplayNameOrDefault(displayName?: string, defaultValue = ''): string {
// Not using nullish coalescing as it differs from OR for strings. For example:
// '' || 'A' === 'A'
// '' ?? 'A' === ''
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
return displayName || defaultValue || Localize.translateLocal('common.hidden');
function getDisplayNameOrDefault(passedPersonalDetails?: Partial<PersonalDetails> | null, defaultValue = '', shouldFallbackToHidden = true): string {
const displayName = passedPersonalDetails?.displayName ? passedPersonalDetails.displayName.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, '') : '';
const fallbackValue = shouldFallbackToHidden ? Localize.translateLocal('common.hidden') : '';
return displayName || defaultValue || fallbackValue;
}

/**
Expand Down
13 changes: 8 additions & 5 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import linkingConfig from './Navigation/linkingConfig';
import Navigation from './Navigation/Navigation';
import * as NumberUtils from './NumberUtils';
import Permissions from './Permissions';
import * as PersonalDetailsUtils from './PersonalDetailsUtils';
import * as PolicyUtils from './PolicyUtils';
import * as ReportActionsUtils from './ReportActionsUtils';
import {LastVisibleMessage} from './ReportActionsUtils';
Expand Down Expand Up @@ -1326,7 +1327,7 @@ function getIcons(
const parentReportAction = ReportActionsUtils.getParentReportAction(report);

const actorAccountID = parentReportAction.actorAccountID;
const actorDisplayName = allPersonalDetails?.[actorAccountID ?? -1]?.displayName ?? '';
const actorDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(allPersonalDetails?.[actorAccountID ?? -1], '', false);
const actorIcon = {
id: actorAccountID,
source: UserUtils.getAvatar(personalDetails?.[actorAccountID ?? -1]?.avatar ?? '', actorAccountID ?? -1),
Expand Down Expand Up @@ -1450,13 +1451,15 @@ function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = f
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
return formattedLogin;
}
const longName = personalDetails.displayName ? personalDetails.displayName : formattedLogin;

const shortName = personalDetails.firstName ? personalDetails.firstName : longName;
const longName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails, formattedLogin, shouldFallbackToHidden);

if (!longName && shouldFallbackToHidden) {
return Localize.translateLocal('common.hidden');
// If the user's personal details (first name) should be hidden, make sure we return "hidden" instead of the short name
if (shouldFallbackToHidden && longName === Localize.translateLocal('common.hidden')) {
return longName;
}

const shortName = personalDetails.firstName ? personalDetails.firstName : longName;
return shouldUseShortForm ? shortName : longName;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ function getOptionData(
case CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED: {
lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, {
policyName: ReportUtils.getPolicyName(report, false, policy),
displayName: PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails?.displayName),
displayName: PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails),
});
break;
}
Expand Down
3 changes: 2 additions & 1 deletion src/libs/actions/Task.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as ErrorUtils from '@libs/ErrorUtils';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
Expand Down Expand Up @@ -668,7 +669,7 @@ function getAssignee(assigneeAccountID, personalDetails) {
}
return {
icons: ReportUtils.getIconsForParticipants([details.accountID], personalDetails),
displayName: details.displayName,
displayName: PersonalDetailsUtils.getDisplayNameOrDefault(details),
subtitle: details.login,
};
}
Expand Down
10 changes: 6 additions & 4 deletions src/pages/DetailsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import UserDetailsTooltip from '@components/UserDetailsTooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import * as Report from '@userActions/Report';
Expand Down Expand Up @@ -120,6 +121,7 @@ function DetailsPage(props) {

const phoneNumber = getPhoneNumber(details);
const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : details.login;
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(details, '', false);

const isCurrentUser = props.session.accountID === details.accountID;

Expand All @@ -132,7 +134,7 @@ function DetailsPage(props) {
<ScrollView>
<View style={styles.avatarSectionWrapper}>
<AttachmentModal
headerTitle={details.displayName}
headerTitle={displayName}
source={UserUtils.getFullSizeAvatar(details.avatar, details.accountID)}
isAuthTokenRequired
originalFileName={details.originalFileName}
Expand All @@ -156,12 +158,12 @@ function DetailsPage(props) {
</PressableWithoutFocus>
)}
</AttachmentModal>
{Boolean(details.displayName) && (
{Boolean(displayName) && (
<Text
style={[styles.textHeadline, styles.mb6, styles.pre]}
numberOfLines={1}
>
{details.displayName}
{displayName}
</Text>
)}
{details.login ? (
Expand Down Expand Up @@ -194,7 +196,7 @@ function DetailsPage(props) {
</View>
{!isCurrentUser && (
<MenuItem
title={`${props.translate('common.message')}${details.displayName}`}
title={`${props.translate('common.message')}${displayName}`}
titleStyle={styles.flex1}
icon={Expensicons.ChatBubble}
onPress={() => Report.navigateToAndOpenReport([login])}
Expand Down
3 changes: 2 additions & 1 deletion src/pages/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
Expand Down Expand Up @@ -99,7 +100,7 @@ function ProfilePage(props) {
const accountID = Number(lodashGet(props.route.params, 'accountID', 0));
const details = lodashGet(props.personalDetails, accountID, ValidationUtils.isValidAccountRoute(accountID) ? {} : {isloading: false});

const displayName = details.displayName ? details.displayName : props.translate('common.hidden');
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(details);
const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar());
const fallbackIcon = lodashGet(details, 'fallbackIcon', '');
const originalFileName = lodashGet(details, 'originalFileName', '');
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ReportParticipantsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const getAllParticipants = (report, personalDetails, translate) =>
.map((accountID, index) => {
const userPersonalDetail = lodashGet(personalDetails, accountID, {displayName: personalDetails.displayName || translate('common.hidden'), avatar: ''});
const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login || '') || translate('common.hidden');
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail.displayName);
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail);

return {
alternateText: userLogin,
Expand Down
5 changes: 3 additions & 2 deletions src/pages/RoomMembersPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import compose from '@libs/compose';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
Expand Down Expand Up @@ -194,7 +195,7 @@ function RoomMembersPage(props) {
memberDetails += ` ${details.lastName.toLowerCase()}`;
}
if (details.displayName) {
memberDetails += ` ${details.displayName.toLowerCase()}`;
memberDetails += ` ${PersonalDetailsUtils.getDisplayNameOrDefault(details).toLowerCase()}`;
}
if (details.phoneNumber) {
memberDetails += ` ${details.phoneNumber.toLowerCase()}`;
Expand All @@ -210,7 +211,7 @@ function RoomMembersPage(props) {
accountID: Number(accountID),
isSelected: _.contains(selectedMembers, Number(accountID)),
isDisabled: accountID === props.session.accountID,
text: props.formatPhoneNumber(details.displayName),
text: props.formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(details)),
alternateText: props.formatPhoneNumber(details.login),
icons: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {usePersonalDetails} from '@components/OnyxProvider';
import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as SuggestionsUtils from '@libs/SuggestionUtils';
import * as UserUtils from '@libs/UserUtils';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -149,7 +150,8 @@ function SuggestionMention({
if (!detail.login || detail.isOptimisticPersonalDetail) {
return false;
}
const displayText = detail.displayName === formatPhoneNumber(detail.login) ? detail.displayName : `${detail.displayName} ${detail.login}`;
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(detail);
const displayText = displayName === formatPhoneNumber(detail.login) ? displayName : `${displayName} ${detail.login}`;
if (searchValue && !displayText.toLowerCase().includes(searchValue.toLowerCase())) {
return false;
}
Expand All @@ -159,7 +161,7 @@ function SuggestionMention({
const sortedPersonalDetails = _.sortBy(filteredPersonalDetails, (detail) => detail.displayName || detail.login);
_.each(_.first(sortedPersonalDetails, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length), (detail) => {
suggestions.push({
text: detail.displayName,
text: PersonalDetailsUtils.getDisplayNameOrDefault(detail),
alternateText: formatPhoneNumber(detail.login),
login: detail.login,
icons: [
Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/report/ReportActionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ function ReportActionItem(props) {
</ShowContextMenuContext.Provider>
);
} else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED) {
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(personalDetails, [props.report.ownerAccountID, 'displayName']));
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(personalDetails, props.report.ownerAccountID));
const paymentType = lodashGet(props.action, 'originalMessage.paymentType', '');

const isSubmitterOfUnsettledReport = ReportUtils.isCurrentUserSubmitter(props.report.reportID) && !ReportUtils.isSettled(props.report.reportID);
Expand Down Expand Up @@ -416,7 +416,7 @@ function ReportActionItem(props) {
</ReportActionItemBasicMessage>
);
} else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTDEQUEUED) {
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(personalDetails, [props.report.ownerAccountID, 'displayName']));
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(personalDetails, props.report.ownerAccountID));
const amount = CurrencyUtils.convertToDisplayString(props.report.total, props.report.currency);

children = <ReportActionItemBasicMessage message={props.translate('iou.canceledRequest', {submitterDisplayName, amount})} />;
Expand Down
Loading

0 comments on commit 5049f8c

Please sign in to comment.