Add trie-based user search cache to replace non-performant linear scans

Changelog-Added: Speed up user search
Tested-by: William Casarin <jb55@jb55.com>
Fixes: #1219
Closes: #1342
This commit is contained in:
2023-07-01 14:42:36 -04:00
committed by William Casarin
parent 4b7444f338
commit 6e964f71ff
13 changed files with 519 additions and 95 deletions

View File

@@ -8,7 +8,6 @@
import SwiftUI
struct SearchedUser: Identifiable {
let petname: String?
let profile: Profile?
let pubkey: String
@@ -28,11 +27,7 @@ struct UserSearch: View {
@EnvironmentObject var tagModel: TagModel
var users: [SearchedUser] {
guard let contacts = damus_state.contacts.event else {
return search_profiles(profiles: damus_state.profiles, search: search)
}
return search_users_for_autocomplete(profiles: damus_state.profiles, tags: contacts.tags, search: search)
return search_profiles(profiles: damus_state.profiles, search: search)
}
func on_user_tapped(user: SearchedUser) {
@@ -99,56 +94,6 @@ struct UserSearch_Previews: PreviewProvider {
}
}
func search_users_for_autocomplete(profiles: Profiles, tags: [[String]], search _search: String) -> [SearchedUser] {
var seen_user = Set<String>()
let search = _search.lowercased()
var matches = tags.reduce(into: Array<SearchedUser>()) { arr, tag in
guard tag.count >= 2 && tag[0] == "p" else {
return
}
let pubkey = tag[1]
guard !seen_user.contains(pubkey) else {
return
}
seen_user.insert(pubkey)
var petname: String? = nil
if tag.count >= 4 {
petname = tag[3]
}
let profile = profiles.lookup(id: pubkey)
guard ((petname?.lowercased().hasPrefix(search) ?? false) ||
(profile?.name?.lowercased().hasPrefix(search) ?? false) ||
(profile?.display_name?.lowercased().hasPrefix(search) ?? false)) else {
return
}
let searched_user = SearchedUser(petname: petname, profile: profile, pubkey: pubkey)
arr.append(searched_user)
}
// search profile cache as well
for tup in profiles.enumerated() {
let pk = tup.element.key
let prof = tup.element.value.profile
guard !seen_user.contains(pk) else {
continue
}
if let match = profile_search_matches(profiles: profiles, profile: prof, pubkey: pk, search: search) {
matches.append(match)
}
}
return matches
}
func user_tag_attr_string(profile: Profile?, pubkey: String) -> NSMutableAttributedString {
let display_name = Profile.displayName(profile: profile, pubkey: pubkey)
let name = display_name.username.truncate(maxLength: 50)