diff options
| author | Fuwn <[email protected]> | 2025-02-24 06:04:35 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-02-24 06:04:35 -0800 |
| commit | bb3adb028da4bf0f11790c5f081d199cae659201 (patch) | |
| tree | 02a4376e860277b59280894430eccaacac0064cd | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-bb3adb028da4bf0f11790c5f081d199cae659201.tar.xz sora-testing-bb3adb028da4bf0f11790c5f081d199cae659201.zip | |
feat: Development commit
| -rw-r--r-- | Sora/Data/Booru/BooruManager.swift | 43 | ||||
| -rw-r--r-- | Sora/Data/Booru/Tag/BooruTag.swift | 4 | ||||
| -rw-r--r-- | Sora/Views/SearchSuggestionsView.swift | 13 |
3 files changed, 53 insertions, 7 deletions
diff --git a/Sora/Data/Booru/BooruManager.swift b/Sora/Data/Booru/BooruManager.swift index 45a2240..00fb3d1 100644 --- a/Sora/Data/Booru/BooruManager.swift +++ b/Sora/Data/Booru/BooruManager.swift @@ -21,6 +21,14 @@ class BooruManager: ObservableObject { .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { !$0.isEmpty } } + private var tagsCacheFileURL: URL? { + guard let directory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first + else { + return nil + } + + return directory.appendingPathComponent("\(provider)_tags.json") + } #if os(macOS) @Published var selectedPost: BooruPost? @@ -29,6 +37,7 @@ class BooruManager: ObservableObject { init(_ provider: BooruProvider) { self.provider = provider + loadCachedTags() fetchAllTags() } @@ -103,7 +112,7 @@ class BooruManager: ObservableObject { } } - func fetchAllTags(limit: Int = 100_000) { + func fetchAllTags(limit: Int = 0) { Task { guard let url = urlForTags(limit: limit) else { return } @@ -114,6 +123,7 @@ class BooruManager: ObservableObject { DispatchQueue.main.async { self.allTags = BooruTagXMLParser(data: data).parse().sorted { $0.count > $1.count } + self.saveTagsToCache() } } catch { if (error as? URLError)?.code != .cancelled { @@ -170,6 +180,37 @@ class BooruManager: ObservableObject { } } + private func saveTagsToCache() { + guard let url = tagsCacheFileURL else { return } + + do { + let data = try JSONEncoder().encode(allTags) + + try data.write(to: url) + } catch { + #if DEBUG + print("saveTagsToCache: \(error)") + #endif + } + } + + private func loadCachedTags() { + guard let url = tagsCacheFileURL else { return } + + do { + let data = try Data(contentsOf: url) + let cachedTags = try JSONDecoder().decode([BooruTag].self, from: data) + + DispatchQueue.main.async { + self.allTags = cachedTags + } + } catch { + #if DEBUG + print("loadCachedTags: \(error)") + #endif + } + } + deinit { currentTask?.cancel() } diff --git a/Sora/Data/Booru/Tag/BooruTag.swift b/Sora/Data/Booru/Tag/BooruTag.swift index d603e9f..06de48a 100644 --- a/Sora/Data/Booru/Tag/BooruTag.swift +++ b/Sora/Data/Booru/Tag/BooruTag.swift @@ -1,6 +1,4 @@ -import Foundation - -struct BooruTag: Identifiable, Hashable { +struct BooruTag: Identifiable, Hashable, Encodable, Decodable { let id: String let name: String let count: Int diff --git a/Sora/Views/SearchSuggestionsView.swift b/Sora/Views/SearchSuggestionsView.swift index 34ccfbc..2a1a8d6 100644 --- a/Sora/Views/SearchSuggestionsView.swift +++ b/Sora/Views/SearchSuggestionsView.swift @@ -3,8 +3,13 @@ import SwiftUI struct SearchSuggestionsView: View { var tags: [BooruTag] @Binding var searchText: String - var lastSearchTag: String { - String(searchText.split(separator: " ").last ?? "") + private var lastSearchTag: String { + String(searchText.split(separator: " ").last ?? "").lowercased() + } + private var filteredTags: [BooruTag] { + guard !lastSearchTag.isEmpty else { return [] } + + return tags.filter { $0.name.lowercased().contains(lastSearchTag) } } var body: some View { @@ -14,7 +19,9 @@ struct SearchSuggestionsView: View { } ) { suggestion in Button { - searchText.replaceSubrange(searchText.range(of: lastSearchTag)!, with: suggestion.name) + if let range = searchText.range(of: lastSearchTag, options: .backwards) { + searchText.replaceSubrange(range, with: suggestion.name) + } } label: { Text(suggestion.name) } |