From 8bce4415a6cdc8f1fad37e843c8e7695e8ddb119 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 16 Feb 2024 15:22:42 +0700 Subject: [PATCH 1/5] fix: Drop domain names when searching for users and auto-filling mentions --- src/libs/ReportUtils.ts | 10 +++++- .../ReportActionCompose/SuggestionMention.js | 34 +++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b5da21c0f67e..edb858804768 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -54,6 +54,7 @@ import DateUtils from './DateUtils'; import isReportMessageAttachment from './isReportMessageAttachment'; import * as LocalePhoneNumber from './LocalePhoneNumber'; import * as Localize from './Localize'; +import {isEmailPublicDomain} from './LoginUtils'; import linkingConfig from './Navigation/linkingConfig'; import Navigation from './Navigation/Navigation'; import * as NumberUtils from './NumberUtils'; @@ -436,12 +437,14 @@ Onyx.connect({ }); let allPersonalDetails: OnyxCollection; +let allPersonalDetailLogins: string[]; let currentUserPersonalDetails: OnyxEntry; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (value) => { currentUserPersonalDetails = value?.[currentUserAccountID ?? -1] ?? null; allPersonalDetails = value ?? {}; + allPersonalDetailLogins = Object.values(allPersonalDetails).map((v) => v?.login ?? ''); }, }); @@ -2674,7 +2677,12 @@ function hasReportNameError(report: OnyxEntry): boolean { */ function getParsedComment(text: string): string { const parser = new ExpensiMark(); - return text.length <= CONST.MAX_MARKUP_LENGTH ? parser.replace(text) : lodashEscape(text); + return text.length <= CONST.MAX_MARKUP_LENGTH + ? parser.replace(text, { + currentUserPrivateDomain: isEmailPublicDomain(currentUserEmail ?? '') ? '' : Str.extractEmailDomain(currentUserEmail ?? ''), + allPersonalDetailLogins, + }) + : lodashEscape(text); } function getReportDescriptionText(report: Report): string { diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.js b/src/pages/home/report/ReportActionCompose/SuggestionMention.js index 152ce54d5481..8575f57588a1 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.js @@ -4,9 +4,11 @@ import _ from 'underscore'; import * as Expensicons from '@components/Icon/Expensicons'; import MentionSuggestions from '@components/MentionSuggestions'; import {usePersonalDetails} from '@components/OnyxProvider'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; +import * as LoginUtils from '@libs/LoginUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import * as UserUtils from '@libs/UserUtils'; @@ -32,10 +34,13 @@ const propTypes = { forwardedRef: PropTypes.shape({current: PropTypes.shape({})}), ...SuggestionProps.implementationBaseProps, + + ...withCurrentUserPersonalDetailsPropTypes, }; const defaultProps = { forwardedRef: null, + ...withCurrentUserPersonalDetailsDefaultProps, }; function SuggestionMention({ @@ -50,6 +55,7 @@ function SuggestionMention({ isAutoSuggestionPickerLarge, measureParentContainer, isComposerFocused, + currentUserPersonalDetails, }) { const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; const {translate, formatPhoneNumber} = useLocalize(); @@ -67,6 +73,19 @@ function SuggestionMention({ // Used to decide whether to block the suggestions list from showing to prevent flickering const shouldBlockCalc = useRef(false); + const formatLoginPrivateDomain = (displayText, userLogin = '') => { + if (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]; + }; + /** * Replace the code of mention and update selection * @param {Number} highlightedMentionIndex @@ -75,7 +94,10 @@ function SuggestionMention({ (highlightedMentionIndexInner) => { const commentBeforeAtSign = value.slice(0, suggestionValues.atSignIndex); const mentionObject = suggestionValues.suggestedMentions[highlightedMentionIndexInner]; - const mentionCode = mentionObject.text === CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT ? CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT : `@${mentionObject.login}`; + const mentionCode = + mentionObject.text === CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT + ? CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT + : `@${formatLoginPrivateDomain(mentionObject.login, mentionObject.login)}`; const commentAfterMention = value.slice(suggestionValues.atSignIndex + suggestionValues.mentionPrefix.length + 1); updateComment(`${commentBeforeAtSign}${mentionCode} ${SuggestionsUtils.trimLeadingSpace(commentAfterMention)}`, true); @@ -88,7 +110,7 @@ function SuggestionMention({ suggestedMentions: [], })); }, - [value, suggestionValues.atSignIndex, suggestionValues.suggestedMentions, suggestionValues.mentionPrefix, updateComment, setSelection], + [value, suggestionValues.atSignIndex, suggestionValues.suggestedMentions, suggestionValues.mentionPrefix, updateComment, setSelection, formatLoginPrivateDomain], ); /** @@ -165,8 +187,8 @@ 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: PersonalDetailsUtils.getDisplayNameOrDefault(detail), - alternateText: formatPhoneNumber(detail.login), + text: formatLoginPrivateDomain(PersonalDetailsUtils.getDisplayNameOrDefault(detail), detail.login), + alternateText: `@${ formatLoginPrivateDomain(formatPhoneNumber(detail.login), detail.login)}`, login: detail.login, icons: [ { @@ -181,7 +203,7 @@ function SuggestionMention({ return suggestions; }, - [translate, formatPhoneNumber], + [translate, formatPhoneNumber, formatLoginPrivateDomain], ); const calculateMentionSuggestion = useCallback( @@ -332,4 +354,4 @@ const SuggestionMentionWithRef = React.forwardRef((props, ref) => ( SuggestionMentionWithRef.displayName = 'SuggestionMentionWithRef'; -export default SuggestionMentionWithRef; +export default withCurrentUserPersonalDetails(SuggestionMentionWithRef); From dc4d23110b40de11eb3685791d4ec1a18941cfd6 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 16 Feb 2024 16:27:01 +0700 Subject: [PATCH 2/5] add useCallback --- .../ReportActionCompose/SuggestionMention.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.js b/src/pages/home/report/ReportActionCompose/SuggestionMention.js index 8575f57588a1..645105597b8f 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.js @@ -73,18 +73,21 @@ function SuggestionMention({ // Used to decide whether to block the suggestions list from showing to prevent flickering const shouldBlockCalc = useRef(false); - const formatLoginPrivateDomain = (displayText, userLogin = '') => { - if (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; - } + const formatLoginPrivateDomain = useCallback( + (displayText, userLogin = '') => { + if (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]; - }; + // Otherwise, the emails must be of the same private domain, so we should remove the domain part + return displayText.split('@')[0]; + }, + [currentUserPersonalDetails.login], + ); /** * Replace the code of mention and update selection @@ -188,7 +191,7 @@ function SuggestionMention({ _.each(_.first(sortedPersonalDetails, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length), (detail) => { suggestions.push({ text: formatLoginPrivateDomain(PersonalDetailsUtils.getDisplayNameOrDefault(detail), detail.login), - alternateText: `@${ formatLoginPrivateDomain(formatPhoneNumber(detail.login), detail.login)}`, + alternateText: `@${formatLoginPrivateDomain(formatPhoneNumber(detail.login), detail.login)}`, login: detail.login, icons: [ { From 62b753fb973413ce59e86cc60417b4a31f221694 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 16 Feb 2024 20:58:47 +0700 Subject: [PATCH 3/5] add logic to reconstruct mention --- src/CONST.ts | 2 ++ src/libs/ReportUtils.ts | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index fae319325f13..560854a82eca 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1532,6 +1532,8 @@ const CONST = { PATH_WITHOUT_POLICY_ID: /\/w\/[a-zA-Z0-9]+(\/|$)/, POLICY_ID_FROM_PATH: /\/w\/([a-zA-Z0-9]+)(\/|$)/, + + SHORT_MENTION: new RegExp(`@[\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*`, 'gim'), }, PRONOUNS: { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index edb858804768..dc167ed2270c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -417,6 +417,7 @@ type AncestorIDs = { }; let currentUserEmail: string | undefined; +let currentUserPrivateDomain: string | undefined; let currentUserAccountID: number | undefined; let isAnonymousUser = false; @@ -433,6 +434,7 @@ Onyx.connect({ currentUserEmail = value.email; currentUserAccountID = value.accountID; isAnonymousUser = value.authTokenType === 'anonymousAccount'; + currentUserPrivateDomain = isEmailPublicDomain(currentUserEmail ?? '') ? '' : Str.extractEmailDomain(currentUserEmail ?? ''); }, }); @@ -2677,12 +2679,17 @@ function hasReportNameError(report: OnyxEntry): boolean { */ function getParsedComment(text: string): string { const parser = new ExpensiMark(); - return text.length <= CONST.MAX_MARKUP_LENGTH - ? parser.replace(text, { - currentUserPrivateDomain: isEmailPublicDomain(currentUserEmail ?? '') ? '' : Str.extractEmailDomain(currentUserEmail ?? ''), - allPersonalDetailLogins, - }) - : lodashEscape(text); + const textWithMention = text.replace(CONST.REGEX.SHORT_MENTION, (match) => { + const mention = match.substring(1); + const mentionWithDomain = `${mention}@${currentUserPrivateDomain}`; + + if (!Str.isValidEmail(mention) && currentUserPrivateDomain && allPersonalDetailLogins.includes(mentionWithDomain)) { + return `@${mentionWithDomain}`; + } + return match; + }); + + return textWithMention.length <= CONST.MAX_MARKUP_LENGTH ? parser.replace(textWithMention) : lodashEscape(textWithMention); } function getReportDescriptionText(report: Report): string { From 6ed7a054a29c5eadf2c893d983507d37f99a29c2 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 27 Feb 2024 11:41:58 +0700 Subject: [PATCH 4/5] fix phonenumber mention --- src/libs/OptionsListUtils.ts | 18 +++--------------- src/libs/PhoneNumber.ts | 14 +++++++++++++- src/libs/ReportUtils.ts | 16 +++++++++++++--- src/libs/actions/IOU.ts | 16 ++++++++-------- src/libs/actions/Policy.ts | 6 +++--- src/libs/actions/Report.ts | 4 ++-- src/libs/actions/TeachersUnite.ts | 4 ++-- src/pages/RoomInvitePage.tsx | 10 ++++++---- .../ReportActionCompose/SuggestionMention.js | 5 +++-- src/pages/workspace/WorkspaceInvitePage.tsx | 8 +++++--- 10 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 3d11795f5452..79e67164a15a 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -260,17 +260,6 @@ Onyx.connect({ }, }); -/** - * Adds expensify SMS domain (@expensify.sms) if login is a phone number and if it's not included yet - */ -function addSMSDomainIfPhoneNumber(login: string): string { - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(login); - if (parsedPhoneNumber.possible && !Str.isValidEmail(login)) { - return parsedPhoneNumber.number?.e164 + CONST.SMS.DOMAIN; - } - return login; -} - /** * @param defaultValues {login: accountID} In workspace invite page, when new user is added we pass available data to opt in * @returns Returns avatar data for a list of user accountIDs @@ -779,7 +768,7 @@ function isCurrentUser(userDetails: PersonalDetails): boolean { } // If user login is a mobile number, append sms domain if not appended already. - const userDetailsLogin = addSMSDomainIfPhoneNumber(userDetails.login ?? ''); + const userDetailsLogin = PhoneNumber.addSMSDomainIfPhoneNumber(userDetails.login ?? ''); if (currentUserLogin?.toLowerCase() === userDetailsLogin.toLowerCase()) { return true; @@ -1619,7 +1608,7 @@ function getOptions( const noOptions = recentReportOptions.length + personalDetailsOptions.length === 0 && !currentUserOption; const noOptionsMatchExactly = !personalDetailsOptions .concat(recentReportOptions) - .find((option) => option.login === addSMSDomainIfPhoneNumber(searchValue ?? '').toLowerCase() || option.login === searchValue?.toLowerCase()); + .find((option) => option.login === PhoneNumber.addSMSDomainIfPhoneNumber(searchValue ?? '').toLowerCase() || option.login === searchValue?.toLowerCase()); if ( searchValue && @@ -1628,7 +1617,7 @@ function getOptions( selectedOptions.every((option) => 'login' in option && option.login !== searchValue) && ((Str.isValidEmail(searchValue) && !Str.isDomainEmail(searchValue) && !Str.endsWith(searchValue, CONST.SMS.DOMAIN)) || (parsedPhoneNumber.possible && Str.isValidPhone(LoginUtils.getPhoneNumberWithoutSpecialChars(parsedPhoneNumber.number?.input ?? '')))) && - !optionsToExclude.find((optionToExclude) => 'login' in optionToExclude && optionToExclude.login === addSMSDomainIfPhoneNumber(searchValue).toLowerCase()) && + !optionsToExclude.find((optionToExclude) => 'login' in optionToExclude && optionToExclude.login === PhoneNumber.addSMSDomainIfPhoneNumber(searchValue).toLowerCase()) && (searchValue !== CONST.EMAIL.CHRONOS || Permissions.canUseChronos(betas)) && !excludeUnknownUsers ) { @@ -2009,7 +1998,6 @@ function formatSectionsFromSearchTerm( } export { - addSMSDomainIfPhoneNumber, getAvatarsForAccountIDs, isCurrentUser, isPersonalDetailsReady, diff --git a/src/libs/PhoneNumber.ts b/src/libs/PhoneNumber.ts index f92aade2c892..3e5ebe7b5d0b 100644 --- a/src/libs/PhoneNumber.ts +++ b/src/libs/PhoneNumber.ts @@ -1,6 +1,7 @@ // eslint-disable-next-line no-restricted-imports import {parsePhoneNumber as originalParsePhoneNumber} from 'awesome-phonenumber'; import type {ParsedPhoneNumber, ParsedPhoneNumberInvalid, PhoneNumberParseOptions} from 'awesome-phonenumber'; +import Str from 'expensify-common/lib/str'; import CONST from '@src/CONST'; /** @@ -39,5 +40,16 @@ function parsePhoneNumber(phoneNumber: string, options?: PhoneNumberParseOptions } as ParsedPhoneNumberInvalid; } +/** + * Adds expensify SMS domain (@expensify.sms) if login is a phone number and if it's not included yet + */ +function addSMSDomainIfPhoneNumber(login: string): string { + const parsedPhoneNumber = parsePhoneNumber(login); + if (parsedPhoneNumber.possible && !Str.isValidEmail(login)) { + return parsedPhoneNumber.number?.e164 + CONST.SMS.DOMAIN; + } + return login; +} + // eslint-disable-next-line import/prefer-default-export -export {parsePhoneNumber}; +export {parsePhoneNumber, addSMSDomainIfPhoneNumber}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e99b8f6666f5..2ebf9923a94e 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -61,6 +61,7 @@ import Navigation from './Navigation/Navigation'; import * as NumberUtils from './NumberUtils'; import Permissions from './Permissions'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; +import * as PhoneNumber from './PhoneNumber'; import * as PolicyUtils from './PolicyUtils'; import type {LastVisibleMessage} from './ReportActionsUtils'; import * as ReportActionsUtils from './ReportActionsUtils'; @@ -2687,11 +2688,20 @@ function getParsedComment(text: string): string { const parser = new ExpensiMark(); const textWithMention = text.replace(CONST.REGEX.SHORT_MENTION, (match) => { const mention = match.substring(1); - const mentionWithDomain = `${mention}@${currentUserPrivateDomain}`; - if (!Str.isValidEmail(mention) && currentUserPrivateDomain && allPersonalDetailLogins.includes(mentionWithDomain)) { - return `@${mentionWithDomain}`; + if (!Str.isValidEmail(mention) && currentUserPrivateDomain) { + const mentionWithEmailDomain = `${mention}@${currentUserPrivateDomain}`; + if (allPersonalDetailLogins.includes(mentionWithEmailDomain)) { + return `@${mentionWithEmailDomain}`; + } + } + if (Str.isValidPhone(mention)) { + const mentionWithSmsDomain = PhoneNumber.addSMSDomainIfPhoneNumber(mention); + if (allPersonalDetailLogins.includes(mentionWithSmsDomain)) { + return `@${mentionWithSmsDomain}`; + } } + return match; }); diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ca43d92bde83..160fd50e15b0 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -34,8 +34,8 @@ import * as Localize from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import * as NextStepUtils from '@libs/NextStepUtils'; import * as NumberUtils from '@libs/NumberUtils'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; import Permissions from '@libs/Permissions'; +import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -761,7 +761,7 @@ function getMoneyRequestInformation( payeeEmail = currentUserEmail, moneyRequestReportID = '', ): MoneyRequestInformation { - const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login ?? ''); + const payerEmail = PhoneNumber.addSMSDomainIfPhoneNumber(participant.login ?? ''); const payerAccountID = Number(participant.accountID); const isPolicyExpenseChat = participant.isPolicyExpenseChat; @@ -1602,7 +1602,7 @@ function createSplitsAndOnyxData( existingSplitChatReportID = '', billable = false, ): SplitsAndOnyxData { - const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(currentUserLogin); + const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(currentUserLogin); const participantAccountIDs = participants.map((participant) => Number(participant.accountID)); const existingSplitChatReport = existingSplitChatReportID || participants[0].reportID @@ -1770,7 +1770,7 @@ function createSplitsAndOnyxData( // In case the participant is a workspace, email & accountID should remain undefined and won't be used in the rest of this code // participant.login is undefined when the request is initiated from a group DM with an unknown user, so we need to add a default - const email = isOwnPolicyExpenseChat || isPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login ?? '').toLowerCase(); + const email = isOwnPolicyExpenseChat || isPolicyExpenseChat ? '' : PhoneNumber.addSMSDomainIfPhoneNumber(participant.login ?? '').toLowerCase(); const accountID = isOwnPolicyExpenseChat || isPolicyExpenseChat ? 0 : Number(participant.accountID); if (email === currentUserEmailForIOUSplit) { return; @@ -2066,7 +2066,7 @@ function startSplitBill( existingSplitChatReportID = '', billable = false, ) { - const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(currentUserLogin); + const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(currentUserLogin); const participantAccountIDs = participants.map((participant) => Number(participant.accountID)); const existingSplitChatReport = existingSplitChatReportID || participants[0].reportID @@ -2230,7 +2230,7 @@ function startSplitBill( participants.forEach((participant) => { // Disabling this line since participant.login can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const email = participant.isOwnPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login || participant.text || '').toLowerCase(); + const email = participant.isOwnPolicyExpenseChat ? '' : PhoneNumber.addSMSDomainIfPhoneNumber(participant.login || participant.text || '').toLowerCase(); const accountID = participant.isOwnPolicyExpenseChat ? 0 : Number(participant.accountID); if (email === currentUserEmailForIOUSplit) { return; @@ -2339,7 +2339,7 @@ function startSplitBill( * @param sessionEmail - email of the current user */ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportAction, updatedTransaction: OnyxTypes.Transaction, sessionAccountID: number, sessionEmail: string) { - const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail); + const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(sessionEmail); const {transactionID} = updatedTransaction; const unmodifiedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -3166,7 +3166,7 @@ function getSendMoneyParams( managerID: number, recipient: Participant, ): SendMoneyParamsData { - const recipientEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(recipient.login ?? ''); + const recipientEmail = PhoneNumber.addSMSDomainIfPhoneNumber(recipient.login ?? ''); const recipientAccountID = Number(recipient.accountID); const newIOUReportDetails = JSON.stringify({ amount, diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 57cd4a6fc071..d3e87adfac64 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -32,8 +32,8 @@ import DateUtils from '@libs/DateUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; import * as NumberUtils from '@libs/NumberUtils'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; +import * as PhoneNumber from '@libs/PhoneNumber'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; @@ -646,7 +646,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I Object.keys(invitedEmailsToAccountIDs).forEach((email) => { const accountID = invitedEmailsToAccountIDs[email]; const cleanAccountID = Number(accountID); - const login = OptionsListUtils.addSMSDomainIfPhoneNumber(email); + const login = PhoneNumber.addSMSDomainIfPhoneNumber(email); const oldChat = ReportUtils.getChatByParticipantsAndPolicy([sessionAccountID, cleanAccountID], policyID); @@ -727,7 +727,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I */ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccountIDs, welcomeNote: string, policyID: string) { const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}` as const; - const logins = Object.keys(invitedEmailsToAccountIDs).map((memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); + const logins = Object.keys(invitedEmailsToAccountIDs).map((memberLogin) => PhoneNumber.addSMSDomainIfPhoneNumber(memberLogin)); const accountIDs = Object.values(invitedEmailsToAccountIDs); const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, accountIDs); diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f29f8a4fbaab..6142077004d4 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -50,8 +50,8 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import LocalNotification from '@libs/Notification/LocalNotification'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; +import * as PhoneNumber from '@libs/PhoneNumber'; import getPolicyMemberAccountIDs from '@libs/PolicyMembersUtils'; import {extractPolicyIDFromPath} from '@libs/PolicyUtils'; import * as Pusher from '@libs/Pusher/pusher'; @@ -2375,7 +2375,7 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record typeof accountID === 'number', ); - const logins = inviteeEmails.map((memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); + const logins = inviteeEmails.map((memberLogin) => PhoneNumber.addSMSDomainIfPhoneNumber(memberLogin)); const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs); const optimisticData: OnyxUpdate[] = [ diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index ab48609e2d53..1f8b32724bd4 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -4,7 +4,7 @@ import * as API from '@libs/API'; import type {AddSchoolPrincipalParams, ReferTeachersUniteVolunteerParams} from '@libs/API/parameters'; import {WRITE_COMMANDS} from '@libs/API/types'; import Navigation from '@libs/Navigation/Navigation'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; +import * as PhoneNumber from '@libs/PhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; import type {OptimisticCreatedReportAction} from '@libs/ReportUtils'; import CONST from '@src/CONST'; @@ -69,7 +69,7 @@ function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, l */ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: string, policyID: string) { const policyName = CONST.TEACHERS_UNITE.POLICY_NAME; - const loggedInEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail); + const loggedInEmail = PhoneNumber.addSMSDomainIfPhoneNumber(sessionEmail); const reportCreationData: ReportCreationData = {}; const expenseChatData = ReportUtils.buildOptimisticChatReport([sessionAccountID], '', CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, sessionAccountID, true, policyName); diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 40a1b009b38d..7bcd64397e20 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -21,7 +21,7 @@ import Navigation from '@libs/Navigation/Navigation'; import type {RootStackParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; +import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as Report from '@userActions/Report'; @@ -56,7 +56,7 @@ function RoomInvitePage({betas, personalDetails, report, policies}: RoomInvitePa const excludedUsers = useMemo( () => [...PersonalDetailsUtils.getLoginsByAccountIDs(report?.visibleChatMemberAccountIDs ?? []), ...CONST.EXPENSIFY_EMAILS].map((participant) => - OptionsListUtils.addSMSDomainIfPhoneNumber(participant), + PhoneNumber.addSMSDomainIfPhoneNumber(participant), ), [report], ); @@ -109,7 +109,7 @@ function RoomInvitePage({betas, personalDetails, report, policies}: RoomInvitePa filterSelectedOptions = selectedOptions.filter((option) => { const accountID = option?.accountID; const isOptionInPersonalDetails = invitePersonalDetails.some((personalDetail) => accountID && personalDetail?.accountID === accountID); - const parsedPhoneNumber = parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchTerm))); + const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchTerm))); const searchValue = parsedPhoneNumber.possible && parsedPhoneNumber.number ? parsedPhoneNumber.number.e164 : searchTerm.toLowerCase(); const isPartOfSearchTerm = option.text?.toLowerCase().includes(searchValue) ?? option.login?.toLowerCase().includes(searchValue); return isPartOfSearchTerm ?? isOptionInPersonalDetails; @@ -199,7 +199,9 @@ function RoomInvitePage({betas, personalDetails, report, policies}: RoomInvitePa if ( !userToInvite && excludedUsers.includes( - parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible ? OptionsListUtils.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue)) : searchValue, + PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible + ? PhoneNumber.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue)) + : searchValue, ) ) { return translate('messages.userIsAlreadyMember', {login: searchValue, name: reportName}); diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.js b/src/pages/home/report/ReportActionCompose/SuggestionMention.js index 050ab1c3379b..03b37a466a4e 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.js @@ -1,3 +1,4 @@ +import Str from 'expensify-common/lib/str'; import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import _ from 'underscore'; @@ -80,7 +81,7 @@ function SuggestionMention({ } // If the emails are not in the same private domain, we also return the displayText if (!LoginUtils.areEmailsFromSamePrivateDomain(displayText, currentUserPersonalDetails.login)) { - return displayText; + return Str.removeSMSDomain(displayText); } // Otherwise, the emails must be of the same private domain, so we should remove the domain part @@ -191,7 +192,7 @@ function SuggestionMention({ _.each(_.first(sortedPersonalDetails, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length), (detail) => { suggestions.push({ text: formatLoginPrivateDomain(PersonalDetailsUtils.getDisplayNameOrDefault(detail), detail.login), - alternateText: `@${formatLoginPrivateDomain(formatPhoneNumber(detail.login), detail.login)}`, + alternateText: `@${formatLoginPrivateDomain(detail.login, detail.login)}`, login: detail.login, icons: [ { diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 3c1b009aac70..0d81ea00a889 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -21,7 +21,7 @@ import * as LoginUtils from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {MemberForList} from '@libs/OptionsListUtils'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; +import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {OptionData} from '@libs/ReportUtils'; import type {SettingsNavigatorParamList} from '@navigation/types'; @@ -176,7 +176,7 @@ function WorkspaceInvitePage({ filterSelectedOptions = selectedOptions.filter((option) => { const accountID = option.accountID; const isOptionInPersonalDetails = Object.values(personalDetails).some((personalDetail) => personalDetail.accountID === accountID); - const parsedPhoneNumber = parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchTerm))); + const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchTerm))); const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number?.e164 ?? '' : searchTerm.toLowerCase(); const isPartOfSearchTerm = !!option.text?.toLowerCase().includes(searchValue) || !!option.login?.toLowerCase().includes(searchValue); @@ -274,7 +274,9 @@ function WorkspaceInvitePage({ if ( usersToInvite.length === 0 && excludedUsers.includes( - parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible ? OptionsListUtils.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue)) : searchValue, + PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible + ? PhoneNumber.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue)) + : searchValue, ) ) { return translate('messages.userIsAlreadyMember', {login: searchValue, name: policyName}); From c7b2c5f7279f7f249b1ab8601005dbdb1b0c6c81 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 28 Feb 2024 11:05:01 +0700 Subject: [PATCH 5/5] change var name --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7b3229fb4649..cbb6119e1238 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -454,7 +454,7 @@ Onyx.connect({ callback: (value) => { currentUserPersonalDetails = value?.[currentUserAccountID ?? -1] ?? null; allPersonalDetails = value ?? {}; - allPersonalDetailLogins = Object.values(allPersonalDetails).map((v) => v?.login ?? ''); + allPersonalDetailLogins = Object.values(allPersonalDetails).map((personalDetail) => personalDetail?.login ?? ''); }, });