Match searches for national number format

// FREEBIE
pull/1/head
Michael Kirk 7 years ago
parent d423d3487f
commit f57a5dbc77

@ -210,18 +210,16 @@ class ConversationSearcherTest: XCTestCase {
XCTAssertEqual([bookClubThread, snackClubThread, aliceThread], threads)
}
// TODO
func pending_testSearchContactByNumber() {
var resultSet: SearchResultSet = .empty
func testSearchContactByNumberWithoutCountryCode() {
var threads: [ThreadViewModel] = []
// Phone Number formatting should be forgiving
resultSet = getResultSet(searchText: "234.56")
XCTAssertEqual(1, resultSet.conversations.count)
XCTAssertEqual(aliceThread, resultSet.conversations.first?.thread)
threads = searchConversations(searchText: "234.56")
XCTAssertEqual(3, threads.count)
XCTAssertEqual([bookClubThread, snackClubThread, aliceThread], threads)
resultSet = getResultSet(searchText: "234 56")
XCTAssertEqual(1, resultSet.conversations.count)
XCTAssertEqual(aliceThread, resultSet.conversations.first?.thread)
threads = searchConversations(searchText: "234 56")
XCTAssertEqual(3, threads.count)
XCTAssertEqual([bookClubThread, snackClubThread, aliceThread], threads)
}
func testSearchConversationByContactByName() {

@ -35,10 +35,9 @@
- (NSURL *)toSystemDialerURL;
- (NSString *)toE164;
- (NSString *)localizedDescriptionForUser;
- (NSNumber *)getCountryCode;
@property (nonatomic, readonly, nullable) NSString *nationalNumber;
- (BOOL)isValid;
- (BOOL)resolvesInternationallyTo:(PhoneNumber *)otherPhoneNumber;
- (NSComparisonResult)compare:(PhoneNumber *)other;

@ -372,25 +372,23 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
return self.phoneNumber.countryCode;
}
- (BOOL)isValid {
return [[PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil isValidNumber:self.phoneNumber];
}
- (NSString *)localizedDescriptionForUser {
NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil;
NSError *formatError = nil;
NSString *pretty =
[phoneUtil format:self.phoneNumber numberFormat:NBEPhoneNumberFormatINTERNATIONAL error:&formatError];
if (formatError != nil) {
return self.e164;
- (nullable NSString *)nationalNumber
{
NSError *error;
NSString *nationalNumber = [[PhoneNumberUtil sharedThreadLocal] format:self.phoneNumber
numberFormat:NBEPhoneNumberFormatNATIONAL
error:&error];
if (error) {
DDLogVerbose(@"%@ error parsing number into national format: %@", self.logTag, error);
return nil;
}
return pretty;
return nationalNumber;
}
- (BOOL)resolvesInternationallyTo:(PhoneNumber *)otherPhoneNumber {
return [self.toE164 isEqualToString:otherPhoneNumber.toE164];
- (BOOL)isValid
{
return [[PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil isValidNumber:self.phoneNumber];
}
- (NSString *)description {

@ -27,11 +27,11 @@ public class FullTextSearchFinder: NSObject {
return
}
let normalized = FullTextSearchFinder.normalize(text: searchText)
let normalized = FullTextSearchFinder.normalize(queryText: searchText)
// We want a forgiving query for phone numbers
// TODO a stricter "whole word" query for body text?
let prefixQuery = "*\(normalized)*"
// We want to match by prefix for "search as you type" functionality.
// SQLite does not support suffix or contains matches.
let prefixQuery = "\(normalized)*"
let maxSearchResults = 500
var searchResultCount = 0
@ -57,10 +57,10 @@ public class FullTextSearchFinder: NSObject {
return TextSecureKitEnv.shared().contactsManager
}
private class func normalize(text: String) -> String {
var normalized: String = text.trimmingCharacters(in: .whitespacesAndNewlines)
private class func normalize(indexingText: String) -> String {
var normalized: String = indexingText.trimmingCharacters(in: .whitespacesAndNewlines)
// Remove any phone number formatting from the search terms
// Remove any formatting from the search terms
let nonformattingScalars = normalized.unicodeScalars.lazy.filter {
!CharacterSet.punctuationCharacters.contains($0)
}
@ -70,6 +70,27 @@ public class FullTextSearchFinder: NSObject {
return normalized
}
private class func normalize(queryText: String) -> String {
var normalized: String = queryText.trimmingCharacters(in: .whitespacesAndNewlines)
// Remove any formatting from the search terms
let nonformattingScalars = normalized.unicodeScalars.lazy.filter {
!CharacterSet.punctuationCharacters.contains($0)
}
let normalizedChars = String(String.UnicodeScalarView(nonformattingScalars))
let digitsOnlyScalars = normalized.unicodeScalars.lazy.filter {
CharacterSet.decimalDigits.contains($0)
}
let normalizedDigits = String(String.UnicodeScalarView(digitsOnlyScalars))
if normalizedDigits.count > 0 {
return "\(normalizedChars) OR \(normalizedDigits)"
} else {
return "\(normalizedChars)"
}
}
private static let groupThreadIndexer: SearchIndexer<TSGroupThread> = SearchIndexer { (groupThread: TSGroupThread) in
let groupName = groupThread.groupModel.groupName ?? ""
@ -79,27 +100,43 @@ public class FullTextSearchFinder: NSObject {
let searchableContent = "\(groupName) \(memberStrings)"
return normalize(text: searchableContent)
return normalize(indexingText: searchableContent)
}
private static let contactThreadIndexer: SearchIndexer<TSContactThread> = SearchIndexer { (contactThread: TSContactThread) in
let recipientId = contactThread.contactIdentifier()
let searchableContent = recipientIndexer.index(recipientId)
return normalize(text: searchableContent)
return normalize(indexingText: searchableContent)
}
private static let recipientIndexer: SearchIndexer<String> = SearchIndexer { (recipientId: String) in
let displayName = contactsManager.displayName(forPhoneIdentifier: recipientId)
let searchableContent = "\(recipientId) \(displayName)"
return normalize(text: searchableContent)
let nationalNumber: String = { (recipientId: String) -> String in
guard let phoneNumber = PhoneNumber(fromE164: recipientId) else {
assertionFailure("unexpected unparseable recipientId: \(recipientId)")
return ""
}
guard let digitScalars = phoneNumber.nationalNumber?.unicodeScalars.filter({ CharacterSet.decimalDigits.contains($0) }) else {
assertionFailure("unexpected unparseable recipientId: \(recipientId)")
return ""
}
return String(String.UnicodeScalarView(digitScalars))
}(recipientId)
let searchableContent = "\(recipientId) \(nationalNumber) \(displayName)"
return normalize(indexingText: searchableContent)
}
private static let messageIndexer: SearchIndexer<TSMessage> = SearchIndexer { (message: TSMessage) in
let searchableContent = message.body ?? ""
return normalize(text: searchableContent)
return normalize(indexingText: searchableContent)
}
private class func indexContent(object: Any) -> String? {

Loading…
Cancel
Save