summaryrefslogtreecommitdiff
path: root/Sora/Views/SearchSuggestionsView.swift
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-18 12:33:44 -0800
committerFuwn <[email protected]>2026-02-18 12:33:50 -0800
commit0587c64598267ecace6259241198425cdc284f3a (patch)
treeba90872e872e90ae98096c1da81ceb5a66d5c476 /Sora/Views/SearchSuggestionsView.swift
parentrefactor: share folder menu hierarchy across views (diff)
downloadsora-testing-0587c64598267ecace6259241198425cdc284f3a.tar.xz
sora-testing-0587c64598267ecace6259241198425cdc284f3a.zip
perf: reduce suggestion and image handling hot-path overhead
Diffstat (limited to 'Sora/Views/SearchSuggestionsView.swift')
-rw-r--r--Sora/Views/SearchSuggestionsView.swift68
1 files changed, 43 insertions, 25 deletions
diff --git a/Sora/Views/SearchSuggestionsView.swift b/Sora/Views/SearchSuggestionsView.swift
index 03af4c6..e9593ec 100644
--- a/Sora/Views/SearchSuggestionsView.swift
+++ b/Sora/Views/SearchSuggestionsView.swift
@@ -9,13 +9,21 @@ struct SearchSuggestionsView: View {
var items: [Either<BooruTag, BooruSearchQuery>]
@Binding var searchText: String
@Binding var suppressNextSearchSubmit: Bool
+ @State private var cachedTags: [CachedTag] = []
private var lastSearchTag: String {
String(searchText.split(separator: " ").last ?? "").lowercased()
}
- private var cachedTags: [CachedTag] {
- items.map { item in
+ private var itemsCacheKey: Int {
+ items.reduce(into: Hasher()) { hasher, item in
+ hasher.combine(item)
+ }
+ .finalize()
+ }
+
+ private func refreshCachedTags() {
+ cachedTags = items.map { item in
switch item {
case .left(let tag):
return CachedTag(original: item, names: [tag.name.lowercased()])
@@ -53,36 +61,46 @@ struct SearchSuggestionsView: View {
}
var body: some View {
- ForEach(filteredItems, id: \.self) { item in
- switch item {
- case .left(let tag):
- Button {
- let previousTags = searchText.split(separator: " ").dropLast()
-
- suppressNextSearchSubmit = true
- searchText = (previousTags.map(String.init) + [tag.name]).joined(separator: " ")
- } label: {
- Text(tag.name)
- }
-
- case .right(let query):
- Button {
- if let matchingTag = query.tags.first(where: { $0.lowercased().contains(lastSearchTag) })
- {
+ Group {
+ ForEach(filteredItems, id: \.self) { item in
+ switch item {
+ case .left(let tag):
+ Button {
let previousTags = searchText.split(separator: " ").dropLast()
suppressNextSearchSubmit = true
- searchText = (previousTags.map(String.init) + [matchingTag]).joined(separator: " ")
+ searchText = (previousTags.map(String.init) + [tag.name]).joined(separator: " ")
+ } label: {
+ Text(tag.name)
}
- } label: {
- if let matchingTag = query.tags.first(where: { $0.lowercased().contains(lastSearchTag) })
- {
- Text(matchingTag)
- } else {
- Text(query.tags.first ?? "")
+
+ case .right(let query):
+ let matchingTag = query.tags.first { tag in
+ tag.lowercased().contains(lastSearchTag)
+ }
+
+ Button {
+ if let matchingTag {
+ let previousTags = searchText.split(separator: " ").dropLast()
+
+ suppressNextSearchSubmit = true
+ searchText = (previousTags.map(String.init) + [matchingTag]).joined(separator: " ")
+ }
+ } label: {
+ if let matchingTag {
+ Text(matchingTag)
+ } else {
+ Text(query.tags.first ?? "")
+ }
}
}
}
}
+ .onAppear {
+ refreshCachedTags()
+ }
+ .onChange(of: itemsCacheKey) {
+ refreshCachedTags()
+ }
}
}