Skip to content

Commit

Permalink
feat(AutocompletionView): Give higher priority to Infomaniak Contacts (
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippeWeidmann authored Oct 4, 2024
2 parents 7fe86ab + c2ae592 commit a611879
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 11 deletions.
16 changes: 15 additions & 1 deletion Mail/Views/New Message/AutocompletionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import RealmSwift
import SwiftUI

struct AutocompletionView: View {
private static let maxAutocompleteCount = 10

@EnvironmentObject private var mailboxManager: MailboxManager

@State private var shouldAddUserProposal = false
Expand Down Expand Up @@ -67,7 +69,11 @@ struct AutocompletionView: View {
private func updateAutocompletion(_ search: String) {
let trimmedSearch = search.trimmingCharacters(in: .whitespacesAndNewlines)

let autocompleteContacts = mailboxManager.contactManager.frozenContacts(matching: trimmedSearch, fetchLimit: nil)
let autocompleteContacts = mailboxManager.contactManager.frozenContacts(
matching: trimmedSearch,
fetchLimit: Self.maxAutocompleteCount,
sorted: sortByRemoteAndName
)
var autocompleteRecipients = autocompleteContacts.map { Recipient(email: $0.email, name: $0.name) }

let realResults = autocompleteRecipients.filter { !addedRecipients.map(\.email).contains($0.email) }
Expand All @@ -82,6 +88,14 @@ struct AutocompletionView: View {
autocompletion = autocompleteRecipients
}
}

private func sortByRemoteAndName(lhs: MergedContact, rhs: MergedContact) -> Bool {
if lhs.isRemote != rhs.isRemote {
return lhs.isRemote && !rhs.isRemote
} else {
return lhs.name.localizedStandardCompare(rhs.name) == .orderedAscending
}
}
}

#Preview {
Expand Down
6 changes: 5 additions & 1 deletion Mail/Views/Search/SearchViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ final class SearchViewModel: ObservableObject, ThreadListable {
}

func updateContactSuggestion() {
let autocompleteContacts = mailboxManager.contactManager.frozenContacts(matching: searchValue, fetchLimit: nil)
let autocompleteContacts = mailboxManager.contactManager.frozenContacts(
matching: searchValue,
fetchLimit: nil,
sorted: nil
)
var autocompleteRecipients = autocompleteContacts.map { Recipient(email: $0.email, name: $0.name).freezeIfNeeded() }

// Append typed email
Expand Down
14 changes: 9 additions & 5 deletions MailCore/Cache/ContactManager/ContactManager+DB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public protocol ContactFetchable {
/// - string: input string to match against email and name
/// - fetchLimit: limit the query by default to limit memory footprint
/// - Returns: The collection of matching contacts.
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MergedContact>
func frozenContacts(matching string: String, fetchLimit: Int?, sorted: ((MergedContact, MergedContact) -> Bool)?)
-> any Collection<MergedContact>

/// Get a contact from a given transactionable
func getContact(for correspondent: any Correspondent, transactionable: Transactionable) -> MergedContact?
Expand All @@ -49,18 +50,21 @@ public extension ContactManager {
/// - string: input string to match against email and name
/// - fetchLimit: limit the query by default to limit memory footprint
/// - Returns: The collection of matching contacts. Frozen.
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MergedContact> {
func frozenContacts(matching string: String, fetchLimit: Int?,
sorted: ((MergedContact, MergedContact) -> Bool)?) -> any Collection<MergedContact> {
var lazyResults = fetchResults(ofType: MergedContact.self) { partial in
partial
}
lazyResults = lazyResults
.filter(Self.searchContactInsensitivePredicate, string, string)
.freeze()

let fetchLimit = min(lazyResults.count, fetchLimit ?? Self.contactFetchLimit)
var sortedIfNecessary: any Collection<MergedContact> = lazyResults
if let sorted {
sortedIfNecessary = sortedIfNecessary.sorted(by: sorted)
}

let limitedResults = lazyResults[0 ..< fetchLimit]
return limitedResults
return sortedIfNecessary.prefix(fetchLimit ?? Self.contactFetchLimit)
}

func getContact(for correspondent: any Correspondent) -> MergedContact? {
Expand Down
2 changes: 1 addition & 1 deletion MailCore/Models/Recipient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public final class Recipient: EmbeddedObject, Correspondent, Codable {

let isAnAlias = mailboxManager.mailbox.aliases.contains(email)

let isContact = !(mailboxManager.contactManager.frozenContacts(matching: email, fetchLimit: nil)).isEmpty
let isContact = !(mailboxManager.contactManager.frozenContacts(matching: email, fetchLimit: nil, sorted: nil)).isEmpty

return !isKnownDomain && !isMailerDeamon && !isAnAlias && !isContact
}
Expand Down
2 changes: 1 addition & 1 deletion MailTests/Contacts/UTContactManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ final class UTContactManager: XCTestCase {
generateFakeContacts(count: 100_000)
measure {
// WHEN
let matchingContacts = contactManager.frozenContacts(matching: "mail", fetchLimit: nil)
let matchingContacts = contactManager.frozenContacts(matching: "mail", fetchLimit: nil, sorted: nil)
// THEN
XCTAssertEqual(matchingContacts.isEmpty, false)
}
Expand Down
3 changes: 2 additions & 1 deletion MailTests/Folders/ITFolderListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ struct MCKContactManageable_FolderListViewModel: ContactManageable, MCKTransacti

let transactionExecutor: Transactionable!

func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MailCore.MergedContact> { [] }
func frozenContacts(matching string: String, fetchLimit: Int?,
sorted: ((MergedContact, MergedContact) -> Bool)?) -> any Collection<MailCore.MergedContact> { [] }

func getContact(for correspondent: any MailCore.Correspondent) -> MailCore.MergedContact? { nil }

Expand Down
3 changes: 2 additions & 1 deletion MailTests/Search/ITSearchViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ struct MCKContactManageable_SearchViewModel: ContactManageable, MCKTransactionab
transactionExecutor = TransactionExecutor(realmAccessible: realmAccessor)
}

func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MailCore.MergedContact> { [] }
func frozenContacts(matching string: String, fetchLimit: Int?,
sorted: ((MergedContact, MergedContact) -> Bool)?) -> any Collection<MailCore.MergedContact> { [] }

func getContact(for correspondent: any MailCore.Correspondent) -> MailCore.MergedContact? { nil }

Expand Down

0 comments on commit a611879

Please sign in to comment.