diff --git a/Sora/SoraApp.swift b/Sora/SoraApp.swift index 9809d0e..7fe5b97 100644 --- a/Sora/SoraApp.swift +++ b/Sora/SoraApp.swift @@ -34,8 +34,9 @@ struct SoraApp: App { .accentColor(settings.accentColor) .onAppear { settings.updateAppearance() - if UserDefaults.standard.bool(forKey: "refreshModulesOnLaunch") { - Task { + iCloudSyncManager.shared.syncModulesFromiCloud() + Task { + if UserDefaults.standard.bool(forKey: "refreshModulesOnLaunch") { await moduleManager.refreshModules() } } @@ -97,4 +98,4 @@ struct SoraApp: App { Logger.shared.log("Unknown authentication service", type: "Error") } } -} \ No newline at end of file +} diff --git a/Sora/Utils/Modules/ModuleManager.swift b/Sora/Utils/Modules/ModuleManager.swift index 72ec704..9c1d48d 100644 --- a/Sora/Utils/Modules/ModuleManager.swift +++ b/Sora/Utils/Modules/ModuleManager.swift @@ -26,7 +26,7 @@ class ModuleManager: ObservableObject { DispatchQueue.main.async { self.loadModules() Task { - await self.cehckJSModuleFIle() + await self.checkJSModuleFiles() } Logger.shared.log("Reloaded modules after iCloud sync") } @@ -46,20 +46,26 @@ class ModuleManager: ObservableObject { modules = (try? JSONDecoder().decode([ScrapingModule].self, from: data)) ?? [] Task { - await cehckJSModuleFIle() + await checkJSModuleFiles() } } - func cehckJSModuleFIle() async { + func checkJSModuleFiles() async { + Logger.shared.log("Checking JS module files...", type: "Info") + var missingCount = 0 + for module in modules { let localUrl = getDocumentsDirectory().appendingPathComponent(module.localPath) - if (!fileManager.fileExists(atPath: localUrl.path)) { + if !fileManager.fileExists(atPath: localUrl.path) { + missingCount += 1 do { guard let scriptUrl = URL(string: module.metadata.scriptUrl) else { Logger.shared.log("Invalid script URL for module: \(module.metadata.sourceName)", type: "Error") continue } + Logger.shared.log("Downloading missing JS file for: \(module.metadata.sourceName)", type: "Info") + let (scriptData, _) = try await URLSession.custom.data(from: scriptUrl) guard let jsContent = String(data: scriptData, encoding: .utf8) else { Logger.shared.log("Invalid script encoding for module: \(module.metadata.sourceName)", type: "Error") @@ -67,12 +73,18 @@ class ModuleManager: ObservableObject { } try jsContent.write(to: localUrl, atomically: true, encoding: .utf8) - Logger.shared.log("Recovered missing JS file for module: \(module.metadata.sourceName)") + Logger.shared.log("Successfully downloaded JS file for module: \(module.metadata.sourceName)") } catch { - Logger.shared.log("Failed to recover JS file for module: \(module.metadata.sourceName) - \(error.localizedDescription)", type: "Error") + Logger.shared.log("Failed to download JS file for module: \(module.metadata.sourceName) - \(error.localizedDescription)", type: "Error") } } } + + if missingCount > 0 { + Logger.shared.log("Downloaded \(missingCount) missing module JS files", type: "Info") + } else { + Logger.shared.log("All module JS files are present", type: "Info") + } } private func saveModules() { diff --git a/Sora/Utils/iCloudSyncManager/iCloudSyncManager.swift b/Sora/Utils/iCloudSyncManager/iCloudSyncManager.swift index dead626..0f3c9cd 100644 --- a/Sora/Utils/iCloudSyncManager/iCloudSyncManager.swift +++ b/Sora/Utils/iCloudSyncManager/iCloudSyncManager.swift @@ -153,35 +153,42 @@ class iCloudSyncManager { } func syncModulesFromiCloud() { - DispatchQueue.global(qos: .background).async { - guard let iCloudURL = self.ubiquityContainerURL else { return } - let localModulesURL = self.getLocalModulesFileURL() - let iCloudModulesURL = iCloudURL.appendingPathComponent(self.modulesFileName) - do { - guard FileManager.default.fileExists(atPath: iCloudModulesURL.path) else { return } - - let shouldCopy: Bool - if FileManager.default.fileExists(atPath: localModulesURL.path) { - let localData = try Data(contentsOf: localModulesURL) - let iCloudData = try Data(contentsOf: iCloudModulesURL) - shouldCopy = localData != iCloudData - } else { - shouldCopy = true - } - - if shouldCopy { - if FileManager.default.fileExists(atPath: localModulesURL.path) { - try FileManager.default.removeItem(at: localModulesURL) - } - try FileManager.default.copyItem(at: iCloudModulesURL, to: localModulesURL) - - DispatchQueue.main.async { - NotificationCenter.default.post(name: .modulesSyncDidComplete, object: nil) - } - } - } catch { - Logger.shared.log("iCloud modules fetch error: \(error)", type: "Error") + guard let iCloudURL = self.ubiquityContainerURL else { + Logger.shared.log("iCloud container not available", type: "Warning") + return + } + + let localModulesURL = self.getLocalModulesFileURL() + let iCloudModulesURL = iCloudURL.appendingPathComponent(self.modulesFileName) + + do { + if !FileManager.default.fileExists(atPath: iCloudModulesURL.path) { + Logger.shared.log("No modules file found in iCloud", type: "Info") + return } + + let shouldCopy: Bool + if FileManager.default.fileExists(atPath: localModulesURL.path) { + let localData = try Data(contentsOf: localModulesURL) + let iCloudData = try Data(contentsOf: iCloudModulesURL) + shouldCopy = localData != iCloudData + } else { + shouldCopy = true + } + + if shouldCopy { + Logger.shared.log("Syncing modules from iCloud", type: "Info") + if FileManager.default.fileExists(atPath: localModulesURL.path) { + try FileManager.default.removeItem(at: localModulesURL) + } + try FileManager.default.copyItem(at: iCloudModulesURL, to: localModulesURL) + + DispatchQueue.main.async { + NotificationCenter.default.post(name: .modulesSyncDidComplete, object: nil) + } + } + } catch { + Logger.shared.log("iCloud modules fetch error: \(error)", type: "Error") } }