diff --git a/.eslintrc.js b/.eslintrc.js index 822a7f66b474..e0ebd2252c3d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,11 +14,6 @@ const restrictedImportPaths = [ importNames: ['TouchableOpacity', 'TouchableWithoutFeedback', 'TouchableNativeFeedback', 'TouchableHighlight'], message: "Please use 'PressableWithFeedback' and/or 'PressableWithoutFeedback' from 'src/components/Pressable' instead.", }, - { - name: 'awesome-phonenumber', - importNames: ['parsePhoneNumber'], - message: "Please use '@libs/PhoneNumber' instead.", - }, { name: 'react-native-safe-area-context', importNames: ['useSafeAreaInsets', 'SafeAreaConsumer', 'SafeAreaInsetsContext'], diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index 933aa7937560..e50f3be87c84 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -1,7 +1,7 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import {parsePhoneNumber} from './PhoneNumber'; let countryCodeByIP: number; Onyx.connect({ diff --git a/src/libs/LoginUtils.ts b/src/libs/LoginUtils.ts index dca84b9b11e0..742f9bfe16ce 100644 --- a/src/libs/LoginUtils.ts +++ b/src/libs/LoginUtils.ts @@ -1,9 +1,9 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import {PUBLIC_DOMAINS} from 'expensify-common/lib/CONST'; import Str from 'expensify-common/lib/str'; import Onyx from 'react-native-onyx'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {parsePhoneNumber} from './PhoneNumber'; let countryCodeByIP: number; Onyx.connect({ diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 943bd4aa2c16..1c2899f14c94 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1,4 +1,5 @@ /* eslint-disable no-continue */ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import lodashOrderBy from 'lodash/orderBy'; @@ -16,7 +17,6 @@ import ModifiedExpenseMessage from './ModifiedExpenseMessage'; import Navigation from './Navigation/Navigation'; import Permissions from './Permissions'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; -import * as PhoneNumber from './PhoneNumber'; import * as ReportActionUtils from './ReportActionsUtils'; import * as ReportUtils from './ReportUtils'; import * as TaskUtils from './TaskUtils'; @@ -116,7 +116,7 @@ Onyx.connect({ * @return {String} */ function addSMSDomainIfPhoneNumber(login) { - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(login); + const parsedPhoneNumber = parsePhoneNumber(login); if (parsedPhoneNumber.possible && !Str.isValidEmail(login)) { return parsedPhoneNumber.number.e164 + CONST.SMS.DOMAIN; } @@ -1133,7 +1133,7 @@ function getOptions( let recentReportOptions = []; let personalDetailsOptions = []; const reportMapForAccountIDs = {}; - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue))); + const parsedPhoneNumber = parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue))); const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number.e164 : searchInputValue.toLowerCase(); // Filter out all the reports that shouldn't be displayed @@ -1300,7 +1300,7 @@ function getOptions( if (includePersonalDetails) { // Next loop over all personal details removing any that are selectedUsers or recentChats _.each(allPersonalDetailsOptions, (personalDetailOption) => { - if (_.some(optionsToExclude, (optionToExclude) => optionToExclude.login === addSMSDomainIfPhoneNumber(personalDetailOption.login))) { + if (_.some(optionsToExclude, (optionToExclude) => optionToExclude.login === personalDetailOption.login)) { return; } const {searchText, participantsList, isChatRoom} = personalDetailOption; @@ -1634,7 +1634,7 @@ function getHeaderMessage(hasSelectableOptions, hasUserToInvite, searchValue, ma return Localize.translate(preferredLocale, 'common.maxParticipantsReached', {count: CONST.REPORT.MAXIMUM_PARTICIPANTS}); } - const isValidPhone = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible; + const isValidPhone = parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible; const isValidEmail = Str.isValidEmail(searchValue); diff --git a/src/libs/PhoneNumber.ts b/src/libs/PhoneNumber.ts deleted file mode 100644 index a702de2039e3..000000000000 --- a/src/libs/PhoneNumber.ts +++ /dev/null @@ -1,42 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import {parsePhoneNumber as originalParsePhoneNumber, ParsedPhoneNumber, ParsedPhoneNumberInvalid, PhoneNumberParseOptions} from 'awesome-phonenumber'; -import CONST from '@src/CONST'; - -/** - * Wraps awesome-phonenumber's parsePhoneNumber function to handle the case where we want to treat - * a US phone number that's technically valid as invalid. eg: +115005550009. - * See https://github.com/Expensify/App/issues/28492 - */ -function parsePhoneNumber(phoneNumber: string, options?: PhoneNumberParseOptions): ParsedPhoneNumber { - const parsedPhoneNumber = originalParsePhoneNumber(phoneNumber, options); - if (!parsedPhoneNumber.possible) { - return parsedPhoneNumber; - } - - const phoneNumberWithoutSpecialChars = phoneNumber.replace(CONST.REGEX.SPECIAL_CHARS_WITHOUT_NEWLINE, ''); - if (!/^\+11[0-9]{10}$/.test(phoneNumberWithoutSpecialChars)) { - return parsedPhoneNumber; - } - - const countryCode = phoneNumberWithoutSpecialChars.substring(0, 2); - const phoneNumberWithoutCountryCode = phoneNumberWithoutSpecialChars.substring(2); - - return { - ...parsedPhoneNumber, - valid: false, - possible: false, - number: { - ...parsedPhoneNumber.number, - - // mimic the behavior of awesome-phonenumber - e164: phoneNumberWithoutSpecialChars, - international: `${countryCode} ${phoneNumberWithoutCountryCode}`, - national: phoneNumberWithoutCountryCode, - rfc3966: `tel:${countryCode}-${phoneNumberWithoutCountryCode}`, - significant: phoneNumberWithoutCountryCode, - }, - } as ParsedPhoneNumberInvalid; -} - -// eslint-disable-next-line import/prefer-default-export -export {parsePhoneNumber}; diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 6d4f486663ec..ba977312fcfb 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import {addYears, endOfMonth, format, isAfter, isBefore, isSameDay, isValid, isWithinInterval, parse, parseISO, startOfDay, subYears} from 'date-fns'; import {URL_REGEX_WITH_REQUIRED_PROTOCOL} from 'expensify-common/lib/Url'; import isDate from 'lodash/isDate'; @@ -9,7 +10,6 @@ import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import * as CardUtils from './CardUtils'; import DateUtils from './DateUtils'; import * as LoginUtils from './LoginUtils'; -import {parsePhoneNumber} from './PhoneNumber'; import StringUtils from './StringUtils'; /** diff --git a/src/pages/DetailsPage.js b/src/pages/DetailsPage.js index bc7ff5543d66..b0362a69b4d6 100755 --- a/src/pages/DetailsPage.js +++ b/src/pages/DetailsPage.js @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; @@ -21,7 +22,6 @@ import UserDetailsTooltip from '@components/UserDetailsTooltip'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; import * as UserUtils from '@libs/UserUtils'; import * as Report from '@userActions/Report'; diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index d937be615370..d6f21f3ecdca 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import {subYears} from 'date-fns'; import PropTypes from 'prop-types'; import React from 'react'; @@ -16,7 +17,6 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ValidationUtils from '@libs/ValidationUtils'; import AddressForm from '@pages/ReimbursementAccount/AddressForm'; import * as PersonalDetails from '@userActions/PersonalDetails'; diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 10ca3cd79190..b50798f2d856 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; @@ -25,7 +26,6 @@ import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; import * as UserUtils from '@libs/UserUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index b868591ed0c8..a35fa596160a 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; @@ -19,7 +20,6 @@ import TextLink from '@components/TextLink'; import withLocalize from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; diff --git a/src/pages/RoomInvitePage.js b/src/pages/RoomInvitePage.js index e94dd6203b1b..cb72b2f8b08a 100644 --- a/src/pages/RoomInvitePage.js +++ b/src/pages/RoomInvitePage.js @@ -70,13 +70,7 @@ function RoomInvitePage(props) { const [userToInvite, setUserToInvite] = useState(null); // Any existing participants and Expensify emails should not be eligible for invitation - const excludedUsers = useMemo( - () => - _.map([...PersonalDetailsUtils.getLoginsByAccountIDs(lodashGet(props.report, 'participantAccountIDs', [])), ...CONST.EXPENSIFY_EMAILS], (participant) => - OptionsListUtils.addSMSDomainIfPhoneNumber(participant), - ), - [props.report], - ); + const excludedUsers = useMemo(() => [...PersonalDetailsUtils.getLoginsByAccountIDs(lodashGet(props.report, 'participantAccountIDs', [])), ...CONST.EXPENSIFY_EMAILS], [props.report]); useEffect(() => { const inviteOptions = OptionsListUtils.getMemberInviteOptions(props.personalDetails, props.betas, searchTerm, excludedUsers); @@ -185,7 +179,7 @@ function RoomInvitePage(props) { if (!userToInvite && CONST.EXPENSIFY_EMAILS.includes(searchValue)) { return translate('messages.errorMessageInvalidEmail'); } - if (!userToInvite && excludedUsers.includes(OptionsListUtils.addSMSDomainIfPhoneNumber(searchValue).toLowerCase())) { + if (!userToInvite && excludedUsers.includes(searchValue)) { return translate('messages.userIsAlreadyMember', {login: searchValue, name: reportName}); } return OptionsListUtils.getHeaderMessage(personalDetails.length !== 0, Boolean(userToInvite), searchValue); diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js index 131e71ccb2d0..3d4c7f4ac6fb 100644 --- a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js +++ b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js @@ -1,3 +1,4 @@ +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import PropTypes from 'prop-types'; import React from 'react'; @@ -7,7 +8,6 @@ import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import FormUtils from '@libs/FormUtils'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; diff --git a/src/pages/signin/LoginForm/BaseLoginForm.js b/src/pages/signin/LoginForm/BaseLoginForm.js index aa158d66a936..882f142ee5ad 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.js +++ b/src/pages/signin/LoginForm/BaseLoginForm.js @@ -1,4 +1,5 @@ import {useIsFocused} from '@react-navigation/native'; +import {parsePhoneNumber} from 'awesome-phonenumber'; import Str from 'expensify-common/lib/str'; import PropTypes from 'prop-types'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; @@ -24,7 +25,6 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import isInputAutoFilled from '@libs/isInputAutoFilled'; import Log from '@libs/Log'; import * as LoginUtils from '@libs/LoginUtils'; -import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import Visibility from '@libs/Visibility'; diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js index 16da273750fa..7a28558ee587 100644 --- a/src/pages/workspace/WorkspaceInvitePage.js +++ b/src/pages/workspace/WorkspaceInvitePage.js @@ -225,7 +225,7 @@ function WorkspaceInvitePage(props) { if (usersToInvite.length === 0 && CONST.EXPENSIFY_EMAILS.includes(searchValue)) { return translate('messages.errorMessageInvalidEmail'); } - if (usersToInvite.length === 0 && excludedUsers.includes(OptionsListUtils.addSMSDomainIfPhoneNumber(searchValue))) { + if (usersToInvite.length === 0 && excludedUsers.includes(searchValue)) { return translate('messages.userIsAlreadyMember', {login: searchValue, name: policyName}); } return OptionsListUtils.getHeaderMessage(personalDetails.length !== 0, usersToInvite.length > 0, searchValue); diff --git a/tests/unit/PhoneNumberTest.js b/tests/unit/PhoneNumberTest.js deleted file mode 100644 index f720dc6a88e1..000000000000 --- a/tests/unit/PhoneNumberTest.js +++ /dev/null @@ -1,43 +0,0 @@ -import {parsePhoneNumber} from '@libs/PhoneNumber'; - -describe('PhoneNumber', () => { - describe('parsePhoneNumber', () => { - it('Should return valid phone number', () => { - const validNumbers = [ - '+1 (234) 567-8901', - '+12345678901', - '+54 11 8765-4321', - '+49 30 123456', - '+44 20 8759 9036', - '+34 606 49 95 99', - ' + 1 2 3 4 5 6 7 8 9 0 1', - '+ 4 4 2 0 8 7 5 9 9 0 3 6', - '+1 ( 2 3 4 ) 5 6 7 - 8 9 0 1', - ]; - - validNumbers.forEach((givenPhone) => { - const parsedPhone = parsePhoneNumber(givenPhone); - expect(parsedPhone.valid).toBe(true); - expect(parsedPhone.possible).toBe(true); - }); - }); - it('Should return invalid phone number if US number has extra 1 after country code', () => { - const validNumbers = ['+1 1 (234) 567-8901', '+112345678901', '+115550123355', '+ 1 1 5 5 5 0 1 2 3 3 5 5']; - - validNumbers.forEach((givenPhone) => { - const parsedPhone = parsePhoneNumber(givenPhone); - expect(parsedPhone.valid).toBe(false); - expect(parsedPhone.possible).toBe(false); - }); - }); - it('Should return invalid phone number', () => { - const invalidNumbers = ['+165025300001', 'John Doe', '123', 'email@domain.com']; - - invalidNumbers.forEach((givenPhone) => { - const parsedPhone = parsePhoneNumber(givenPhone); - expect(parsedPhone.valid).toBe(false); - expect(parsedPhone.possible).toBe(false); - }); - }); - }); -});