From 30aa66bf2a12f007785014e6d8e8aadea660c8f4 Mon Sep 17 00:00:00 2001 From: Francesco <100066266+cranci1@users.noreply.github.com> Date: Sun, 25 May 2025 13:26:48 +0200 Subject: [PATCH] Revert "test backup system" This reverts commit 18075308dd88a4c77d3848a6327b101ebe545dff. --- Sora/Utils/Backups/BackupData.swift | 115 ----------------- Sora/Utils/Backups/BackupManager.swift | 88 ------------- Sora/Utils/Extensions/DateFormatter.swift | 16 --- Sora/Utils/Extensions/Notification+Name.swift | 1 - .../SettingsSubViews/SettingsViewData.swift | 118 +++--------------- Sulfur.xcodeproj/project.pbxproj | 22 +--- 6 files changed, 16 insertions(+), 344 deletions(-) delete mode 100644 Sora/Utils/Backups/BackupData.swift delete mode 100644 Sora/Utils/Backups/BackupManager.swift delete mode 100644 Sora/Utils/Extensions/DateFormatter.swift diff --git a/Sora/Utils/Backups/BackupData.swift b/Sora/Utils/Backups/BackupData.swift deleted file mode 100644 index 2f30dd8..0000000 --- a/Sora/Utils/Backups/BackupData.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// BackupData.swift -// Sulfur -// -// Created by Francesco on 25/05/25. -// - -import Foundation -import SwiftUI - -struct BackupData: Codable { - let version: String - let timestamp: Date - let userData: [String: Any] - - init(userData: [String: Any]) { - self.version = "1.0" - self.timestamp = Date() - self.userData = userData - } - - enum CodingKeys: String, CodingKey { - case version, timestamp, userData - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - version = try container.decode(String.self, forKey: .version) - timestamp = try container.decode(Date.self, forKey: .timestamp) - - let userDataContainer = try container.nestedContainer(keyedBy: DynamicKey.self, forKey: .userData) - var userData: [String: Any] = [:] - - for key in userDataContainer.allKeys { - userData[key.stringValue] = try userDataContainer.decode(AnyCodable.self, forKey: key).value - } - - self.userData = userData - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(version, forKey: .version) - try container.encode(timestamp, forKey: .timestamp) - - var userDataContainer = container.nestedContainer(keyedBy: DynamicKey.self, forKey: .userData) - for (key, value) in userData { - let dynamicKey = DynamicKey(stringValue: key)! - try userDataContainer.encode(AnyCodable(value), forKey: dynamicKey) - } - } -} - -struct DynamicKey: CodingKey { - var stringValue: String - var intValue: Int? - - init?(stringValue: String) { - self.stringValue = stringValue - } - - init?(intValue: Int) { - self.intValue = intValue - self.stringValue = String(intValue) - } -} - -struct AnyCodable: Codable { - let value: Any - - init(_ value: Any) { - self.value = value - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - if let bool = try? container.decode(Bool.self) { - value = bool - } else if let int = try? container.decode(Int.self) { - value = int - } else if let double = try? container.decode(Double.self) { - value = double - } else if let string = try? container.decode(String.self) { - value = string - } else if let array = try? container.decode([AnyCodable].self) { - value = array.map { $0.value } - } else if let dictionary = try? container.decode([String: AnyCodable].self) { - value = dictionary.mapValues { $0.value } - } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: "Unsupported type") - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - - switch value { - case let bool as Bool: - try container.encode(bool) - case let int as Int: - try container.encode(int) - case let double as Double: - try container.encode(double) - case let string as String: - try container.encode(string) - case let array as [Any]: - try container.encode(array.map { AnyCodable($0) }) - case let dictionary as [String: Any]: - try container.encode(dictionary.mapValues { AnyCodable($0) }) - default: - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: container.codingPath, debugDescription: "Unsupported type")) - } - } -} diff --git a/Sora/Utils/Backups/BackupManager.swift b/Sora/Utils/Backups/BackupManager.swift deleted file mode 100644 index 3a3f377..0000000 --- a/Sora/Utils/Backups/BackupManager.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// BackupManager.swift -// Sulfur -// -// Created by Francesco on 25/05/25. -// - -import Foundation - -class BackupManager: ObservableObject { - static let shared = BackupManager() - - private init() {} - - func createBackup() -> BackupData { - var userData: [String: Any] = [:] - - let userDefaults = UserDefaults.standard - let defaultsDict = userDefaults.dictionaryRepresentation() - - let appKeys = defaultsDict.keys.filter { key in - !key.hasPrefix("Apple") && - !key.hasPrefix("NS") && - !key.hasPrefix("com.apple") && - !key.contains("Keyboard") - } - - for key in appKeys { - userData[key] = defaultsDict[key] - } - - return BackupData(userData: userData) - } - - func exportBackup() -> URL? { - let backup = createBackup() - - do { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .iso8601 - encoder.outputFormatting = .prettyPrinted - - let data = try encoder.encode(backup) - - let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] - let fileName = "sora_backup_\(DateFormatter.backupFormatter.string(from: Date())).json" - let fileURL = documentsPath.appendingPathComponent(fileName) - - try data.write(to: fileURL) - return fileURL - - } catch { - print("Failed to export backup: \(error)") - return nil - } - } - - func importBackup(from url: URL) -> Bool { - do { - let data = try Data(contentsOf: url) - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .iso8601 - - let backup = try decoder.decode(BackupData.self, from: data) - - let userDefaults = UserDefaults.standard - for (key, value) in backup.userData { - userDefaults.set(value, forKey: key) - } - - userDefaults.synchronize() - - - NotificationCenter.default.post(name: .backupRestored, object: nil) - - return true - - } catch { - print("Failed to import backup: \(error)") - return false - } - } - - func shareBackup() -> URL? { - return exportBackup() - } -} - diff --git a/Sora/Utils/Extensions/DateFormatter.swift b/Sora/Utils/Extensions/DateFormatter.swift deleted file mode 100644 index a82db22..0000000 --- a/Sora/Utils/Extensions/DateFormatter.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// DateFormatter.swift -// Sulfur -// -// Created by Francesco on 25/05/25. -// - -import Foundation - -extension DateFormatter { - static let backupFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy-MM-dd_HH-mm-ss" - return formatter - }() -} diff --git a/Sora/Utils/Extensions/Notification+Name.swift b/Sora/Utils/Extensions/Notification+Name.swift index 6f5d6a7..2e87c5c 100644 --- a/Sora/Utils/Extensions/Notification+Name.swift +++ b/Sora/Utils/Extensions/Notification+Name.swift @@ -13,5 +13,4 @@ extension Notification.Name { static let ContinueWatchingDidUpdate = Notification.Name("ContinueWatchingDidUpdate") static let DownloadManagerStatusUpdate = Notification.Name("DownloadManagerStatusUpdate") static let modulesSyncDidComplete = Notification.Name("modulesSyncDidComplete") - static let backupRestored = Notification.Name("backupRestored") } diff --git a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewData.swift b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewData.swift index 1804f20..e6a5b19 100644 --- a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewData.swift +++ b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewData.swift @@ -6,7 +6,6 @@ // import SwiftUI -import UniformTypeIdentifiers struct SettingsViewData: View { @State private var showEraseAppDataAlert = false @@ -19,41 +18,14 @@ struct SettingsViewData: View { @State private var movPkgSize: Int64 = 0 @State private var showRemoveMovPkgAlert = false + // State bindings for cache settings @State private var isMetadataCachingEnabled: Bool = true @State private var isImageCachingEnabled: Bool = true @State private var isMemoryOnlyMode: Bool = false - @StateObject private var backupManager = BackupManager.shared - @State private var showingExportSuccess = false - @State private var showingImportSuccess = false - @State private var showingError = false - @State private var errorMessage = "" - @State private var showingFilePicker = false - @State private var showingShareSheet = false - @State private var backupURL: URL? - var body: some View { Form { - Section(header: Text("Backup & Restore"), footer: Text("Create backups to transfer your data to another device or restore from a previous backup.")) { - Button(action: exportBackup) { - HStack { - Image(systemName: "square.and.arrow.up") - .foregroundColor(.blue) - Text("Create Backup") - Spacer() - } - } - - Button(action: { showingFilePicker = true }) { - HStack { - Image(systemName: "square.and.arrow.down") - .foregroundColor(.green) - Text("Restore from Backup") - Spacer() - } - } - } - + // New section for cache settings Section(header: Text("Cache Settings"), footer: Text("Caching helps reduce network usage and load content faster. You can disable it to save storage space.")) { Toggle("Enable Metadata Caching", isOn: $isMetadataCachingEnabled) .onChange(of: isMetadataCachingEnabled) { newValue in @@ -76,6 +48,7 @@ struct SettingsViewData: View { .onChange(of: isMemoryOnlyMode) { newValue in MetadataCacheManager.shared.isMemoryOnlyMode = newValue if newValue { + // Clear disk cache when switching to memory-only MetadataCacheManager.shared.clearAllCache() calculateCacheSize() } @@ -145,42 +118,13 @@ struct SettingsViewData: View { .navigationTitle("App Data") .navigationViewStyle(StackNavigationViewStyle()) .onAppear { + // Initialize state with current values isMetadataCachingEnabled = MetadataCacheManager.shared.isCachingEnabled isImageCachingEnabled = KingfisherCacheManager.shared.isCachingEnabled isMemoryOnlyMode = MetadataCacheManager.shared.isMemoryOnlyMode calculateCacheSize() updateSizes() } - .fileImporter( - isPresented: $showingFilePicker, - allowedContentTypes: [UTType.json], - allowsMultipleSelection: false - ) { result in - handleFileImport(result) - } - .sheet(isPresented: $showingShareSheet) { - if let url = backupURL { - ShareSheet(items: [url]) - } - } - .alert("Backup Created", isPresented: $showingExportSuccess) { - Button("Share") { - showingShareSheet = true - } - Button("OK") { } - } message: { - Text("Your backup has been created successfully. You can share it or find it in your Files app.") - } - .alert("Backup Restored", isPresented: $showingImportSuccess) { - Button("OK") { } - } message: { - Text("Your data has been restored successfully. The app will refresh with your restored settings.") - } - .alert("Error", isPresented: $showingError) { - Button("OK") { } - } message: { - Text(errorMessage) - } .alert(isPresented: $showEraseAppDataAlert) { Alert( title: Text("Erase App Data"), @@ -213,51 +157,24 @@ struct SettingsViewData: View { } } - private func exportBackup() { - guard let url = backupManager.exportBackup() else { - errorMessage = "Failed to create backup file" - showingError = true - return - } - - backupURL = url - showingExportSuccess = true - } - - private func handleFileImport(_ result: Result<[URL], Error>) { - switch result { - case .success(let urls): - guard let url = urls.first else { return } - - if backupManager.importBackup(from: url) { - showingImportSuccess = true - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - isMetadataCachingEnabled = MetadataCacheManager.shared.isCachingEnabled - isImageCachingEnabled = KingfisherCacheManager.shared.isCachingEnabled - isMemoryOnlyMode = MetadataCacheManager.shared.isMemoryOnlyMode - } - } else { - errorMessage = "Failed to restore backup. Please check if the file is a valid Sora backup." - showingError = true - } - - case .failure(let error): - errorMessage = "Failed to read backup file: \(error.localizedDescription)" - showingError = true - } - } + // Calculate and update the combined cache size func calculateCacheSize() { isCalculatingSize = true cacheSizeText = "Calculating..." + // Group all cache size calculations DispatchQueue.global(qos: .background).async { var totalSize: Int64 = 0 + + // Get metadata cache size let metadataSize = MetadataCacheManager.shared.getCacheSize() totalSize += metadataSize + // Get image cache size asynchronously KingfisherCacheManager.shared.calculateCacheSize { imageSize in totalSize += Int64(imageSize) + // Update the UI on the main thread DispatchQueue.main.async { self.cacheSizeText = KingfisherCacheManager.formatCacheSize(UInt(totalSize)) self.isCalculatingSize = false @@ -266,9 +183,14 @@ struct SettingsViewData: View { } } + // Clear all caches (both metadata and images) func clearAllCaches() { + // Clear metadata cache MetadataCacheManager.shared.clearAllCache() + + // Clear image cache KingfisherCacheManager.shared.clearCache { + // Update cache size after clearing calculateCacheSize() } @@ -392,13 +314,3 @@ struct SettingsViewData: View { return totalSize } } - -struct ShareSheet: UIViewControllerRepresentable { - let items: [Any] - - func makeUIViewController(context: Context) -> UIActivityViewController { - UIActivityViewController(activityItems: items, applicationActivities: nil) - } - - func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {} -} diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index 8cb6030..c4553d9 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -18,9 +18,6 @@ 132AF1232D9995C300A0140B /* JSController-Details.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1222D9995C300A0140B /* JSController-Details.swift */; }; 132AF1252D9995F900A0140B /* JSController-Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1242D9995F900A0140B /* JSController-Search.swift */; }; 132FC5B32DE31DAE009A80F7 /* SettingsViewAlternateAppIconPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132FC5B22DE31DAD009A80F7 /* SettingsViewAlternateAppIconPicker.swift */; }; - 132FC5BB2DE333D3009A80F7 /* BackupData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132FC5BA2DE333D3009A80F7 /* BackupData.swift */; }; - 132FC5BD2DE333F4009A80F7 /* DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132FC5BC2DE333F4009A80F7 /* DateFormatter.swift */; }; - 132FC5BF2DE33410009A80F7 /* BackupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132FC5BE2DE33410009A80F7 /* BackupManager.swift */; }; 133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6D2D2BE2500075467E /* SoraApp.swift */; }; 133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; }; 133D7C722D2BE2520075467E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 133D7C712D2BE2520075467E /* Assets.xcassets */; }; @@ -101,9 +98,6 @@ 132AF1222D9995C300A0140B /* JSController-Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Details.swift"; sourceTree = ""; }; 132AF1242D9995F900A0140B /* JSController-Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Search.swift"; sourceTree = ""; }; 132FC5B22DE31DAD009A80F7 /* SettingsViewAlternateAppIconPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewAlternateAppIconPicker.swift; sourceTree = ""; }; - 132FC5BA2DE333D3009A80F7 /* BackupData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupData.swift; sourceTree = ""; }; - 132FC5BC2DE333F4009A80F7 /* DateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatter.swift; sourceTree = ""; }; - 132FC5BE2DE33410009A80F7 /* BackupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupManager.swift; sourceTree = ""; }; 133D7C6A2D2BE2500075467E /* Sulfur.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sulfur.app; sourceTree = BUILT_PRODUCTS_DIR; }; 133D7C6D2D2BE2500075467E /* SoraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraApp.swift; sourceTree = ""; }; 133D7C6F2D2BE2500075467E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -219,15 +213,6 @@ path = Analytics; sourceTree = ""; }; - 132FC5B92DE333BD009A80F7 /* Backups */ = { - isa = PBXGroup; - children = ( - 132FC5BA2DE333D3009A80F7 /* BackupData.swift */, - 132FC5BE2DE33410009A80F7 /* BackupManager.swift */, - ); - path = Backups; - sourceTree = ""; - }; 133D7C612D2BE2500075467E = { isa = PBXGroup; children = ( @@ -309,10 +294,9 @@ 133D7C852D2BE2640075467E /* Utils */ = { isa = PBXGroup; children = ( - 13D842532D45266900EBBFA6 /* Drops */, 7205AEDA2DCCEF9500943F3F /* Cache */, + 13D842532D45266900EBBFA6 /* Drops */, 1399FAD12D3AB33D00E97C31 /* Logger */, - 132FC5B92DE333BD009A80F7 /* Backups */, 133D7C882D2BE2640075467E /* Modules */, 133D7C8A2D2BE2640075467E /* JSLoader */, 1327FBA52D758CEA00FC6689 /* Analytics */, @@ -331,7 +315,6 @@ 73D164D42D8B5B340011A360 /* JavaScriptCore+Extensions.swift */, 136BBE7F2DB1038000906B5E /* Notification+Name.swift */, 1327FBA82D758DEA00FC6689 /* UIDevice+Model.swift */, - 132FC5BC2DE333F4009A80F7 /* DateFormatter.swift */, 13637B892DE0EA1100BDA2FC /* UserDefaults.swift */, 133D7C872D2BE2640075467E /* URLSession.swift */, 1359ED132D76F49900C13034 /* finTopView.swift */, @@ -637,7 +620,6 @@ 13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */, 133D7C702D2BE2500075467E /* ContentView.swift in Sources */, 13D99CF72D4E73C300250A86 /* ModuleAdditionSettingsView.swift in Sources */, - 132FC5BF2DE33410009A80F7 /* BackupManager.swift in Sources */, 13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */, 13CBA0882D60F19C00EFE70A /* VTTSubtitlesLoader.swift in Sources */, 13EA2BD62D32D97400C1EBD7 /* Double+Extension.swift in Sources */, @@ -680,8 +662,6 @@ 72AC3A032DD4DAEB00C60B96 /* PerformanceMonitor.swift in Sources */, 72443C7F2DC8038300A61321 /* SettingsViewDownloads.swift in Sources */, 13DB46922D900BCE008CBC03 /* SettingsViewTrackers.swift in Sources */, - 132FC5BB2DE333D3009A80F7 /* BackupData.swift in Sources */, - 132FC5BD2DE333F4009A80F7 /* DateFormatter.swift in Sources */, 7222485F2DCBAA2C00CABE2D /* DownloadModels.swift in Sources */, 722248602DCBAA2C00CABE2D /* M3U8StreamExtractor.swift in Sources */, 13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */,