diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx index f2e38ccb74af..5d8c0f6ef81e 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx @@ -1,3 +1,4 @@ +import cloneDeep from 'lodash/cloneDeep'; import isEmpty from 'lodash/isEmpty'; import React from 'react'; import {StyleSheet} from 'react-native'; @@ -13,12 +14,14 @@ import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentU import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; +import * as LoginUtils from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {Route} from '@src/ROUTES'; +import asMutable from '@src/types/utils/asMutable'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type MentionUserRendererProps = WithCurrentUserPersonalDetailsProps & CustomRendererProps; @@ -28,20 +31,41 @@ function MentionUserRenderer({style, tnode, TDefaultRenderer, currentUserPersona const StyleUtils = useStyleUtils(); const htmlAttribAccountID = tnode.attributes.accountid; const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; + const htmlAttributeAccountID = tnode.attributes.accountid; let accountID: number; let displayNameOrLogin: string; let navigationRoute: Route; + const tnodeClone = cloneDeep(tnode); + + const getMentionDisplayText = (displayText: string, userAccountID: string, userLogin = '') => { + // If the userAccountID does not exist, this is an email-based mention so the displayText must be an email. + // If the userAccountID exists but userLogin is different from displayText, this means the displayText is either user display name, Hidden, or phone number, in which case we should return it as is. + if (userAccountID && userLogin !== displayText) { + return displayText; + } + + // If the emails are not in the same private domain, we also return the displayText + if (!LoginUtils.areEmailsFromSamePrivateDomain(displayText, currentUserPersonalDetails.login ?? '')) { + return displayText; + } + + // Otherwise, the emails must be of the same private domain, so we should remove the domain part + return displayText.split('@')[0]; + }; + if (!isEmpty(htmlAttribAccountID)) { const user = personalDetails[htmlAttribAccountID]; accountID = parseInt(htmlAttribAccountID, 10); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing displayNameOrLogin = PersonalDetailsUtils.getDisplayNameOrDefault(user, LocalePhoneNumber.formatPhoneNumber(user?.login ?? '')); navigationRoute = ROUTES.PROFILE.getRoute(htmlAttribAccountID); - } else if ('data' in tnode && !isEmptyObject(tnode.data)) { + } else if ('data' in tnodeClone && !isEmptyObject(tnodeClone.data)) { // We need to remove the LTR unicode and leading @ from data as it is not part of the login - displayNameOrLogin = tnode.data.replace(CONST.UNICODE.LTR, '').slice(1); + displayNameOrLogin = tnodeClone.data.replace(CONST.UNICODE.LTR, '').slice(1); + // We need to replace tnode.data here because we will pass it to TNodeChildrenRenderer below + asMutable(tnodeClone).data = tnodeClone.data.replace(displayNameOrLogin, getMentionDisplayText(displayNameOrLogin, htmlAttributeAccountID)); accountID = PersonalDetailsUtils.getAccountIDsByLogins([displayNameOrLogin])?.[0]; navigationRoute = ROUTES.DETAILS.getRoute(displayNameOrLogin); @@ -82,7 +106,7 @@ function MentionUserRenderer({style, tnode, TDefaultRenderer, currentUserPersona testID="span" href={`/${navigationRoute}`} > - {htmlAttribAccountID ? `@${displayNameOrLogin}` : } + {htmlAttribAccountID ? `@${displayNameOrLogin}` : } diff --git a/src/types/utils/asMutable.ts b/src/types/utils/asMutable.ts new file mode 100644 index 000000000000..57c49058cd14 --- /dev/null +++ b/src/types/utils/asMutable.ts @@ -0,0 +1,5 @@ +import type {Writable} from 'type-fest'; + +const asMutable = (value: T): Writable => value as Writable; + +export default asMutable;