import Foundation import BackgroundTasks final class BackgroundTaskManager { static let backupTaskID = "com.albert.nasbackup.backup" static let refreshTaskID = "com.albert.nasbackup.refresh" static func registerTasks() { BGTaskScheduler.shared.register( forTaskWithIdentifier: backupTaskID, using: nil ) { task in guard let task = task as? BGProcessingTask else { return } BackgroundTaskManager.handleBackupTask(task) } BGTaskScheduler.shared.register( forTaskWithIdentifier: refreshTaskID, using: nil ) { task in guard let task = task as? BGAppRefreshTask else { return } BackgroundTaskManager.handleRefreshTask(task) } } static func scheduleBackup(delay: TimeInterval = 30) { let request = BGProcessingTaskRequest(identifier: backupTaskID) request.requiresNetworkConnectivity = true request.requiresExternalPower = false request.earliestBeginDate = Date(timeIntervalSinceNow: delay) do { try BGTaskScheduler.shared.submit(request) } catch { print("BGTask schedule failed: \(error)") } } static func scheduleAppRefresh() { let request = BGAppRefreshTaskRequest(identifier: refreshTaskID) request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) do { try BGTaskScheduler.shared.submit(request) } catch { print("BGRefresh schedule failed: \(error)") } } private static func handleBackupTask(_ task: BGProcessingTask) { scheduleBackup() let engine = BackupEngine.shared task.expirationHandler = { Task { await engine.cancel() } } Task { do { let store = ConnectionStore.shared guard let connection = store.savedConnection else { task.setTaskCompleted(success: false) return } let filter = store.backupFilter _ = try await engine.run(connection: connection, filter: filter, triggeredByLAN: true) task.setTaskCompleted(success: true) } catch { task.setTaskCompleted(success: false) } } } private static func handleRefreshTask(_ task: BGAppRefreshTask) { scheduleAppRefresh() task.setTaskCompleted(success: true) } }