Browse Source

Refactor History (DataTable) to use only Core Data WIP

dnzxy 2 năm trước cách đây
mục cha
commit
277ba58bf1

+ 20 - 0
FreeAPS/Sources/APS/Storage/PumpHistoryStorage.swift

@@ -181,6 +181,26 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
                         )
                     ]
                 case .resume:
+                    self.context.perform {
+                        // create pump event
+                        let newPumpEvent = PumpEventStored(context: self.context)
+                        newPumpEvent.id = id
+                        newPumpEvent.timestamp = event.date
+                        newPumpEvent.type = PumpEvent.pumpResume.rawValue
+
+                        if self.context.hasChanges {
+                            do {
+                                try self.context.save()
+                                debugPrint(
+                                    "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved pump resumption to core data"
+                                )
+                            } catch {
+                                debugPrint(
+                                    "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save pump resumption to core data"
+                                )
+                            }
+                        }
+                    }
                     return [
                         PumpHistoryEvent(
                             id: id,

+ 2 - 1
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -342,7 +342,8 @@ extension Bolus {
                 let authenticated = try await unlockmanager.unlock()
                 if authenticated {
                     apsManager.enactBolus(amount: maxAmount, isSMB: false)
-                    savePumpInsulin(amount: amount)
+//                    savePumpInsulin(amount: amount)
+                    // already saved via pumphistory through apsManager
                 } else {
                     print("authentication failed")
                 }

+ 2 - 5
FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift

@@ -217,9 +217,6 @@ enum DataTable {
 }
 
 protocol DataTableProvider: Provider {
-    func pumpHistory() -> [PumpHistoryEvent]
-    func tempTargets() -> [TempTarget]
-    func carbs() -> [CarbsEntry]
-    func deleteCarbs(_ treatement: DataTable.Treatment)
-    func deleteInsulin(_ treatement: DataTable.Treatment)
+    func deleteCarbs(_ treatment: CarbEntryStored)
+    func deleteInsulin(_ treatment: PumpEventStored)
 }

+ 6 - 25
FreeAPS/Sources/Modules/DataTable/DataTableProvider.swift

@@ -2,42 +2,23 @@ import Foundation
 
 extension DataTable {
     final class Provider: BaseProvider, DataTableProvider {
-        @Injected() var pumpHistoryStorage: PumpHistoryStorage!
-        @Injected() var tempTargetsStorage: TempTargetsStorage!
-        @Injected() var glucoseStorage: GlucoseStorage!
-        @Injected() var carbsStorage: CarbsStorage!
         @Injected() var nightscoutManager: NightscoutManager!
         @Injected() var healthkitManager: HealthKitManager!
 
-        func pumpHistory() -> [PumpHistoryEvent] {
-            pumpHistoryStorage.recent()
-        }
-
         func pumpSettings() -> PumpSettings {
             storage.retrieve(OpenAPS.Settings.settings, as: PumpSettings.self)
                 ?? PumpSettings(from: OpenAPS.defaults(for: OpenAPS.Settings.settings))
                 ?? PumpSettings(insulinActionCurve: 6, maxBolus: 10, maxBasal: 2)
         }
 
-        func tempTargets() -> [TempTarget] {
-            tempTargetsStorage.recent()
-        }
-
-        func carbs() -> [CarbsEntry] {
-            carbsStorage.recent()
-        }
-
-        func fpus() -> [CarbsEntry] {
-            carbsStorage.recent()
-        }
-
-        func deleteCarbs(_ treatement: Treatment) {
-            nightscoutManager.deleteCarbs(treatement, complexMeal: false)
+        func deleteCarbs(_: CarbEntryStored) {
+            // TODO: fix this and refactor nightscoutManager.deleteCarbs()
+//            nightscoutManager.deleteCarbs(treatment, complexMeal: false)
         }
 
-        func deleteInsulin(_ treatement: Treatment) {
-            nightscoutManager.deleteInsulin(at: treatement.date)
-            if let id = treatement.idPumpEvent {
+        func deleteInsulin(_ treatment: PumpEventStored) {
+            nightscoutManager.deleteInsulin(at: treatment.timestamp ?? Date())
+            if let id = treatment.id {
                 healthkitManager.deleteInsulin(syncID: id)
             }
         }

+ 37 - 153
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -24,146 +24,42 @@ extension DataTable {
         @Published var carbEntryDeleted: Bool = false
 
         var units: GlucoseUnits = .mmolL
-        var historyLayout: HistoryLayout = .twoTabs
 
         override func subscribe() {
             units = settingsManager.settings.units
             maxBolus = provider.pumpSettings().maxBolus
-            historyLayout = settingsManager.settings.historyLayout
-            setupTreatments()
-            broadcaster.register(SettingsObserver.self, observer: self)
-            broadcaster.register(PumpHistoryObserver.self, observer: self)
-            broadcaster.register(TempTargetsObserver.self, observer: self)
-            broadcaster.register(CarbsObserver.self, observer: self)
-            broadcaster.register(SuggestionObserver.self, observer: self)
+            broadcaster.register(DeterminationObserver.self, observer: self)
         }
 
-        private func setupTreatments() {
-            DispatchQueue.global().async {
-                let units = self.settingsManager.settings.units
-                let carbs = self.provider.carbs()
-                    .filter { !($0.isFPU ?? false) }
-                    .map {
-                        if let id = $0.id {
-                            return Treatment(
-                                units: units,
-                                type: .carbs,
-                                date: $0.actualDate ?? $0.createdAt,
-                                amount: $0.carbs,
-                                id: id,
-                                fpuID: $0.fpuID,
-                                note: $0.note
-                            )
-                        } else {
-                            return Treatment(
-                                units: units,
-                                type: .carbs,
-                                date: $0.actualDate ?? $0.createdAt,
-                                amount: $0.carbs,
-                                note: $0.note
-                            )
-                        }
-                    }
-
-                let fpus = self.provider.fpus()
-                    .filter { $0.isFPU ?? false }
-                    .map {
-                        Treatment(
-                            units: units,
-                            type: .fpus,
-                            date: $0.actualDate ?? $0.createdAt,
-                            amount: $0.carbs,
-                            id: $0.id,
-                            isFPU: $0.isFPU,
-                            fpuID: $0.fpuID,
-                            note: $0.note
-                        )
-                    }
-
-                let boluses = self.provider.pumpHistory()
-                    .filter { $0.type == .bolus }
-                    .map {
-                        Treatment(
-                            units: units,
-                            type: .bolus,
-                            date: $0.timestamp,
-                            amount: $0.amount,
-                            idPumpEvent: $0.id,
-                            isSMB: $0.isSMB,
-                            isExternal: $0.isExternal
-                        )
-                    }
-
-                let tempBasals = self.provider.pumpHistory()
-                    .filter { $0.type == .tempBasal || $0.type == .tempBasalDuration }
-                    .chunks(ofCount: 2)
-                    .compactMap { chunk -> Treatment? in
-                        let chunk = Array(chunk)
-                        guard chunk.count == 2, chunk[0].type == .tempBasal,
-                              chunk[1].type == .tempBasalDuration else { return nil }
-                        return Treatment(
-                            units: units,
-                            type: .tempBasal,
-                            date: chunk[0].timestamp,
-                            amount: chunk[0].rate ?? 0,
-                            secondAmount: nil,
-                            duration: Decimal(chunk[1].durationMin ?? 0)
-                        )
-                    }
-
-                let tempTargets = self.provider.tempTargets()
-                    .map {
-                        Treatment(
-                            units: units,
-                            type: .tempTarget,
-                            date: $0.createdAt,
-                            amount: $0.targetBottom ?? 0,
-                            secondAmount: $0.targetTop,
-                            duration: $0.duration
-                        )
-                    }
-
-                let suspend = self.provider.pumpHistory()
-                    .filter { $0.type == .pumpSuspend }
-                    .map {
-                        Treatment(units: units, type: .suspend, date: $0.timestamp)
-                    }
-
-                let resume = self.provider.pumpHistory()
-                    .filter { $0.type == .pumpResume }
-                    .map {
-                        Treatment(units: units, type: .resume, date: $0.timestamp)
-                    }
-
-                DispatchQueue.main.async {
-                    if self.historyLayout == .threeTabs {
-                        self.treatments = [boluses, tempBasals, tempTargets, suspend, resume]
-                            .flatMap { $0 }
-                            .sorted { $0.date > $1.date }
-                        self.meals = [carbs, fpus]
-                            .flatMap { $0 }
-                            .sorted { $0.date > $1.date }
-                    } else {
-                        self.treatments = [carbs, fpus, boluses, tempBasals, tempTargets, suspend, resume]
-                            .flatMap { $0 }
-                            .sorted { $0.date > $1.date }
-                    }
+        @MainActor func invokeCarbDeletionTask(_ treatment: CarbEntryStored) {
+            Task {
+                do {
+                    await deleteCarbs(treatment)
+                    carbEntryDeleted = true
+                    waitForSuggestion = true
                 }
             }
         }
 
-        func invokeCarbDeletionTask(_ treatment: Treatment) {
-            carbEntryDeleted = true
-            waitForSuggestion = true
-            deleteCarbs(treatment)
-        }
+        func deleteCarbs(_ carbEntry: CarbEntryStored) async {
+            do {
+                // TODO: when deleting FPU, do an NSDeleteBatchRequest and remove all entries with same FpuID
+                coredataContext.delete(carbEntry)
+                try coredataContext.save()
+                debugPrint(
+                    "Data Table State: \(#function) \(DebuggingIdentifiers.succeeded) deleted carb entry from core data"
+                )
+            } catch {
+                debugPrint(
+                    "Data Table State: \(#function) \(DebuggingIdentifiers.failed) error while deleting carb entry from core data"
+                )
+            }
 
-        func deleteCarbs(_ treatment: Treatment) {
-            provider.deleteCarbs(treatment)
+            provider.deleteCarbs(carbEntry)
             apsManager.determineBasalSync()
         }
 
-        @MainActor func invokeInsulinDeletionTask(_ treatment: Treatment) {
+        @MainActor func invokeInsulinDeletionTask(_ treatment: PumpEventStored) {
             Task {
                 do {
                     await deleteInsulin(treatment)
@@ -173,10 +69,22 @@ extension DataTable {
             }
         }
 
-        func deleteInsulin(_ treatment: Treatment) async {
+        func deleteInsulin(_ treatment: PumpEventStored) async {
             do {
                 let authenticated = try await unlockmanager.unlock()
                 if authenticated {
+                    do {
+                        coredataContext.delete(treatment)
+                        try coredataContext.save()
+                        debugPrint(
+                            "Data Table State: \(#function) \(DebuggingIdentifiers.succeeded) deleted insulin from core data"
+                        )
+                    } catch {
+                        debugPrint(
+                            "Data Table State: \(#function) \(DebuggingIdentifiers.failed) error while deleting insulin from core data"
+                        )
+                    }
+
                     provider.deleteInsulin(treatment)
                     apsManager.determineBasalSync()
                 } else {
@@ -233,32 +141,8 @@ extension DataTable {
     }
 }
 
-extension DataTable.StateModel:
-    SettingsObserver,
-    PumpHistoryObserver,
-    TempTargetsObserver,
-    CarbsObserver
-{
-    func settingsDidChange(_: FreeAPSSettings) {
-        historyLayout = settingsManager.settings.historyLayout
-        setupTreatments()
-    }
-
-    func pumpHistoryDidUpdate(_: [PumpHistoryEvent]) {
-        setupTreatments()
-    }
-
-    func tempTargetsDidUpdate(_: [TempTarget]) {
-        setupTreatments()
-    }
-
-    func carbsDidUpdate(_: [CarbsEntry]) {
-        setupTreatments()
-    }
-}
-
-extension DataTable.StateModel: SuggestionObserver {
-    func suggestionDidUpdate(_: Suggestion) {
+extension DataTable.StateModel: DeterminationObserver {
+    func determinationDidUpdate(_: Determination) {
         DispatchQueue.main.async {
             self.waitForSuggestion = false
         }

+ 102 - 82
FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift

@@ -9,7 +9,8 @@ extension DataTable {
         @State private var isRemoveHistoryItemAlertPresented: Bool = false
         @State private var alertTitle: String = ""
         @State private var alertMessage: String = ""
-        @State private var alertTreatmentToDelete: Treatment?
+        @State private var alertTreatmentToDelete: PumpEventStored?
+        @State private var alertCarbEntryToDelete: CarbEntryStored?
         @State private var alertGlucoseToDelete: Glucose?
 
         @State private var showFutureEntries: Bool = false // default to hide future entries
@@ -21,12 +22,27 @@ extension DataTable {
         @Environment(\.colorScheme) var colorScheme
         @Environment(\.managedObjectContext) var context
 
-        /// fetch ALL glucose values, i.e. manual and non-manual
         @FetchRequest(
-            fetchRequest: GlucoseStored.fetch(NSPredicate.predicateForOneDayAgo, ascending: false, fetchLimit: 288),
+            entity: GlucoseStored.entity(),
+            sortDescriptors: [NSSortDescriptor(keyPath: \GlucoseStored.date, ascending: false)],
+            predicate: NSPredicate.predicateForOneDayAgo,
             animation: .bouncy
         ) var glucoseStored: FetchedResults<GlucoseStored>
 
+        @FetchRequest(
+            entity: PumpEventStored.entity(),
+            sortDescriptors: [NSSortDescriptor(keyPath: \PumpEventStored.timestamp, ascending: false)],
+            predicate: NSPredicate.pumpHistoryLast24h,
+            animation: .bouncy
+        ) var pumpEventStored: FetchedResults<PumpEventStored>
+
+        @FetchRequest(
+            entity: CarbEntryStored.entity(),
+            sortDescriptors: [NSSortDescriptor(keyPath: \CarbEntryStored.date, ascending: false)],
+            predicate: NSPredicate.predicateForOneDayAgo,
+            animation: .bouncy
+        ) var carbEntryStored: FetchedResults<CarbEntryStored>
+
         private var insulinFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
@@ -65,6 +81,13 @@ extension DataTable {
             return formatter
         }
 
+        private var numberFormatter: NumberFormatter {
+            let formatter = NumberFormatter()
+            formatter.numberStyle = .decimal
+            formatter.maximumFractionDigits = 2
+            return formatter
+        }
+
         private var color: LinearGradient {
             colorScheme == .dark ? LinearGradient(
                 gradient: Gradient(colors: [
@@ -87,16 +110,10 @@ extension DataTable {
                 VStack {
                     Picker("Mode", selection: $state.mode) {
                         ForEach(
-                            Mode.allCases.filter({ state.historyLayout == .twoTabs ? $0 != .meals : true }).indexed(),
+                            Mode.allCases.indexed(),
                             id: \.1
                         ) { index, item in
-                            if state.historyLayout == .threeTabs && item == .treatments {
-                                Text("Insulin")
-                                    .tag(index)
-                            } else {
-                                Text(item.name)
-                                    .tag(index)
-                            }
+                            Text(item.name).tag(index)
                         }
                     }
                     .pickerStyle(SegmentedPickerStyle())
@@ -106,7 +123,7 @@ extension DataTable {
                         switch state.mode {
                         case .treatments: treatmentsList
                         case .glucose: glucoseList
-                        case .meals: state.historyLayout == .threeTabs ? AnyView(mealsList) : AnyView(EmptyView())
+                        case .meals: mealsList
                         }
                     }.scrollContentBackground(.hidden)
                         .background(color)
@@ -164,18 +181,12 @@ extension DataTable {
         private var treatmentsList: some View {
             List {
                 HStack {
-                    if state.historyLayout == .twoTabs {
-                        Text("Treatments").foregroundStyle(.secondary)
-                        Spacer()
-                        filterEntriesButton
-                    } else {
-                        Text("Insulin").foregroundStyle(.secondary)
-                        Spacer()
-                        Text("Time").foregroundStyle(.secondary)
-                    }
+                    Text("Insulin").foregroundStyle(.secondary)
+                    Spacer()
+                    Text("Time").foregroundStyle(.secondary)
                 }
-                if !state.treatments.isEmpty {
-                    ForEach(state.treatments.filter({ !showFutureEntries ? $0.date <= Date() : true })) { item in
+                if !pumpEventStored.isEmpty {
+                    ForEach(pumpEventStored.filter({ !showFutureEntries ? $0.timestamp ?? Date() <= Date() : true })) { item in
                         treatmentView(item)
                     }
                 } else {
@@ -193,8 +204,8 @@ extension DataTable {
                     Spacer()
                     filterEntriesButton
                 }
-                if !state.meals.isEmpty {
-                    ForEach(state.meals.filter({ !showFutureEntries ? $0.date <= Date() : true })) { item in
+                if !carbEntryStored.isEmpty {
+                    ForEach(carbEntryStored.filter({ !showFutureEntries ? $0.date ?? Date() <= Date() : true })) { item in
                         mealView(item)
                     }
                 } else {
@@ -321,49 +332,58 @@ extension DataTable {
             }).buttonStyle(.borderless)
         }
 
-        @ViewBuilder private func treatmentView(_ item: Treatment) -> some View {
+        @ViewBuilder private func treatmentView(_ item: PumpEventStored) -> some View {
             HStack {
-                Image(systemName: "circle.fill").foregroundColor(item.color)
-                Text((item.isSMB ?? false) ? "SMB" : item.type.name)
-                Text(item.amountText).foregroundColor(.secondary)
-
-                if let duration = item.durationText {
-                    Text(duration).foregroundColor(.secondary)
+                if let bolus = item.bolus, let amount = bolus.amount {
+                    Image(systemName: "circle.fill").foregroundColor(Color.insulin)
+                    Text(bolus.isSMB ? "SMB" : item.type ?? "Bolus")
+                    Text((insulinFormatter.string(from: amount) ?? "0") + NSLocalizedString(" U", comment: "Insulin unit"))
+                        .foregroundColor(.secondary)
+                    if bolus.isExternal {
+                        Text(NSLocalizedString("External", comment: "External Insulin")).foregroundColor(.secondary)
+                    }
+                } else if let tempBasal = item.tempBasal, let rate = tempBasal.rate {
+                    Image(systemName: "circle.fill").foregroundColor(Color.insulin.opacity(0.4))
+                    Text("Temp Basal")
+                    Text(
+                        (insulinFormatter.string(from: rate) ?? "0") +
+                            NSLocalizedString(" U/hr", comment: "Unit insulin per hour")
+                    )
+                    .foregroundColor(.secondary)
+                    if tempBasal.duration > 0 {
+                        Text("\(tempBasal.duration.string) min").foregroundColor(.secondary)
+                    }
+                } else {
+                    Image(systemName: "circle.fill").foregroundColor(Color.loopGray)
+                    Text(item.type ?? "Pump Event")
                 }
                 Spacer()
-                Text(dateFormatter.string(from: item.date))
-                    .moveDisabled(true)
+                Text(dateFormatter.string(from: item.timestamp ?? Date())).moveDisabled(true)
             }
             .swipeActions {
-                Button(
-                    "Delete",
-                    systemImage: "trash.fill",
-                    role: .none,
-                    action: {
-                        alertTreatmentToDelete = item
-
-                        if item.type == .carbs {
-                            alertTitle = "Delete Carbs?"
-                            alertMessage = dateFormatter.string(from: item.date) + ", " + item.amountText
-                        } else if item.type == .fpus {
-                            alertTitle = "Delete Carb Equivalents?"
-                            alertMessage = "All FPUs of the meal will be deleted."
-                        } else {
-                            // item is insulin treatment; item.type == .bolus
+                if item.bolus != nil {
+                    Button(
+                        "Delete",
+                        systemImage: "trash.fill",
+                        role: .none,
+                        action: {
+                            alertTreatmentToDelete = item
                             alertTitle = "Delete Insulin?"
-                            alertMessage = dateFormatter.string(from: item.date) + ", " + item.amountText
+                            alertMessage = dateFormatter
+                                .string(from: item.timestamp ?? Date()) + ", " +
+                                (insulinFormatter.string(from: item.bolus?.amount ?? 0) ?? "0") +
+                                NSLocalizedString(" U", comment: "Insulin unit")
 
-                            if item.isSMB ?? false {
+                            if let bolus = item.bolus {
                                 // Add text snippet, so that alert message is more descriptive for SMBs
-                                alertMessage += "SMB"
+                                alertMessage += bolus.isSMB ? " SMB" : ""
                             }
-                        }
 
-                        isRemoveHistoryItemAlertPresented = true
-                    }
-                ).tint(.red)
+                            isRemoveHistoryItemAlertPresented = true
+                        }
+                    ).tint(.red)
+                }
             }
-            .disabled(item.type == .tempBasal || item.type == .tempTarget || item.type == .resume || item.type == .suspend)
             .alert(
                 Text(NSLocalizedString(alertTitle, comment: "")),
                 isPresented: $isRemoveHistoryItemAlertPresented
@@ -375,49 +395,49 @@ extension DataTable {
                         return
                     }
 
-                    if state.historyLayout == .twoTabs, treatmentToDelete.type == .carbs || treatmentToDelete.type == .fpus {
-                        state.invokeCarbDeletionTask(treatmentToDelete)
-                    } else {
-                        state.invokeInsulinDeletionTask(treatmentToDelete)
-                    }
+                    state.invokeInsulinDeletionTask(treatmentToDelete)
                 }
             } message: {
                 Text("\n" + NSLocalizedString(alertMessage, comment: ""))
             }
         }
 
-        @ViewBuilder private func mealView(_ meal: Treatment) -> some View {
+        @ViewBuilder private func mealView(_ meal: CarbEntryStored) -> some View {
             HStack {
-                Image(systemName: "circle.fill").foregroundColor(meal.color)
-                Text(meal.type.name)
-                Text(meal.amountText).foregroundColor(.secondary)
-
-                if let duration = meal.durationText {
-                    Text(duration).foregroundColor(.secondary)
+                if meal.isFPU {
+                    Image(systemName: "circle.fill").foregroundColor(Color.orange.opacity(0.5))
+                    Text("Fat / Protein")
+                    Text((numberFormatter.string(for: meal.carbs) ?? "0") + NSLocalizedString(" g", comment: "gram of carbs"))
+                } else {
+                    Image(systemName: "circle.fill").foregroundColor(Color.loopYellow)
+                    Text("Carbs")
+                    Text(
+                        (numberFormatter.string(for: meal.carbs) ?? "0") +
+                            NSLocalizedString(" g", comment: "gram of carb equilvalents")
+                    )
                 }
 
                 Spacer()
 
-                Text(dateFormatter.string(from: meal.date))
+                Text(dateFormatter.string(from: meal.date ?? Date()))
                     .moveDisabled(true)
-            }.swipeActions {
+            }
+            .swipeActions {
                 Button(
                     "Delete",
                     systemImage: "trash.fill",
                     role: .none,
                     action: {
-                        alertTreatmentToDelete = meal
+                        alertCarbEntryToDelete = meal
 
-                        if meal.type == .carbs {
+                        if !meal.isFPU {
                             alertTitle = "Delete Carbs?"
-                            alertMessage = dateFormatter.string(from: meal.date) + ", " + meal.amountText
-                        } else if meal.type == .fpus {
+                            alertMessage = dateFormatter
+                                .string(from: meal.date ?? Date()) + ", " + (numberFormatter.string(for: meal.carbs) ?? "0") +
+                                NSLocalizedString(" g", comment: "gram of carbs")
+                        } else {
                             alertTitle = "Delete Carb Equivalents?"
                             alertMessage = "All FPUs of the meal will be deleted."
-                        } else {
-                            // item is insulin treatment; item.type == .bolus
-                            alertTitle = "Delete Insulin?"
-                            alertMessage = dateFormatter.string(from: meal.date) + ", " + meal.amountText
                         }
 
                         isRemoveHistoryItemAlertPresented = true
@@ -430,11 +450,11 @@ extension DataTable {
             ) {
                 Button("Cancel", role: .cancel) {}
                 Button("Delete", role: .destructive) {
-                    guard let treatmentToDelete = alertTreatmentToDelete else {
-                        debug(.default, "Cannot gracefully unwrap alertTreatmentToDelete!")
+                    guard let carbEntryToDelete = alertCarbEntryToDelete else {
+                        debug(.default, "Cannot gracefully unwrap alertCarbEntryToDelete!")
                         return
                     }
-                    state.invokeCarbDeletionTask(treatmentToDelete)
+                    state.invokeCarbDeletionTask(carbEntryToDelete)
                 }
             } message: {
                 Text("\n" + NSLocalizedString(alertMessage, comment: ""))

+ 3 - 3
FreeAPS/Sources/Services/Network/NightscoutAPI.swift

@@ -141,7 +141,7 @@ extension NightscoutAPI {
             .eraseToAnyPublisher()
     }
 
-    func deleteCarbs(_ treatement: DataTable.Treatment) -> AnyPublisher<Void, Swift.Error> {
+    func deleteCarbs(_ treatment: DataTable.Treatment) -> AnyPublisher<Void, Swift.Error> {
         var components = URLComponents()
         components.scheme = url.scheme
         components.host = url.host
@@ -149,10 +149,10 @@ extension NightscoutAPI {
         components.path = Config.treatmentsPath
 
         var arguments = "find[id][$eq]"
-        if treatement.isFPU ?? false {
+        if treatment.isFPU ?? false {
             arguments = "find[fpuID][$eq]"
         }
-        let value = !(treatement.isFPU ?? false) ? treatement.id : (treatement.fpuID ?? "")
+        let value = !(treatment.isFPU ?? false) ? treatment.id : (treatment.fpuID ?? "")
 
         components.queryItems = [
             // Removed below because it prevented all futire entries to be deleted. Don't know why?

+ 18 - 18
FreeAPS/Sources/Services/Network/NightscoutManager.swift

@@ -10,7 +10,7 @@ protocol NightscoutManager: GlucoseSource {
     func fetchCarbs() -> AnyPublisher<[CarbsEntry], Never>
     func fetchTempTargets() -> AnyPublisher<[TempTarget], Never>
     func fetchAnnouncements() -> AnyPublisher<[Announcement], Never>
-    func deleteCarbs(_ treatement: DataTable.Treatment, complexMeal: Bool)
+    func deleteCarbs(_ treatment: DataTable.Treatment, complexMeal: Bool)
     func deleteInsulin(at date: Date)
     func deleteManualGlucose(at: Date)
     func uploadStatus()
@@ -182,33 +182,33 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
             .eraseToAnyPublisher()
     }
 
-    func deleteCarbs(_ treatement: DataTable.Treatment, complexMeal: Bool) {
+    func deleteCarbs(_ treatment: DataTable.Treatment, complexMeal: Bool) {
         guard let nightscout = nightscoutAPI, isUploadEnabled else {
-            carbsStorage.deleteCarbs(at: treatement.id, fpuID: treatement.fpuID ?? "", complex: complexMeal)
+            carbsStorage.deleteCarbs(at: treatment.id, fpuID: treatment.fpuID ?? "", complex: complexMeal)
             return
         }
 
-        print("meals 3: ID: " + (treatement.id ?? "").description + " FPU ID: " + (treatement.fpuID ?? "").description)
+        print("meals 3: ID: " + (treatment.id ?? "").description + " FPU ID: " + (treatment.fpuID ?? "").description)
 
         var arg1 = ""
         var arg2 = ""
         if complexMeal {
-            arg1 = treatement.id ?? ""
-            arg2 = treatement.fpuID ?? ""
-        } else if treatement.isFPU ?? false {
+            arg1 = treatment.id ?? ""
+            arg2 = treatment.fpuID ?? ""
+        } else if treatment.isFPU ?? false {
             arg1 = ""
-            arg2 = treatement.fpuID ?? ""
+            arg2 = treatment.fpuID ?? ""
         } else {
-            arg1 = treatement.id
+            arg1 = treatment.id
             arg2 = ""
         }
         healthkitManager.deleteCarbs(syncID: arg1, fpuID: arg2)
 
         if complexMeal {
-            nightscout.deleteCarbs(treatement)
+            nightscout.deleteCarbs(treatment)
                 .collect()
                 .sink { completion in
-                    self.carbsStorage.deleteCarbs(at: treatement.id ?? "", fpuID: treatement.fpuID ?? "", complex: true)
+                    self.carbsStorage.deleteCarbs(at: treatment.id ?? "", fpuID: treatment.fpuID ?? "", complex: true)
                     switch completion {
                     case .finished:
                         debug(.nightscout, "Carbs deleted")
@@ -222,8 +222,8 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
                 } receiveValue: { _ in }
                 .store(in: &lifetime)
 
-            if (treatement.fpuID ?? "") != "" {
-                nightscout.deleteCarbs(treatement)
+            if (treatment.fpuID ?? "") != "" {
+                nightscout.deleteCarbs(treatment)
                     .collect()
                     .sink { completion in
                         switch completion {
@@ -239,11 +239,11 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
                     } receiveValue: { _ in }
                     .store(in: &lifetime)
             }
-        } else if treatement.isFPU ?? false {
-            nightscout.deleteCarbs(treatement)
+        } else if treatment.isFPU ?? false {
+            nightscout.deleteCarbs(treatment)
                 .collect()
                 .sink { completion in
-                    self.carbsStorage.deleteCarbs(at: "", fpuID: treatement.fpuID ?? "", complex: false)
+                    self.carbsStorage.deleteCarbs(at: "", fpuID: treatment.fpuID ?? "", complex: false)
                     switch completion {
                     case .finished:
                         debug(.nightscout, "Carb equivalents deleted")
@@ -257,10 +257,10 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
                 } receiveValue: { _ in }
                 .store(in: &lifetime)
         } else {
-            nightscout.deleteCarbs(treatement)
+            nightscout.deleteCarbs(treatment)
                 .collect()
                 .sink { completion in
-                    self.carbsStorage.deleteCarbs(at: treatement.id, fpuID: "", complex: false)
+                    self.carbsStorage.deleteCarbs(at: treatment.id, fpuID: "", complex: false)
                     switch completion {
                     case .finished:
                         debug(.nightscout, "Carbs deleted")