Update libPhoneNumber-unsupported country codes
This commit is contained in:
parent
f4e8ccd3bd
commit
5c38ebf6a1
@ -645,6 +645,7 @@
|
||||
5073EACF2C4F469A001FBB3E /* CallLinkFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5073EACE2C4F469A001FBB3E /* CallLinkFetcher.swift */; };
|
||||
5075C21729CA1EE700A260D2 /* GroupMemberUpdaterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5075C21629CA1EE700A260D2 /* GroupMemberUpdaterTest.swift */; };
|
||||
5077B5B82BBC7FE600EF399E /* ContactTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5077B5B72BBC7FE600EF399E /* ContactTest.swift */; };
|
||||
50791B1D2D037A9800D747F8 /* PhoneNumberCountryTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50791B1C2D037A9800D747F8 /* PhoneNumberCountryTest.swift */; };
|
||||
507B69112C503FA800F1C6D7 /* CallLinkTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50552C302BAC079A00815474 /* CallLinkTest.swift */; };
|
||||
507B69122C5044F800F1C6D7 /* LinkPreviewGroupLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A95517271B510400B05242 /* LinkPreviewGroupLink.swift */; };
|
||||
507CD5E529660D5100E47DAC /* ServiceId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CD5E429660D5100E47DAC /* ServiceId.swift */; };
|
||||
@ -4392,6 +4393,7 @@
|
||||
5073EACE2C4F469A001FBB3E /* CallLinkFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CallLinkFetcher.swift; path = SignalUI/Calls/CallLinkFetcher.swift; sourceTree = SOURCE_ROOT; };
|
||||
5075C21629CA1EE700A260D2 /* GroupMemberUpdaterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMemberUpdaterTest.swift; sourceTree = "<group>"; };
|
||||
5077B5B72BBC7FE600EF399E /* ContactTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactTest.swift; sourceTree = "<group>"; };
|
||||
50791B1C2D037A9800D747F8 /* PhoneNumberCountryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneNumberCountryTest.swift; sourceTree = "<group>"; };
|
||||
507CD5E429660D5100E47DAC /* ServiceId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceId.swift; sourceTree = "<group>"; };
|
||||
507D614B2BE433EE00DA7BA3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = translations/be.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
507D614C2BE433EE00DA7BA3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = translations/be.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@ -8663,6 +8665,14 @@
|
||||
path = GroupMembers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
50791B1B2D037A7800D747F8 /* RecipientPickers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
50791B1C2D037A9800D747F8 /* PhoneNumberCountryTest.swift */,
|
||||
);
|
||||
path = RecipientPickers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
50A76F512AF565A300FCF02D /* Preconditions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -10599,6 +10609,7 @@
|
||||
3471210D25ED5F850037CD1F /* Payments */,
|
||||
66CDB75A2AFC42B6009A36EC /* Provisioning */,
|
||||
D99ABC712A3D0BAA0034CD3B /* QRCodes */,
|
||||
50791B1B2D037A7800D747F8 /* RecipientPickers */,
|
||||
661278052996BA6700A1D5A1 /* Registration */,
|
||||
4C3EF8002109184A0007EBF7 /* SSKTests */,
|
||||
E75DD3DC2810CD3500E32C36 /* subscriptions */,
|
||||
@ -16710,6 +16721,7 @@
|
||||
3452851D26DFD12300824983 /* PaymentsFormatTest.swift in Sources */,
|
||||
3471211025ED5F910037CD1F /* PaymentsReconciliationTest.swift in Sources */,
|
||||
346EFC3225FD051400F493C7 /* PaymentsTest.swift in Sources */,
|
||||
50791B1D2D037A9800D747F8 /* PhoneNumberCountryTest.swift in Sources */,
|
||||
4C5250D421E7C51900CE3D95 /* PhoneNumberValidatorTest.swift in Sources */,
|
||||
66CDB7602AFC45CF009A36EC /* ProvisioningCoordinator+Mocks.swift in Sources */,
|
||||
66CDB75D2AFC42FC009A36EC /* ProvisioningCoordinatorTest.swift in Sources */,
|
||||
|
||||
52
Signal/test/RecipientPickers/PhoneNumberCountryTest.swift
Normal file
52
Signal/test/RecipientPickers/PhoneNumberCountryTest.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import SignalUI
|
||||
|
||||
final class PhoneNumberCountryTest: XCTestCase {
|
||||
func testCountryCodesForSearchTerm() {
|
||||
func countryCodes(forSearchTerm searchTerm: String?) -> [String] {
|
||||
return PhoneNumberCountry.buildCountries(searchText: searchTerm).map(\.countryCode)
|
||||
}
|
||||
// Empty search.
|
||||
XCTAssertGreaterThan(countryCodes(forSearchTerm: nil).count, 30)
|
||||
XCTAssertGreaterThan(countryCodes(forSearchTerm: "").count, 30)
|
||||
XCTAssertGreaterThan(countryCodes(forSearchTerm: " ").count, 30)
|
||||
|
||||
// Searches with no results.
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " . ").count, 0)
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " XXXXX ").count, 0)
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " ! ").count, 0)
|
||||
|
||||
// Search by country code.
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: "GB"), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: "gb"), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: "GB "), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " GB"), ["GB"])
|
||||
XCTAssert(countryCodes(forSearchTerm: " G").contains("GB"))
|
||||
XCTAssertFalse(countryCodes(forSearchTerm: " B").contains("GB"))
|
||||
|
||||
// Search by country name.
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: "united kingdom"), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " UNITED KINGDOM "), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " UNITED KING "), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " UNI KING "), ["GB"])
|
||||
XCTAssertEqual(countryCodes(forSearchTerm: " u k "), ["GB"])
|
||||
XCTAssert(countryCodes(forSearchTerm: " u").contains("GB"))
|
||||
XCTAssert(countryCodes(forSearchTerm: " k").contains("GB"))
|
||||
XCTAssertFalse(countryCodes(forSearchTerm: " m").contains("GB"))
|
||||
|
||||
// Search by calling code.
|
||||
XCTAssert(countryCodes(forSearchTerm: " +44 ").contains("GB"))
|
||||
XCTAssert(countryCodes(forSearchTerm: " 44 ").contains("GB"))
|
||||
XCTAssert(countryCodes(forSearchTerm: " +4 ").contains("GB"))
|
||||
XCTAssert(countryCodes(forSearchTerm: " 4 ").contains("GB"))
|
||||
XCTAssertFalse(countryCodes(forSearchTerm: " +123 ").contains("GB"))
|
||||
XCTAssertFalse(countryCodes(forSearchTerm: " +444 ").contains("GB"))
|
||||
}
|
||||
}
|
||||
@ -107,54 +107,36 @@ public class PhoneNumberUtil: NSObject {
|
||||
}
|
||||
|
||||
extension PhoneNumberUtil {
|
||||
// country code -> calling code
|
||||
public func plusPrefixedCallingCode(fromCountryCode countryCode: String) -> String? {
|
||||
guard let countryCode = countryCode.nilIfEmpty else {
|
||||
return "+0"
|
||||
/// Returns calling codes for libPhoneNumber-unsupported country codes.
|
||||
///
|
||||
/// These are country codes that NSLocale.isoCountryCodes contains but
|
||||
/// libPhoneNumber doesn't support. In every case, these countries share a
|
||||
/// calling code with a country that libPhoneNumber *does* support. We show
|
||||
/// these unsupported countries in the UI and convert them to a supported
|
||||
/// country when parsing the number.
|
||||
public static func callingCodeForUnsupportedCountryCode(_ countryCode: String) -> Int? {
|
||||
switch countryCode {
|
||||
case "AQ": /* Antarctica */ return 672
|
||||
case "BV": /* Bouvet Island */ return 55
|
||||
case "IC": /* Canary Islands */ return 34
|
||||
case "EA": /* Ceuta & Melilla */ return 34
|
||||
case "DG": /* Diego Garcia */ return 246
|
||||
case "TF": /* French Southern Territories */ return 262
|
||||
case "HM": /* Heard & McDonald Islands */ return 672
|
||||
case "PN": /* Pitcairn Islands */ return 64
|
||||
case "CQ": /* Sark */ return 44
|
||||
case "GS": /* So. Georgia & So. Sandwich Isl. */ return 500
|
||||
case "UM": /* U.S. Outlying Islands */ return 1
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
if countryCode == "AQ" {
|
||||
// Antarctica
|
||||
return "+672"
|
||||
} else if countryCode == "BV" {
|
||||
// Bouvet Island
|
||||
return "+55"
|
||||
} else if countryCode == "IC" {
|
||||
// Canary Islands
|
||||
return "+34"
|
||||
} else if countryCode == "EA" {
|
||||
// Ceuta & Melilla
|
||||
return "+34"
|
||||
} else if countryCode == "CP" {
|
||||
// Clipperton Island
|
||||
//
|
||||
// This country code should be filtered - it does not appear to have a calling code.
|
||||
return nil
|
||||
} else if countryCode == "DG" {
|
||||
// Diego Garcia
|
||||
return "+246"
|
||||
} else if countryCode == "TF" {
|
||||
// French Southern Territories
|
||||
return "+262"
|
||||
} else if countryCode == "HM" {
|
||||
// Heard & McDonald Islands
|
||||
return "+672"
|
||||
} else if countryCode == "XK" {
|
||||
// Kosovo
|
||||
return "+383"
|
||||
} else if countryCode == "PN" {
|
||||
// Pitcairn Islands
|
||||
return "+64"
|
||||
} else if countryCode == "GS" {
|
||||
// So. Georgia & So. Sandwich Isl.
|
||||
return "+500"
|
||||
} else if countryCode == "UM" {
|
||||
// U.S. Outlying Islands
|
||||
return "+1"
|
||||
public func countryCodeForParsing(fromCountryCode countryCode: String) -> String {
|
||||
if let callingCode = Self.callingCodeForUnsupportedCountryCode(countryCode) {
|
||||
// Force unwrap is covered by unit tests.
|
||||
return getFilteredRegionCodeForCallingCode(callingCode)!
|
||||
}
|
||||
|
||||
let callingCode = getCallingCode(forRegion: countryCode)
|
||||
return PhoneNumber.countryCodePrefix + "\(callingCode)"
|
||||
return countryCode
|
||||
}
|
||||
|
||||
public static func defaultCountryCode() -> String {
|
||||
@ -245,52 +227,9 @@ extension PhoneNumberUtil {
|
||||
return try? format(phoneNumber.nbPhoneNumber, numberFormat: .NATIONAL)
|
||||
}
|
||||
|
||||
private class func does(_ string: String, matchQuery query: String) -> Bool {
|
||||
let searchOptions: String.CompareOptions = [.caseInsensitive, .anchored]
|
||||
|
||||
let stringTokens = string.components(separatedBy: .whitespaces)
|
||||
let queryTokens = query.components(separatedBy: .whitespaces)
|
||||
|
||||
return queryTokens.allSatisfy { queryToken in
|
||||
if queryToken.isEmpty {
|
||||
return true
|
||||
}
|
||||
return stringTokens.contains { stringToken in
|
||||
stringToken.range(of: queryToken, options: searchOptions) != nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get country codes from a search term.
|
||||
public func countryCodes(forSearchTerm searchTerm: String?) -> [String] {
|
||||
let cleanedSearch = (searchTerm ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
let codes = NSLocale.isoCountryCodes.filter { countryCode in
|
||||
guard
|
||||
let callingCode = plusPrefixedCallingCode(fromCountryCode: countryCode),
|
||||
callingCode != "+0"
|
||||
else {
|
||||
return false
|
||||
}
|
||||
let countryName = Self.countryName(fromCountryCode: countryCode)
|
||||
return (
|
||||
cleanedSearch.isEmpty ||
|
||||
Self.does(countryName, matchQuery: cleanedSearch) ||
|
||||
Self.does(countryCode, matchQuery: cleanedSearch) ||
|
||||
callingCode.contains(cleanedSearch)
|
||||
)
|
||||
}
|
||||
|
||||
return codes.sorted { lhs, rhs in
|
||||
let lhsCountry = Self.countryName(fromCountryCode: lhs)
|
||||
let rhsCountry = Self.countryName(fromCountryCode: rhs)
|
||||
return lhsCountry.localizedCaseInsensitiveCompare(rhsCountry) == .orderedAscending
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert country code to country name.
|
||||
public class func countryName(fromCountryCode countryCode: String) -> String {
|
||||
lazy var unknownValue = OWSLocalizedString(
|
||||
public static func countryName(fromCountryCode countryCode: String) -> String {
|
||||
lazy var unknownValue = OWSLocalizedString(
|
||||
"UNKNOWN_VALUE",
|
||||
comment: "Indicates an unknown or unrecognizable value."
|
||||
)
|
||||
@ -331,7 +270,10 @@ extension PhoneNumberUtil {
|
||||
}
|
||||
|
||||
public func parsePhoneNumber(countryCode: String, nationalNumber: String) -> PhoneNumber? {
|
||||
return _parsePhoneNumber(filteredValue: nationalNumber.filteredAsE164, countryCode: countryCode)
|
||||
return _parsePhoneNumber(
|
||||
filteredValue: nationalNumber.filteredAsE164,
|
||||
countryCode: countryCodeForParsing(fromCountryCode: countryCode)
|
||||
)
|
||||
}
|
||||
|
||||
public func parsePhoneNumbers(userSpecifiedText: String, localPhoneNumber: String?) -> [PhoneNumber] {
|
||||
|
||||
@ -15,17 +15,30 @@ class PhoneNumberUtilTestSwift: XCTestCase {
|
||||
self.phoneNumberUtilRef = PhoneNumberUtil()
|
||||
}
|
||||
|
||||
func testCountryCodeForParsing() {
|
||||
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
for ch1 in alphabet {
|
||||
for ch2 in alphabet {
|
||||
_ = self.phoneNumberUtilRef.countryCodeForParsing(fromCountryCode: String(ch1) + String(ch2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_callingCodeFromCountryCode() {
|
||||
XCTAssertEqual("+1", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "US"))
|
||||
XCTAssertEqual("+44", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "GB"))
|
||||
XCTAssertEqual("+598", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "UY"))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "QG"))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "EK"))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "ZZZ"))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: ""))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "+"))
|
||||
XCTAssertEqual("+0", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "9"))
|
||||
XCTAssertEqual("+1", phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: "US "))
|
||||
func plusPrefixedCallingCode(fromCountryCode countryCode: String) -> String {
|
||||
let callingCode = phoneNumberUtilRef.getCallingCode(forRegion: countryCode)
|
||||
return "+\(callingCode)"
|
||||
}
|
||||
XCTAssertEqual("+1", plusPrefixedCallingCode(fromCountryCode: "US"))
|
||||
XCTAssertEqual("+44", plusPrefixedCallingCode(fromCountryCode: "GB"))
|
||||
XCTAssertEqual("+598", plusPrefixedCallingCode(fromCountryCode: "UY"))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: "QG"))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: "EK"))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: "ZZZ"))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: ""))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: "+"))
|
||||
XCTAssertEqual("+0", plusPrefixedCallingCode(fromCountryCode: "9"))
|
||||
XCTAssertEqual("+1", plusPrefixedCallingCode(fromCountryCode: "US "))
|
||||
}
|
||||
|
||||
func test_examplePhoneNumberForCountryCode() {
|
||||
@ -58,44 +71,6 @@ class PhoneNumberUtilTestSwift: XCTestCase {
|
||||
XCTAssertEqual(0, phoneNumberUtilRef.getCallingCode(forRegion: "ZQ"))
|
||||
}
|
||||
|
||||
func testCountryCodesForSearchTerm() {
|
||||
// Empty search.
|
||||
XCTAssertGreaterThan(phoneNumberUtilRef.countryCodes(forSearchTerm: nil).count, 30)
|
||||
XCTAssertGreaterThan(phoneNumberUtilRef.countryCodes(forSearchTerm: "").count, 30)
|
||||
XCTAssertGreaterThan(phoneNumberUtilRef.countryCodes(forSearchTerm: " ").count, 30)
|
||||
|
||||
// Searches with no results.
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " . ").count, 0)
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " XXXXX ").count, 0)
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " ! ").count, 0)
|
||||
|
||||
// Search by country code.
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: "GB"), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: "gb"), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: "GB "), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " GB"), ["GB"])
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " G").contains("GB"))
|
||||
XCTAssertFalse(phoneNumberUtilRef.countryCodes(forSearchTerm: " B").contains("GB"))
|
||||
|
||||
// Search by country name.
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: "united kingdom"), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " UNITED KINGDOM "), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " UNITED KING "), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " UNI KING "), ["GB"])
|
||||
XCTAssertEqual(phoneNumberUtilRef.countryCodes(forSearchTerm: " u k "), ["GB"])
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " u").contains("GB"))
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " k").contains("GB"))
|
||||
XCTAssertFalse(phoneNumberUtilRef.countryCodes(forSearchTerm: " m").contains("GB"))
|
||||
|
||||
// Search by calling code.
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " +44 ").contains("GB"))
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " 44 ").contains("GB"))
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " +4 ").contains("GB"))
|
||||
XCTAssert(phoneNumberUtilRef.countryCodes(forSearchTerm: " 4 ").contains("GB"))
|
||||
XCTAssertFalse(phoneNumberUtilRef.countryCodes(forSearchTerm: " +123 ").contains("GB"))
|
||||
XCTAssertFalse(phoneNumberUtilRef.countryCodes(forSearchTerm: " +444 ").contains("GB"))
|
||||
}
|
||||
|
||||
func testTranslateCursorPosition() {
|
||||
XCTAssertEqual(0, PhoneNumberUtil.translateCursorPosition(0, from: "", to: "", stickingRightward: true))
|
||||
|
||||
|
||||
@ -33,9 +33,60 @@ public struct PhoneNumberCountry: Equatable {
|
||||
|
||||
// MARK: -
|
||||
|
||||
private static func bestEffortCallingCode(fromCountryCode countryCode: String) -> Int? {
|
||||
if let result = PhoneNumberUtil.callingCodeForUnsupportedCountryCode(countryCode) {
|
||||
return result
|
||||
}
|
||||
let result = SSKEnvironment.shared.phoneNumberUtilRef.getCallingCode(forRegion: countryCode)
|
||||
return result == 0 ? nil : result
|
||||
}
|
||||
|
||||
private static func does(_ string: String, matchQuery query: String) -> Bool {
|
||||
let searchOptions: String.CompareOptions = [.caseInsensitive, .anchored]
|
||||
|
||||
let stringTokens = string.components(separatedBy: .whitespaces)
|
||||
let queryTokens = query.components(separatedBy: .whitespaces)
|
||||
|
||||
return queryTokens.allSatisfy { queryToken in
|
||||
if queryToken.isEmpty {
|
||||
return true
|
||||
}
|
||||
return stringTokens.contains { stringToken in
|
||||
stringToken.range(of: queryToken, options: searchOptions) != nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get country codes from a search term.
|
||||
private static func countryCodes(forSearchTerm searchTerm: String?) -> [String] {
|
||||
let cleanedSearch = (searchTerm ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
var countryCodesAndNames = NSLocale.isoCountryCodes.compactMap { countryCode -> (countryCode: String, countryName: String)? in
|
||||
guard let callingCode = bestEffortCallingCode(fromCountryCode: countryCode) else {
|
||||
// Clipperton Island is filtered intentionally.
|
||||
owsAssertDebug(countryCode == "CP")
|
||||
return nil
|
||||
}
|
||||
let countryName = PhoneNumberUtil.countryName(fromCountryCode: countryCode)
|
||||
let isMatch = (
|
||||
cleanedSearch.isEmpty ||
|
||||
Self.does(countryName, matchQuery: cleanedSearch) ||
|
||||
Self.does(countryCode, matchQuery: cleanedSearch) ||
|
||||
"+\(callingCode)".contains(cleanedSearch)
|
||||
)
|
||||
return isMatch ? (countryCode, countryName) : nil
|
||||
}
|
||||
|
||||
countryCodesAndNames.sort(by: { lhs, rhs in
|
||||
return lhs.countryName.localizedCaseInsensitiveCompare(rhs.countryName) == .orderedAscending
|
||||
})
|
||||
|
||||
return countryCodesAndNames.map(\.countryCode)
|
||||
}
|
||||
|
||||
public static func buildCountries(searchText: String?) -> [PhoneNumberCountry] {
|
||||
let searchText = searchText?.strippedOrNil
|
||||
let countryCodes: [String] = SSKEnvironment.shared.phoneNumberUtilRef.countryCodes(forSearchTerm: searchText)
|
||||
let countryCodes: [String] = countryCodes(forSearchTerm: searchText)
|
||||
return PhoneNumberCountry.buildCountries(forCountryCodes: countryCodes)
|
||||
}
|
||||
|
||||
@ -50,11 +101,11 @@ public struct PhoneNumberCountry: Equatable {
|
||||
}
|
||||
|
||||
public static func buildCountry(forCountryCode countryCode: String) -> PhoneNumberCountry? {
|
||||
guard let plusPrefixedCallingCode = SSKEnvironment.shared.phoneNumberUtilRef.plusPrefixedCallingCode(fromCountryCode: countryCode) else {
|
||||
guard let callingCode = bestEffortCallingCode(fromCountryCode: countryCode) else {
|
||||
owsFailDebug("Invalid countryCode.")
|
||||
return nil
|
||||
}
|
||||
return buildCountry(countryCode: countryCode, plusPrefixedCallingCode: plusPrefixedCallingCode)
|
||||
return buildCountry(countryCode: countryCode, plusPrefixedCallingCode: "+\(callingCode)")
|
||||
}
|
||||
|
||||
public static func buildCountry(forCallingCode callingCode: Int) -> PhoneNumberCountry? {
|
||||
@ -68,17 +119,9 @@ public struct PhoneNumberCountry: Equatable {
|
||||
return buildCountry(countryCode: countryCode, plusPrefixedCallingCode: "+\(callingCode)")
|
||||
}
|
||||
|
||||
private static func buildCountry(countryCode: String, plusPrefixedCallingCode: String) -> PhoneNumberCountry? {
|
||||
guard let countryName = PhoneNumberUtil.countryName(fromCountryCode: countryCode).strippedOrNil else {
|
||||
owsFailDebug("Invalid countryName.")
|
||||
return nil
|
||||
}
|
||||
guard plusPrefixedCallingCode != "+0" else {
|
||||
owsFailDebug("Invalid callingCode.")
|
||||
return nil
|
||||
}
|
||||
private static func buildCountry(countryCode: String, plusPrefixedCallingCode: String) -> PhoneNumberCountry {
|
||||
return PhoneNumberCountry(
|
||||
countryName: countryName,
|
||||
countryName: PhoneNumberUtil.countryName(fromCountryCode: countryCode),
|
||||
plusPrefixedCallingCode: plusPrefixedCallingCode,
|
||||
countryCode: countryCode
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user