diff options
| author | Fuwn <[email protected]> | 2025-08-28 15:39:59 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-08-28 15:39:59 -0700 |
| commit | add606fb0555a9a73f624e15e5fd916a49469ab8 (patch) | |
| tree | 27ff8daf5e3fee1a97970ca9bc70f26ab690c570 /Sora/Data/Settings | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-add606fb0555a9a73f624e15e5fd916a49469ab8.tar.xz sora-testing-add606fb0555a9a73f624e15e5fd916a49469ab8.zip | |
feat: Development commit
Diffstat (limited to 'Sora/Data/Settings')
| -rw-r--r-- | Sora/Data/Settings/SettingsManager.swift | 146 |
1 files changed, 129 insertions, 17 deletions
diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift index 53d699e..30fe587 100644 --- a/Sora/Data/Settings/SettingsManager.swift +++ b/Sora/Data/Settings/SettingsManager.swift @@ -5,7 +5,7 @@ import SwiftUI @MainActor class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_length // MARK: - Stored Properties - @AppStorage("detailViewType") + @AppStorage("detailViewQuality") var detailViewQuality: BooruPostFileType = .original @AppStorage("thumbnailQuality") @@ -49,6 +49,8 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l private var displayRatingsCache: [BooruRating] = [] private var uniformThumbnailGridCache: Bool = false private var thumbnailQualityCache: BooruPostFileType = .preview + private var isUpdatingCache = false + private var pendingSyncKeys: Set<SettingsSyncKey> = [] // MARK: - Codable Properties @AppStorage("bookmarks") @@ -80,12 +82,22 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l get { bookmarksCache } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "bookmarks", localData: $bookmarksData, newValue: newValue ) { $0.sorted { $0.date > $1.date } } - triggerSyncIfNeeded(for: .bookmarks) + + bookmarksCache = newValue.sorted { $0.date > $1.date } + + pendingSyncKeys.insert(.bookmarks) + triggerBatchedSync() } } @@ -111,7 +123,14 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l get { displayRatingsCache } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + displayRatingsData = Self.encode(newValue) ?? displayRatingsData + displayRatingsCache = newValue } } @@ -119,7 +138,14 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l get { blurRatingsCache } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + blurRatingsData = Self.encode(newValue) ?? blurRatingsData + blurRatingsCache = newValue } } @@ -127,12 +153,22 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l get { searchHistoryCache } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "searchHistory", localData: $searchHistoryData, newValue: newValue, ) { $0.sorted { $0.date > $1.date } } - triggerSyncIfNeeded(for: .searchHistory) + + searchHistoryCache = newValue.sorted { $0.date > $1.date } + + pendingSyncKeys.insert(.searchHistory) + triggerBatchedSync() } } @@ -155,12 +191,19 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "customProviders", localData: $customProvidersData, newValue: newValue, ) { $0 } - triggerSyncIfNeeded(for: .customProviders) + pendingSyncKeys.insert(.customProviders) + triggerBatchedSync() } } @@ -175,6 +218,12 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "folders", localData: $foldersData, @@ -195,6 +244,12 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l } set { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + let existingCredentials: [BooruProviderCredentials] = Self.decode([BooruProviderCredentials].self, from: providerCredentialsData) ?? [] let rawCredentials = newValue.map { credentials in @@ -266,39 +321,73 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l } func updateBookmarks(_ newValue: [SettingsBookmark]) async { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "bookmarks", localData: $bookmarksData, newValue: newValue ) { $0.sorted { $0.date > $1.date } } - loadBookmarksCache() + + bookmarksCache = newValue.sorted { $0.date > $1.date } + await backupBookmarks() - triggerSyncIfNeeded(for: .bookmarks) + pendingSyncKeys.insert(.bookmarks) + triggerBatchedSync() } func updateSearchHistory(_ newValue: [BooruSearchQuery]) { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + syncableData( key: "searchHistory", localData: $searchHistoryData, newValue: newValue, ) { $0.sorted { $0.date > $1.date } } - loadSearchHistoryCache() - triggerSyncIfNeeded(for: .searchHistory) + + searchHistoryCache = newValue.sorted { $0.date > $1.date } + + pendingSyncKeys.insert(.searchHistory) + triggerBatchedSync() } func updateDisplayRatings(_ newValue: [BooruRating]) { - displayRatingsData = Self.encode(newValue) ?? displayRatingsData + guard !isUpdatingCache else { return } - loadDisplayRatingsCache() + isUpdatingCache = true + + defer { isUpdatingCache = false } + + displayRatingsData = Self.encode(newValue) ?? displayRatingsData + displayRatingsCache = newValue } func updateBlurRatings(_ newValue: [BooruRating]) { - blurRatingsData = Self.encode(newValue) ?? blurRatingsData + guard !isUpdatingCache else { return } - loadBlurRatingsCache() + isUpdatingCache = true + + defer { isUpdatingCache = false } + + blurRatingsData = Self.encode(newValue) ?? blurRatingsData + blurRatingsCache = newValue } func updateProviderCredentials(_ newValue: [BooruProviderCredentials]) { + guard !isUpdatingCache else { return } + + isUpdatingCache = true + + defer { isUpdatingCache = false } + let existingCredentials: [BooruProviderCredentials] = Self.decode([BooruProviderCredentials].self, from: providerCredentialsData) ?? [] let rawCredentials = newValue.map { credentials in @@ -371,6 +460,24 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l } } + private func triggerBatchedSync() { + guard !pendingSyncKeys.isEmpty else { return } + + let keysToSync = pendingSyncKeys + + pendingSyncKeys.removeAll() + + Task.detached { [weak self] in + await self?.performBatchedSync(for: keysToSync) + } + } + + private func performBatchedSync(for keys: Set<SettingsSyncKey>) async { + for key in keys { + await triggerSyncIfNeeded(for: key) + } + } + private func backupBookmarks() async { await Task.detached { guard @@ -708,7 +815,8 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l await updateBookmarks(updated) } - triggerSyncIfNeeded(for: .bookmarks) + pendingSyncKeys.insert(.bookmarks) + triggerBatchedSync() } func updateBookmarkLastVisit(withID id: UUID, date: Date = Date()) { @@ -722,7 +830,8 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l await updateBookmarks(updated) } - triggerSyncIfNeeded(for: .bookmarks) + pendingSyncKeys.insert(.bookmarks) + triggerBatchedSync() } func incrementBookmarkVisitCount(withID id: UUID) { @@ -736,7 +845,8 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l await updateBookmarks(updated) } - triggerSyncIfNeeded(for: .bookmarks) + pendingSyncKeys.insert(.bookmarks) + triggerBatchedSync() } func folderName(forID id: UUID) -> String? { @@ -764,14 +874,16 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l updated.remove(atOffsets: offsets) updateSearchHistory(updated) - triggerSyncIfNeeded(for: .searchHistory) + pendingSyncKeys.insert(.searchHistory) + triggerBatchedSync() } func removeSearchHistoryEntry(withID id: UUID) { let updated = searchHistory.filter { $0.id != id } updateSearchHistory(updated) - triggerSyncIfNeeded(for: .searchHistory) + pendingSyncKeys.insert(.searchHistory) + triggerBatchedSync() } #if DEBUG |