From 814b4562ee936c78596fea4f17fa87aeb0160e18 Mon Sep 17 00:00:00 2001 From: Roma Sosnovsky Date: Fri, 29 Oct 2021 14:56:37 +0300 Subject: [PATCH] issue #743 add search for auto-generated user contacts --- .../CheckAuthScopesViewController.swift | 1 + .../CloudContactsProvider.swift | 51 ++++++++++++++++--- .../Services/GeneralConstants.swift | 3 +- FlowCryptAppTests/GeneralConstantsTest.swift | 3 +- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/FlowCrypt/Controllers/CheckAuthScopes/CheckAuthScopesViewController.swift b/FlowCrypt/Controllers/CheckAuthScopes/CheckAuthScopesViewController.swift index 4e2957417..122894dcf 100644 --- a/FlowCrypt/Controllers/CheckAuthScopes/CheckAuthScopesViewController.swift +++ b/FlowCrypt/Controllers/CheckAuthScopes/CheckAuthScopesViewController.swift @@ -16,6 +16,7 @@ private extension GoogleScope { case .userInfo: return "User Info" case .mail: return "Gmail" case .contacts: return "Contacts" + case .otherContacts: return "Other Contacts" } } } diff --git a/FlowCrypt/Functionality/Mail Provider/Contacts Provider/CloudContactsProvider.swift b/FlowCrypt/Functionality/Mail Provider/Contacts Provider/CloudContactsProvider.swift index d57fbb978..d09f0b6bc 100644 --- a/FlowCrypt/Functionality/Mail Provider/Contacts Provider/CloudContactsProvider.swift +++ b/FlowCrypt/Functionality/Mail Provider/Contacts Provider/CloudContactsProvider.swift @@ -34,6 +34,31 @@ final class UserContactsProvider { return service } + private enum QueryType { + case contacts, other + + func query(searchString: String) -> GTLRPeopleServiceQuery { + switch self { + case .contacts: + let query = GTLRPeopleServiceQuery_PeopleSearchContacts.query() + query.readMask = readMask + query.query = searchString + return query + case .other: + let query = GTLRPeopleServiceQuery_OtherContactsSearch.query() + query.readMask = readMask + query.query = searchString + return query + } + } + + var readMask: String { + switch self { + case .contacts, .other: return "emailAddresses" + } + } + } + init(userService: GoogleUserServiceType = GoogleUserService()) { self.userService = userService @@ -43,19 +68,31 @@ final class UserContactsProvider { private func runWarmupQuery() { Task { // Warmup query for google contacts cache - _ = try? await searchContacts(query: "") + _ = await searchContacts(query: "") } } } extension UserContactsProvider: CloudContactsProvider { - func searchContacts(query: String) async throws -> [String] { - let searchQuery = GTLRPeopleServiceQuery_PeopleSearchContacts.query() - searchQuery.readMask = "names,emailAddresses" - searchQuery.query = query + func searchContacts(query: String) async -> [String] { + let contacts = await searchUserContacts(query: query, type: .contacts) + let otherContacts = await searchUserContacts(query: query, type: .other) + let emails = Set(contacts + otherContacts) + return Array(emails).sorted(by: >) + } +} + +extension UserContactsProvider { + private func searchUserContacts(query: String, type: QueryType) async -> [String] { + let query = type.query(searchString: query) + + guard let emails = try? await perform(query: query) else { return [] } + return emails + } - return try await withCheckedThrowingContinuation { continuation in - self.peopleService.executeQuery(searchQuery) { _, data, error in + private func perform(query: GTLRPeopleServiceQuery) async throws -> [String] { + try await withCheckedThrowingContinuation { continuation in + self.peopleService.executeQuery(query) { _, data, error in if let error = error { continuation.resume(throwing: CloudContactsProviderError.providerError(error)) return diff --git a/FlowCrypt/Functionality/Services/GeneralConstants.swift b/FlowCrypt/Functionality/Services/GeneralConstants.swift index df1b95244..e438b4618 100644 --- a/FlowCrypt/Functionality/Services/GeneralConstants.swift +++ b/FlowCrypt/Functionality/Services/GeneralConstants.swift @@ -29,13 +29,14 @@ enum GeneralConstants { } enum GoogleScope: CaseIterable { - case userInfo, mail, contacts + case userInfo, mail, contacts, otherContacts var value: String { switch self { case .userInfo: return "https://www.googleapis.com/auth/userinfo.profile" case .mail: return "https://mail.google.com/" case .contacts: return "https://www.googleapis.com/auth/contacts" + case .otherContacts: return "https://www.googleapis.com/auth/contacts.other.readonly" } } } diff --git a/FlowCryptAppTests/GeneralConstantsTest.swift b/FlowCryptAppTests/GeneralConstantsTest.swift index c3b8401aa..d4273c481 100644 --- a/FlowCryptAppTests/GeneralConstantsTest.swift +++ b/FlowCryptAppTests/GeneralConstantsTest.swift @@ -29,7 +29,8 @@ class GeneralConstantsTest: XCTestCase { let expectedScope = Set([ "https://www.googleapis.com/auth/userinfo.profile", "https://mail.google.com/", - "https://www.googleapis.com/auth/contacts" + "https://www.googleapis.com/auth/contacts", + "https://www.googleapis.com/auth/contacts.other.readonly" ]) XCTAssert(currentScope == expectedScope)