Quellcode durchsuchen

Meal presets

Revert


Clean


Clean

Concurrency fix

Concurrency fix

Allow 1 fraction digit
Jon B.M vor 3 Jahren
Ursprung
Commit
bfb08b1196

+ 1 - 1
BGaverages+CoreDataProperties.swift

@@ -6,10 +6,10 @@ public extension BGaverages {
         NSFetchRequest<BGaverages>(entityName: "BGaverages")
     }
 
-    @NSManaged var date: Date?
     @NSManaged var average: NSDecimalNumber?
     @NSManaged var average_1: NSDecimalNumber?
     @NSManaged var average_7: NSDecimalNumber?
     @NSManaged var average_30: NSDecimalNumber?
     @NSManaged var average_90: NSDecimalNumber?
+    @NSManaged var date: Date?
 }

+ 1 - 1
BGmedian+CoreDataProperties.swift

@@ -9,7 +9,7 @@ public extension BGmedian {
     @NSManaged var date: Date?
     @NSManaged var median: NSDecimalNumber?
     @NSManaged var median_1: NSDecimalNumber?
+    @NSManaged var median_7: NSDecimalNumber?
     @NSManaged var median_30: NSDecimalNumber?
     @NSManaged var median_90: NSDecimalNumber?
-    @NSManaged var median_7: NSDecimalNumber?
 }

+ 1 - 1
Carbohydrates+CoreDataProperties.swift

@@ -6,7 +6,7 @@ public extension Carbohydrates {
         NSFetchRequest<Carbohydrates>(entityName: "Carbohydrates")
     }
 
-    @NSManaged var date: Date?
     @NSManaged var carbs: NSDecimalNumber?
+    @NSManaged var date: Date?
     @NSManaged var enteredBy: String?
 }

+ 6 - 0
Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents

@@ -46,6 +46,12 @@
         <relationship name="computedInsulinDistribution" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="InsulinDistribution" inverseName="insulin" inverseEntity="InsulinDistribution"/>
         <relationship name="computedTDD" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="TDD" inverseName="computed" inverseEntity="TDD"/>
     </entity>
+    <entity name="Presets" representedClassName="Presets" syncable="YES" codeGenerationType="class">
+        <attribute name="carbs" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
+        <attribute name="dish" optional="YES" attributeType="String"/>
+        <attribute name="fat" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
+        <attribute name="protein" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
+    </entity>
     <entity name="Readings" representedClassName="Readings" syncable="YES" codeGenerationType="class">
         <attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
         <attribute name="glucose" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>

+ 6 - 0
FreeAPS.xcworkspace/contents.xcworkspacedata

@@ -5,6 +5,12 @@
       location = "container:"
       name = "CoreDataClassesAndProperties">
       <FileRef
+         location = "group:Presets+CoreDataClass.swift">
+      </FileRef>
+      <FileRef
+         location = "group:Presets+CoreDataProperties.swift">
+      </FileRef>
+      <FileRef
          location = "group:InsulinDistribution+CoreDataClass.swift">
       </FileRef>
       <FileRef

+ 29 - 33
FreeAPS/Sources/APS/APSManager.swift

@@ -974,7 +974,7 @@ final class BaseAPSManager: APSManager, Injectable {
             minimumLoopTime = 0.0
         }
 
-        var glucose: [Readings] = []
+        var glucose = [Readings]()
 
         var firstElementTime = Date()
         var lastElementTime = Date()
@@ -1163,16 +1163,19 @@ final class BaseAPSManager: APSManager, Injectable {
 
         // MARK: Save to Median to CoreData
 
-        let saveMedianToCoreData = BGmedian(context: coredataContext)
-
-        saveMedianToCoreData.date = Date()
-        saveMedianToCoreData.median = median.total as NSDecimalNumber
-        saveMedianToCoreData.median_1 = median.day as NSDecimalNumber
-        saveMedianToCoreData.median_7 = median.week as NSDecimalNumber
-        saveMedianToCoreData.median_30 = median.month as NSDecimalNumber
-        saveMedianToCoreData.median_90 = roundDecimal(Decimal(medianCalculation(array: bgArray_90_)), 1) as NSDecimalNumber
-
         coredataContext.perform {
+            let saveMedianToCoreData = BGmedian(context: self.coredataContext)
+
+            saveMedianToCoreData.date = Date()
+            saveMedianToCoreData.median = median.total as NSDecimalNumber
+            saveMedianToCoreData.median_1 = median.day as NSDecimalNumber
+            saveMedianToCoreData.median_7 = median.week as NSDecimalNumber
+            saveMedianToCoreData.median_30 = median.month as NSDecimalNumber
+            saveMedianToCoreData.median_90 = self.roundDecimal(
+                Decimal(self.medianCalculation(array: bgArray_90_)),
+                1
+            ) as NSDecimalNumber
+
             try? self.coredataContext.save()
         }
 
@@ -1183,17 +1186,15 @@ final class BaseAPSManager: APSManager, Injectable {
             total: roundDecimal(NGSPa1CStatisticValue_total, 1)
         )
 
-        let saveHbA1c = HbA1c(context: coredataContext)
-        saveHbA1c.date = Date()
-        saveHbA1c.hba1c = NGSPa1CStatisticValue_total as NSDecimalNumber
-        saveHbA1c.hba1c_1 = NGSPa1CStatisticValue as NSDecimalNumber
-        saveHbA1c.hba1c_7 = NGSPa1CStatisticValue_7 as NSDecimalNumber
-        saveHbA1c.hba1c_30 = NGSPa1CStatisticValue_30 as NSDecimalNumber
-        saveHbA1c.hba1c_90 = NGSPa1CStatisticValue_90 as NSDecimalNumber
-
-        // MARK: Save to HbA1c to CoreData
-
         coredataContext.perform {
+            let saveHbA1c = HbA1c(context: self.coredataContext)
+            saveHbA1c.date = Date()
+            saveHbA1c.hba1c = NGSPa1CStatisticValue_total as NSDecimalNumber
+            saveHbA1c.hba1c_1 = NGSPa1CStatisticValue as NSDecimalNumber
+            saveHbA1c.hba1c_7 = NGSPa1CStatisticValue_7 as NSDecimalNumber
+            saveHbA1c.hba1c_30 = NGSPa1CStatisticValue_30 as NSDecimalNumber
+            saveHbA1c.hba1c_90 = NGSPa1CStatisticValue_90 as NSDecimalNumber
+
             try? self.coredataContext.save()
         }
 
@@ -1279,24 +1280,19 @@ final class BaseAPSManager: APSManager, Injectable {
             total: roundDecimal(bg_total, 1)
         )
 
-        let saveAverages = BGaverages(context: coredataContext)
-        saveAverages.date = Date()
-        saveAverages.average = bg_total as NSDecimalNumber
-        saveAverages.average_1 = bg_1 as NSDecimalNumber
-        saveAverages.average_7 = bg_7 as NSDecimalNumber
-        saveAverages.average_30 = bg_30 as NSDecimalNumber
-        saveAverages.average_90 = bg_90 as NSDecimalNumber
-
-        // MARK: Save to HbA1c to CoreData
-
         coredataContext.perform {
+            let saveAverages = BGaverages(context: self.coredataContext)
+            saveAverages.date = Date()
+            saveAverages.average = bg_total as NSDecimalNumber
+            saveAverages.average_1 = bg_1 as NSDecimalNumber
+            saveAverages.average_7 = bg_7 as NSDecimalNumber
+            saveAverages.average_30 = bg_30 as NSDecimalNumber
+            saveAverages.average_90 = bg_90 as NSDecimalNumber
+
             try? self.coredataContext.save()
         }
 
         let avg = Averages(Average: avgs, Median: median)
-
-        // MARK: Fetch InsulinDuration from CoreData
-
         var insulinDistribution = [InsulinDistribution]()
 
         var insulin = Ins(

+ 6 - 0
FreeAPS/Sources/Application/FreeAPSApp.swift

@@ -1,10 +1,14 @@
+import CoreData
 import SwiftUI
 import Swinject
 
 @main struct FreeAPSApp: App {
     @Environment(\.scenePhase) var scenePhase
+
     @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
 
+    @StateObject var dataController = CoreDataStack.shared
+
     // Dependencies Assembler
     // contain all dependencies Assemblies
     // TODO: Remove static key after update "Use Dependencies" logic
@@ -53,6 +57,8 @@ import Swinject
     var body: some Scene {
         WindowGroup {
             Main.RootView(resolver: resolver)
+
+                .environment(\.managedObjectContext, dataController.persistentContainer.viewContext)
         }
         .onChange(of: scenePhase) { newScenePhase in
             debug(.default, "APPLICATION PHASE: \(newScenePhase)")

+ 6 - 2
FreeAPS/Sources/Helpers/CoreDataStack.swift

@@ -1,8 +1,8 @@
 import CoreData
 import Foundation
 
-class CoreDataStack {
-    private init() {}
+class CoreDataStack: ObservableObject {
+    init() {}
 
     static let shared = CoreDataStack()
 
@@ -33,4 +33,8 @@ class CoreDataStack {
             }
         }
     }
+
+    func delete(obj: NSManagedObject) {
+        persistentContainer.viewContext.delete(obj)
+    }
 }

+ 17 - 0
FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift

@@ -1,3 +1,4 @@
+import CoreData
 import SwiftUI
 
 extension AddCarbs {
@@ -11,6 +12,11 @@ extension AddCarbs {
         @Published var fat: Decimal = 0
         @Published var carbsRequired: Decimal?
         @Published var useFPU: Bool = false
+        @Published var dish: String = ""
+        @Published var selection: Presets?
+
+        let coredataContext = CoreDataStack.shared.persistentContainer.viewContext // .newBackgroundContext()
+        @Environment(\.managedObjectContext) var moc
 
         override func subscribe() {
             carbsRequired = provider.suggestion?.carbsReq
@@ -100,5 +106,16 @@ extension AddCarbs {
                 showModal(for: .bolus(waitForSuggestion: true))
             }
         }
+
+        func deletePreset() {
+            if selection != nil {
+                try? coredataContext.delete(selection!)
+                try? coredataContext.save()
+                carbs = 0
+                fat = 0
+                protein = 0
+            }
+            selection = nil
+        }
     }
 }

+ 83 - 6
FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift

@@ -1,3 +1,4 @@
+import CoreData
 import SwiftUI
 import Swinject
 
@@ -5,11 +6,21 @@ extension AddCarbs {
     struct RootView: BaseView {
         let resolver: Resolver
         @StateObject var state = StateModel()
+        @State var dish: String = ""
+        @State var isPromtPresented = false
+        @State var saved = false
+
+        @FetchRequest(
+            entity: Presets.entity(),
+            sortDescriptors: [NSSortDescriptor(key: "dish", ascending: true)]
+        ) var carbPresets: FetchedResults<Presets>
+
+        @Environment(\.managedObjectContext) var moc
 
         private var formatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 0
+            formatter.maximumFractionDigits = 1
             return formatter
         }
 
@@ -33,8 +44,6 @@ extension AddCarbs {
                             Text("grams").foregroundColor(.secondary)
                         }.padding(.vertical)
 
-                        // MARK: Adding Protein and Fat. Test
-
                         if state.useFPU {
                             HStack {
                                 Text("Protein").foregroundColor(.loopRed).fontWeight(.thin)
@@ -46,6 +55,7 @@ extension AddCarbs {
                                     autofocus: false,
                                     cleanInput: true
                                 ).foregroundColor(.loopRed)
+
                                 Text("grams").foregroundColor(.secondary)
                             }
                             HStack {
@@ -60,20 +70,87 @@ extension AddCarbs {
                                 )
                                 Text("grams").foregroundColor(.secondary)
                             }
+
+                            HStack {
+                                Button {
+                                    isPromtPresented = true
+                                }
+                                label: { Text("Save as Preset") }
+                            }
+                            .frame(maxWidth: .infinity, alignment: .trailing)
+                            .disabled(state.carbs <= 0 && state.fat <= 0 && state.protein <= 0)
+                            .popover(isPresented: $isPromtPresented) {
+                                presetPopover
+                            }
                         }
                         DatePicker("Date", selection: $state.date)
                     }
                 }
+
                 Section {
                     Button { state.add() }
-                    label: { Text("Add") }
+                    label: { Text("Save and continue") }
                         .disabled(state.carbs <= 0 && state.fat <= 0 && state.protein <= 0)
                 }
+
+                if state.useFPU {
+                    mealPresets
+                }
             }
             .onAppear(perform: configureView)
-            .navigationTitle("Add Carbs")
-            .navigationBarTitleDisplayMode(.automatic)
             .navigationBarItems(leading: Button("Close", action: state.hideModal))
         }
+
+        var presetPopover: some View {
+            Form {
+                Section(header: Text("Enter Meal Preset Name")) {
+                    TextField("Name Of Dish", text: $dish)
+                    Button {
+                        saved = true
+                        if dish != "", saved {
+                            let preset = Presets(context: moc)
+                            preset.dish = dish
+                            preset.fat = state.fat as NSDecimalNumber
+                            preset.protein = state.protein as NSDecimalNumber
+                            preset.carbs = state.carbs as NSDecimalNumber
+                            try? moc.save()
+                            state.selection = preset
+                            saved = false
+                            isPromtPresented = false
+                        }
+                    }
+                    label: { Text("Save") }
+                    Button {
+                        dish = ""
+                        saved = false
+                        isPromtPresented = false }
+                    label: { Text("Cancel") }
+                }
+            }
+        }
+
+        var mealPresets: some View {
+            Section {
+                VStack {
+                    Picker("Meal Presets", selection: $state.selection) {
+                        Text("Empty").tag(nil as Presets?)
+                        ForEach(carbPresets, id: \.self) { (preset: Presets) in
+                            Text(preset.dish ?? "").tag(preset as Presets?)
+                        }
+                    }
+                    .pickerStyle(.automatic)
+                    ._onBindingChange($state.selection) { _ in
+                        state.carbs = ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
+                        state.fat = ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
+                        state.protein = ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
+                    }
+                }
+                Button {
+                    state.deletePreset()
+                }
+                label: { Text("Delete Selected Preset") }
+                    .disabled(state.selection == nil)
+            }
+        }
     }
 }

+ 2 - 2
InsulinDistribution+CoreDataProperties.swift

@@ -7,8 +7,8 @@ public extension InsulinDistribution {
     }
 
     @NSManaged var bolus: NSDecimalNumber?
-    @NSManaged var tempBasal: NSDecimalNumber?
-    @NSManaged var scheduledBasal: NSDecimalNumber?
     @NSManaged var date: Date?
+    @NSManaged var scheduledBasal: NSDecimalNumber?
+    @NSManaged var tempBasal: NSDecimalNumber?
     @NSManaged var insulin: Oref0Suggestion?
 }

+ 1 - 1
LoopStatRecord+CoreDataProperties.swift

@@ -8,6 +8,6 @@ public extension LoopStatRecord {
 
     @NSManaged var duration: Double
     @NSManaged var end: Date?
-    @NSManaged var start: Date?
     @NSManaged var loopStatus: String?
+    @NSManaged var start: Date?
 }

+ 17 - 17
Oref0Suggestion+CoreDataProperties.swift

@@ -6,24 +6,8 @@ public extension Oref0Suggestion {
         NSFetchRequest<Oref0Suggestion>(entityName: "Oref0Suggestion")
     }
 
-    @NSManaged var computedTDD: NSSet?
     @NSManaged var computedInsulinDistribution: NSSet?
-}
-
-// MARK: Generated accessors for computedTDD
-
-public extension Oref0Suggestion {
-    @objc(addComputedTDDObject:)
-    @NSManaged func addToComputedTDD(_ value: TDD)
-
-    @objc(removeComputedTDDObject:)
-    @NSManaged func removeFromComputedTDD(_ value: TDD)
-
-    @objc(addComputedTDD:)
-    @NSManaged func addToComputedTDD(_ values: NSSet)
-
-    @objc(removeComputedTDD:)
-    @NSManaged func removeFromComputedTDD(_ values: NSSet)
+    @NSManaged var computedTDD: NSSet?
 }
 
 // MARK: Generated accessors for computedInsulinDistribution
@@ -41,3 +25,19 @@ public extension Oref0Suggestion {
     @objc(removeComputedInsulinDistribution:)
     @NSManaged func removeFromComputedInsulinDistribution(_ values: NSSet)
 }
+
+// MARK: Generated accessors for computedTDD
+
+public extension Oref0Suggestion {
+    @objc(addComputedTDDObject:)
+    @NSManaged func addToComputedTDD(_ value: TDD)
+
+    @objc(removeComputedTDDObject:)
+    @NSManaged func removeFromComputedTDD(_ value: TDD)
+
+    @objc(addComputedTDD:)
+    @NSManaged func addToComputedTDD(_ values: NSSet)
+
+    @objc(removeComputedTDD:)
+    @NSManaged func removeFromComputedTDD(_ values: NSSet)
+}

+ 4 - 0
Presets+CoreDataClass.swift

@@ -0,0 +1,4 @@
+import CoreData
+import Foundation
+
+@objc(Presets) public class Presets: NSManagedObject {}

+ 13 - 0
Presets+CoreDataProperties.swift

@@ -0,0 +1,13 @@
+import CoreData
+import Foundation
+
+public extension Presets {
+    @nonobjc class func fetchRequest() -> NSFetchRequest<Presets> {
+        NSFetchRequest<Presets>(entityName: "Presets")
+    }
+
+    @NSManaged var carbs: NSDecimalNumber?
+    @NSManaged var dish: String?
+    @NSManaged var fat: NSDecimalNumber?
+    @NSManaged var protein: NSDecimalNumber?
+}