Просмотр исходного кода

Use background task for cancelling Overrides

polscm32 1 год назад
Родитель
Сommit
0f3dcc2e9a
1 измененных файлов с 77 добавлено и 57 удалено
  1. 77 57
      FreeAPS/Sources/Shortcuts/Override/OverridePresetsIntentRequest.swift

+ 77 - 57
FreeAPS/Sources/Shortcuts/Override/OverridePresetsIntentRequest.swift

@@ -78,7 +78,7 @@ import UIKit
     }
 
     @MainActor func enactOverride(_ preset: OverridePreset) async -> Bool {
-        // Start background task to ensure that the task can run in background mode
+        // Start background task
         var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
         backgroundTaskID = await UIApplication.shared.beginBackgroundTask(withName: "Override Upload") {
             guard backgroundTaskID != .invalid else { return }
@@ -89,14 +89,21 @@ import UIKit
             backgroundTaskID = .invalid
         }
 
+        // Defer block to end background task when function exits
+        defer {
+            if backgroundTaskID != .invalid {
+                Task {
+                    await UIApplication.shared.endBackgroundTask(backgroundTaskID)
+                }
+                backgroundTaskID = .invalid
+            }
+        }
+
         do {
+            // Get NSManagedObjectID of Preset
             guard let overrideID = await fetchOverrideID(preset),
                   let overrideObject = try viewContext.existingObject(with: overrideID) as? OverrideStored
-            else {
-                // Be sure to end background task if error occurs
-                await UIApplication.shared.endBackgroundTask(backgroundTaskID)
-                return false
-            }
+            else { return false }
 
             // Enable Override
             overrideObject.enabled = true
@@ -117,18 +124,13 @@ import UIKit
                 await awaitNotification(.didUpdateOverrideConfiguration)
                 print("Notification received, continuing...")
 
-                // End background task after everything is done
-                await UIApplication.shared.endBackgroundTask(backgroundTaskID)
                 return true
             }
         } catch {
             // Handle error and ensure background task is ended
             debugPrint("Failed to enact Override: \(error.localizedDescription)")
-            await UIApplication.shared.endBackgroundTask(backgroundTaskID)
         }
 
-        // Make sure background task ends in any case
-        await UIApplication.shared.endBackgroundTask(backgroundTaskID)
         return false
     }
 
@@ -140,59 +142,77 @@ import UIKit
         except overrideID: NSManagedObjectID? = nil,
         createOverrideRunEntry _: Bool
     ) async {
-        // Get ALL NSManagedObject IDs of ALL active Overrides to cancel every single Override
-        let ids = await overrideStorage.loadLatestOverrideConfigurations(fetchLimit: 0) // 0 = no fetch limit
+        // Start background task
+        var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
+        backgroundTaskID = await UIApplication.shared.beginBackgroundTask(withName: "Override Cancel") {
+            guard backgroundTaskID != .invalid else { return }
+            Task {
+                // End background task when the time is about to expire
+                await UIApplication.shared.endBackgroundTask(backgroundTaskID)
+            }
+            backgroundTaskID = .invalid
+        }
 
-        await viewContext.perform {
-            do {
-                // Fetch the existing OverrideStored objects from the context
-                let results = try ids.compactMap { id in
-                    try self.viewContext.existingObject(with: id) as? OverrideStored
+        // Defer block to end background task when function exits
+        defer {
+            if backgroundTaskID != .invalid {
+                Task {
+                    await UIApplication.shared.endBackgroundTask(backgroundTaskID)
                 }
+                backgroundTaskID = .invalid
+            }
+        }
 
-                // If there are no results, return early
-                guard !results.isEmpty else { return }
-
-                // Check if we also need to create a corresponding OverrideRunStored entry, i.e. when the User uses the Cancel Button in Override View
-                // Auggie - commented out this if statment, we always need to do this for overrides
-                // if createOverrideRunEntry {
-                // Use the first override to create a new OverrideRunStored entry
-                if let canceledOverride = results.first {
-                    let newOverrideRunStored = OverrideRunStored(context: self.viewContext)
-                    newOverrideRunStored.id = UUID()
-                    newOverrideRunStored.name = canceledOverride.name
-                    newOverrideRunStored.startDate = canceledOverride.date ?? .distantPast
-                    newOverrideRunStored.endDate = Date()
-                    newOverrideRunStored
-                        .target = NSDecimalNumber(
-                            decimal: self.overrideStorage
-                                .calculateTarget(override: canceledOverride)
-                        )
-                    newOverrideRunStored.override = canceledOverride
-                    newOverrideRunStored.isUploadedToNS = false
-                }
-                // }
-
-                // Disable all override except the one with overrideID
-                for overrideToCancel in results {
-                    if overrideToCancel.objectID != overrideID {
-                        overrideToCancel.enabled = false
-                        overrideToCancel.isUploadedToNS = false
-                    }
-                }
+        // Get NSManagedObjectID of all active overrides
+        let ids = await overrideStorage.loadLatestOverrideConfigurations(fetchLimit: 0) // 0 = no fetch limit
 
-                // Save the context if there are changes
-                if self.viewContext.hasChanges {
-                    try self.viewContext.save()
+        do {
+            // Fetch existing OverrideStored objects
+            let results = try ids.compactMap { id in
+                try self.viewContext.existingObject(with: id) as? OverrideStored
+            }
 
-                    // Update State variables in OverrideView
-                    Foundation.NotificationCenter.default.post(name: .didUpdateOverrideConfiguration, object: nil)
-                }
-            } catch {
-                debugPrint(
-                    "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to disable active Overrides with error: \(error.localizedDescription)"
+            // Return early if no results (background task remains active until defer block executes)
+            guard !results.isEmpty else { return }
+
+            // Create OverrideRunStored entry if needed
+            if let canceledOverride = results.first {
+                let newOverrideRunStored = OverrideRunStored(context: viewContext)
+                newOverrideRunStored.id = UUID()
+                newOverrideRunStored.name = canceledOverride.name
+                newOverrideRunStored.startDate = canceledOverride.date ?? .distantPast
+                newOverrideRunStored.endDate = Date()
+                newOverrideRunStored.target = NSDecimalNumber(
+                    decimal: overrideStorage.calculateTarget(override: canceledOverride)
                 )
+                newOverrideRunStored.override = canceledOverride
+                newOverrideRunStored.isUploadedToNS = false
+            }
+
+            // Disable all overrides except the one specified
+            for overrideToCancel in results {
+                if overrideToCancel.objectID != overrideID {
+                    overrideToCancel.enabled = false
+                    overrideToCancel.isUploadedToNS = false
+                }
             }
+
+            if viewContext.hasChanges {
+                try viewContext.save()
+
+                // Update State variables in OverrideView
+                Foundation.NotificationCenter.default.post(name: .willUpdateOverrideConfiguration, object: nil)
+            }
+
+            // Await the notification
+            print("Waiting for notification...")
+            await awaitNotification(.didUpdateOverrideConfiguration)
+            print("Notification received, continuing...")
+
+        } catch {
+            debugPrint(
+                "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to disable active Overrides with error: \(error.localizedDescription)"
+            )
         }
     }
 }