From 9a44f8adb3f7ea00111e46a1ee3cc0b11f7a6940 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Fri, 23 Feb 2024 10:12:03 +0000 Subject: [PATCH 1/3] fix: Domain name is not dropped when sending text with user mention from same domain --- .../HTMLRenderers/MentionUserRenderer.tsx | 30 +++++++++++++++++-- src/types/utils/AsMutable.ts | 5 ++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 src/types/utils/AsMutable.ts diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx index f2e38ccb74af..f7ade59276ca 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; From 5f43d6c0026bfd2b9fdc8d871f4ba9ca22e54404 Mon Sep 17 00:00:00 2001 From: Ruben Rebelo <39693995+ruben-rebelo@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:08:50 +0000 Subject: [PATCH 2/3] Rename AsMutable.ts to asMutable.ts --- src/types/utils/{AsMutable.ts => asMutable.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/types/utils/{AsMutable.ts => asMutable.ts} (100%) diff --git a/src/types/utils/AsMutable.ts b/src/types/utils/asMutable.ts similarity index 100% rename from src/types/utils/AsMutable.ts rename to src/types/utils/asMutable.ts From c68dd83ec408bc84491ebbd9bbe03bb96a3a7992 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Fri, 23 Feb 2024 11:08:59 +0000 Subject: [PATCH 3/3] Fixed util name --- .../HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx index f7ade59276ca..5d8c0f6ef81e 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx @@ -21,7 +21,7 @@ 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 asMutable from '@src/types/utils/asMutable'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type MentionUserRendererProps = WithCurrentUserPersonalDetailsProps & CustomRendererProps;