summaryrefslogtreecommitdiff
path: root/Sora/Data/Settings
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-08-28 15:39:59 -0700
committerFuwn <[email protected]>2025-08-28 15:39:59 -0700
commitadd606fb0555a9a73f624e15e5fd916a49469ab8 (patch)
tree27ff8daf5e3fee1a97970ca9bc70f26ab690c570 /Sora/Data/Settings
parentfeat: Development commit (diff)
downloadsora-testing-add606fb0555a9a73f624e15e5fd916a49469ab8.tar.xz
sora-testing-add606fb0555a9a73f624e15e5fd916a49469ab8.zip
feat: Development commit
Diffstat (limited to 'Sora/Data/Settings')
-rw-r--r--Sora/Data/Settings/SettingsManager.swift146
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