diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 8604d20130c7..2dae84106971 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -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; diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 3c93c3dc9d31..d9332efdc7a3 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -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, @@ -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; @@ -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, ''), + ]); } } } @@ -512,7 +516,9 @@ 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) { @@ -520,7 +526,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { (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), }); } @@ -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), diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index a5a033797c7b..3eb752bac983 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -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'; @@ -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 | 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; } /** diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0c1911401432..9404d832564a 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -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'; @@ -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), @@ -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; } diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index c4fad1a86906..0a776645a393 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -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; } diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 0fe6a528cda1..678e1fb967dd 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -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'; @@ -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, }; } diff --git a/src/pages/DetailsPage.js b/src/pages/DetailsPage.js index b0362a69b4d6..2fdab08e6675 100755 --- a/src/pages/DetailsPage.js +++ b/src/pages/DetailsPage.js @@ -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'; @@ -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; @@ -132,7 +134,7 @@ function DetailsPage(props) { )} - {Boolean(details.displayName) && ( + {Boolean(displayName) && ( - {details.displayName} + {displayName} )} {details.login ? ( @@ -194,7 +196,7 @@ function DetailsPage(props) { {!isCurrentUser && ( Report.navigateToAndOpenReport([login])} diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index b50798f2d856..0618f0ad2a9d 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -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'; @@ -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', ''); diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index e04ffbb352fc..fddf5176f815 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -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, diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js index d8e7dbdaf76e..27e1cd1da2e6 100644 --- a/src/pages/RoomMembersPage.js +++ b/src/pages/RoomMembersPage.js @@ -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'; @@ -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()}`; @@ -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: [ { diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.js b/src/pages/home/report/ReportActionCompose/SuggestionMention.js index e55b96ad99f5..af3074eec06d 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.js @@ -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'; @@ -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; } @@ -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: [ diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index a7972b97f5c1..1a163fcc9bca 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -368,7 +368,7 @@ function ReportActionItem(props) { ); } 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); @@ -416,7 +416,7 @@ function ReportActionItem(props) { ); } 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 = ; diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 9834d4e9e1c0..a7fe8b2f8a71 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -364,7 +364,7 @@ function WorkspaceMembersPage(props) { details.login === props.policy.owner || policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !_.isEmpty(policyMember.errors), - text: props.formatPhoneNumber(details.displayName), + text: props.formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(details)), alternateText: props.formatPhoneNumber(details.login), rightElement: isAdmin ? ( diff --git a/src/pages/workspace/WorkspacesListRow.tsx b/src/pages/workspace/WorkspacesListRow.tsx index 1a28ff47bbde..8bcc23faf550 100755 --- a/src/pages/workspace/WorkspacesListRow.tsx +++ b/src/pages/workspace/WorkspacesListRow.tsx @@ -127,7 +127,7 @@ function WorkspacesListRow({ numberOfLines={1} style={[styles.labelStrong]} > - {PersonalDetailsUtils.getDisplayNameOrDefault(ownerDetails.displayName)} + {PersonalDetailsUtils.getDisplayNameOrDefault(ownerDetails)}