| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import CoreData
- import Foundation
- @available(iOS 16.0, *) final class OverridePresetsIntentRequest: BaseIntentsRequest {
- enum overridePresetsError: Error {
- case noTempOverrideFound
- case noDurationDefined
- case noActiveOverride
- }
- func fetchAndProcessOverrides() async -> [OverridePreset] {
- // Fetch all Override Presets via OverrideStorage
- let allOverridePresetsIDs = await overrideStorage.fetchForOverridePresets()
- // Since we are fetching on a different background Thread we need to unpack the NSManagedObjectID on the correct Thread first
- return await coredataContext.perform {
- do {
- let overrideObjects = try allOverridePresetsIDs.compactMap { id in
- try self.coredataContext.existingObject(with: id) as? OverrideStored
- }
- return overrideObjects.map { object in
- guard let id = object.id,
- let name = object.name else { return OverridePreset(id: UUID().uuidString, name: "") }
- return OverridePreset(id: id, name: name)
- }
- } catch {
- debugPrint(
- "\(#file) \(#function) \(DebuggingIdentifiers.failed) error while fetching/ processing the overrides Array: \(error.localizedDescription)"
- )
- return [OverridePreset(id: UUID().uuidString, name: "")]
- }
- }
- }
- func fetchIDs(_ uuid: [OverridePreset.ID]) async -> [OverridePreset] {
- await coredataContext.perform {
- let fetchRequest: NSFetchRequest<OverrideStored> = OverrideStored.fetchRequest()
- fetchRequest.predicate = NSPredicate(format: "id IN %@", uuid)
- do {
- let result = try self.coredataContext.fetch(fetchRequest)
- if result.isEmpty {
- debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) No OverrideStored found for ids: \(uuid)")
- return [OverridePreset(id: UUID().uuidString, name: "")]
- }
- return result.map { overrideStored in
- OverridePreset(id: overrideStored.id ?? UUID().uuidString, name: overrideStored.name ?? "")
- }
- } catch let error as NSError {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to fetch Override: \(error.localizedDescription)"
- )
- return [OverridePreset(id: UUID().uuidString, name: "")]
- }
- }
- }
- private func fetchOverrideID(_ preset: OverridePreset) async -> NSManagedObjectID? {
- let fetchRequest: NSFetchRequest<OverrideStored> = OverrideStored.fetchRequest()
- fetchRequest.predicate = NSPredicate(format: "id == %@", preset.id)
- fetchRequest.fetchLimit = 1
- return await coredataContext.perform {
- do {
- return try self.coredataContext.fetch(fetchRequest).first?.objectID
- } catch {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to fetch Override: \(error.localizedDescription)"
- )
- return nil
- }
- }
- }
- @MainActor func enactOverride(_ preset: OverridePreset) async -> Bool {
- do {
- guard let overrideID = await fetchOverrideID(preset),
- let overrideObject = try viewContext.existingObject(with: overrideID) as? OverrideStored else { return false }
- overrideObject.enabled = true
- overrideObject.date = Date()
- overrideObject.isUploadedToNS = false
- // Disable previous Overrides
- /// do not create a OverrideRunEntry because we only want that if we cancel a running Override, not when enacting a Preset
- await disableAllActiveOverrides(except: overrideID, createOverrideRunEntry: true)
- if viewContext.hasChanges {
- try viewContext.save()
- // Update State variables in OverrideView
- Foundation.NotificationCenter.default.post(name: .didUpdateOverrideConfiguration, object: nil)
- return true
- }
- } catch let error as NSError {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to enact Override: \(error.localizedDescription)"
- )
- }
- return false
- }
- func cancelOverride() async {
- await disableAllActiveOverrides(createOverrideRunEntry: true)
- }
- @MainActor func disableAllActiveOverrides(
- 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
- 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
- }
- // 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
- }
- }
- // Save the context if there are changes
- if self.viewContext.hasChanges {
- try self.viewContext.save()
- // 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)"
- )
- }
- }
- }
- }
|