diff options
| author | Fuwn <[email protected]> | 2025-03-15 23:09:47 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-03-15 23:09:47 -0700 |
| commit | e801cdd4e8581af30c7f7af6b28dab6dd92c985b (patch) | |
| tree | 3f523f3e76655052bd3c47ab0c85b3ca72c5c82f | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-e801cdd4e8581af30c7f7af6b28dab6dd92c985b.tar.xz sora-testing-e801cdd4e8581af30c7f7af6b28dab6dd92c985b.zip | |
feat: Development commit
| -rw-r--r-- | Sora/Data/Settings/SettingsManager.swift | 222 |
1 files changed, 158 insertions, 64 deletions
diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift index b2749e1..63a6223 100644 --- a/Sora/Data/Settings/SettingsManager.swift +++ b/Sora/Data/Settings/SettingsManager.swift @@ -1,6 +1,8 @@ +// swiftlint:disable file_length + import SwiftUI -class SettingsManager: ObservableObject { +class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_length // MARK: - Stored Properties @AppStorage("detailViewType") var detailViewQuality: BooruPostFileType = .original @@ -55,31 +57,22 @@ class SettingsManager: ObservableObject { // MARK: - Computed Properties var bookmarks: [SettingsBookmark] { get { - if enableICloudSync { - if let data = NSUbiquitousKeyValueStore.default.data(forKey: "bookmarks") { - return (Self.decode([SettingsBookmark].self, from: data) ?? []) - .sorted { $0.date > $1.date } - } - - return (Self.decode([SettingsBookmark].self, from: bookmarksData) ?? []) - .sorted { $0.date > $1.date } - } - - return (Self.decode([SettingsBookmark].self, from: bookmarksData) ?? []) - .sorted { $0.date > $1.date } + syncableData( + key: "bookmarks", + localData: bookmarksData, + sort: { $0.sorted { $0.date > $1.date } }, + identifier: { $0.id } + ) } set { - let sortedBookmarks = newValue.sorted { $0.date > $1.date } - - bookmarksData = Self.encode(sortedBookmarks) ?? Data() - - if enableICloudSync { - NSUbiquitousKeyValueStore.default.set( - Self.encode(sortedBookmarks), - forKey: "bookmarks" - ) - } + syncableData( + key: "bookmarks", + localData: $bookmarksData, + newValue: newValue, + sort: { $0.sorted { $0.date > $1.date } }, + identifier: { $0.id } + ) } } @@ -99,30 +92,22 @@ class SettingsManager: ObservableObject { var searchHistory: [BooruSearchQuery] { get { - if enableICloudSync { - if let data = NSUbiquitousKeyValueStore.default.data(forKey: "searchHistory") { - return (Self.decode([BooruSearchQuery].self, from: data) ?? []) - .sorted { $0.date > $1.date } - } - - return (Self.decode([BooruSearchQuery].self, from: searchHistoryData) ?? []) - .sorted { $0.date > $1.date } - } - - return (Self.decode([BooruSearchQuery].self, from: searchHistoryData) ?? []) - .sorted { $0.date > $1.date } + syncableData( + key: "searchHistory", + localData: searchHistoryData, + sort: { $0.sorted { $0.date > $1.date } }, + identifier: { $0.id } + ) } set { - let sortedHistory = newValue.sorted { $0.date > $1.date } - - searchHistoryData = Self.encode(sortedHistory) ?? Data() - - if enableICloudSync { - NSUbiquitousKeyValueStore.default.set( - Self.encode(sortedHistory), forKey: "searchHistory" - ) - } + syncableData( + key: "searchHistory", + localData: $searchHistoryData, + newValue: newValue, + sort: { $0.sorted { $0.date > $1.date } }, + identifier: { $0.id } + ) } } @@ -136,26 +121,22 @@ class SettingsManager: ObservableObject { var customProviders: [BooruProviderCustom] { get { - if enableICloudSync { - if let data = NSUbiquitousKeyValueStore.default.data(forKey: "customProviders") { - return Self.decode([BooruProviderCustom].self, from: data) ?? [] - } - - return Self.decode([BooruProviderCustom].self, from: customProvidersData) ?? [] - } - - return Self.decode([BooruProviderCustom].self, from: customProvidersData) ?? [] + syncableData( + key: "customProviders", + localData: customProvidersData, + sort: { $0 }, + identifier: { $0.id } + ) } set { - customProvidersData = Self.encode(newValue) ?? Data() - - if enableICloudSync { - NSUbiquitousKeyValueStore.default.set( - Self.encode(newValue), - forKey: "customProviders" - ) - } + syncableData( + key: "customProviders", + localData: $customProvidersData, + newValue: newValue, + sort: { $0 }, + identifier: { $0.id } + ) } } @@ -193,6 +174,64 @@ class SettingsManager: ObservableObject { try? JSONDecoder().decode(type, from: data) } + private func syncableData<T: Codable>( + key: String, + localData: Data, + sort: ([T]) -> [T], + identifier: (T) -> UUID + ) -> [T] { + if enableICloudSync { + if let iCloudData = NSUbiquitousKeyValueStore.default.data(forKey: key) { + if let iCloudValues = Self.decode([T].self, from: iCloudData) { + let localValues = Self.decode([T].self, from: localData) ?? [] + let mergedValues = (localValues + iCloudValues) + .reduce(into: [T]()) { result, value in + if !result.contains(where: { identifier($0) == identifier(value) }) { + result.append(value) + } + } + + return sort(mergedValues) + } + } + } + + let localValues = Self.decode([T].self, from: localData) ?? [] + + return sort(localValues) + } + + private func syncableData<T: Codable>( + key: String, + localData: Binding<Data>, + newValue: [T], + sort: ([T]) -> [T], + identifier: (T) -> UUID + ) { + let sortedValues = sort(newValue) + + localData.wrappedValue = Self.encode(sortedValues) ?? Data() + + if enableICloudSync { + var iCloudValues: [T] = [] + + if let iCloudData = NSUbiquitousKeyValueStore.default.data(forKey: key) { + iCloudValues = Self.decode([T].self, from: iCloudData) ?? [] + } + + let filteredICloudValues = iCloudValues.filter { iCloudItem in + sortedValues.contains { identifier($0) == identifier(iCloudItem) } + } + let newLocalItems = sortedValues.filter { localItem in + !filteredICloudValues.contains { identifier($0) == identifier(localItem) } + } + let mergedValues = filteredICloudValues + newLocalItems + let sortedMergedValues = sort(mergedValues) + + NSUbiquitousKeyValueStore.default.set(Self.encode(sortedMergedValues), forKey: key) + } + } + // MARK: - Public Methods func appendToSearchHistory(_ query: BooruSearchQuery) { self.searchHistory.append(query) @@ -217,9 +256,64 @@ class SettingsManager: ObservableObject { func syncToICloud() { if enableICloudSync { - NSUbiquitousKeyValueStore.default.set(bookmarksData, forKey: "bookmarks") - NSUbiquitousKeyValueStore.default.set(searchHistoryData, forKey: "searchHistory") - NSUbiquitousKeyValueStore.default.set(customProvidersData, forKey: "customProviders") + // Merge bookmarks + var iCloudBookmarks: [SettingsBookmark] = [] + + if let iCloudData = NSUbiquitousKeyValueStore.default.data(forKey: "bookmarks") { + iCloudBookmarks = Self.decode([SettingsBookmark].self, from: iCloudData) ?? [] + } + + let localBookmarks = Self.decode([SettingsBookmark].self, from: bookmarksData) ?? [] + let mergedBookmarks = (localBookmarks + iCloudBookmarks) + .reduce(into: [SettingsBookmark]()) { result, value in + if !result.contains(where: { $0.id == value.id }) { + result.append(value) + } + } + .sorted { $0.date > $1.date } + + NSUbiquitousKeyValueStore.default.set(Self.encode(mergedBookmarks), forKey: "bookmarks") + + bookmarksData = Self.encode(mergedBookmarks) ?? Data() + + // Merge search history + var iCloudHistory: [BooruSearchQuery] = [] + + if let iCloudData = NSUbiquitousKeyValueStore.default.data(forKey: "searchHistory") { + iCloudHistory = Self.decode([BooruSearchQuery].self, from: iCloudData) ?? [] + } + + let localHistory = Self.decode([BooruSearchQuery].self, from: searchHistoryData) ?? [] + let mergedHistory = (localHistory + iCloudHistory) + .reduce(into: [BooruSearchQuery]()) { result, value in + if !result.contains(where: { $0.id == value.id }) { + result.append(value) + } + } + .sorted { $0.date > $1.date } + + NSUbiquitousKeyValueStore.default.set(Self.encode(mergedHistory), forKey: "searchHistory") + + searchHistoryData = Self.encode(mergedHistory) ?? Data() + + // Merge custom providers + var iCloudProviders: [BooruProviderCustom] = [] + + if let iCloudData = NSUbiquitousKeyValueStore.default.data(forKey: "customProviders") { + iCloudProviders = Self.decode([BooruProviderCustom].self, from: iCloudData) ?? [] + } + + let localProviders = Self.decode([BooruProviderCustom].self, from: customProvidersData) ?? [] + let mergedProviders = (localProviders + iCloudProviders) + .reduce(into: [BooruProviderCustom]()) { result, value in + if !result.contains(where: { $0.id == value.id }) { + result.append(value) + } + } + + NSUbiquitousKeyValueStore.default.set(Self.encode(mergedProviders), forKey: "customProviders") + + customProvidersData = Self.encode(mergedProviders) ?? Data() } } |