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

Edit Meal entries from Boluse View (go back and forth).
Not working with the waiter's notepad yet, but can be fixed later, as it's not that important in this reagard.

(cherry picked from commit 3f5c93370ac27c5065bad5e14c64e2f2b5ee0318)

Jon Mårtensson 2 лет назад
Родитель
Сommit
4185165ad6

+ 1 - 1
Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="22G90" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22225" systemVersion="22G120" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
     <entity name="BGaverages" representedClassName="BGaverages" syncable="YES" codeGenerationType="class">
         <attribute name="average" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
         <attribute name="average_1" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>

+ 1 - 1
FreeAPS.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -30,7 +30,7 @@
       },
       {
         "package": "SwiftCharts",
-        "repositoryURL": "https://github.com/ivanschuetz/SwiftCharts",
+        "repositoryURL": "https://github.com/ivanschuetz/SwiftCharts.git",
         "state": {
           "branch": "master",
           "revision": "c354c1945bb35a1f01b665b22474f6db28cba4a2",

+ 17 - 5
FreeAPS/Sources/APS/Storage/CarbsStorage.swift

@@ -12,7 +12,7 @@ protocol CarbsStorage {
     func syncDate() -> Date
     func recent() -> [CarbsEntry]
     func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment]
-    func deleteCarbs(at date: Date)
+    func deleteCarbs(at date: String, complex: Bool?)
 }
 
 final class BaseCarbsStorage: CarbsStorage, Injectable {
@@ -71,7 +71,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
                 // New date for each carb equivalent
                 var useDate = entries.last?.createdAt ?? Date()
                 // Group and Identify all FPUs together
-                let fpuID = UUID().uuidString
+                let fpuID = (entries.last?.id ?? "") + ".fpu"
                 // Create an array of all future carb equivalents.
                 var futureCarbArray = [CarbsEntry]()
                 while carbEquivalents > 0, numberOfEquivalents > 0 {
@@ -81,7 +81,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
                     } else { useDate = useDate.addingTimeInterval(interval.minutes.timeInterval) }
 
                     let eachCarbEntry = CarbsEntry(
-                        id: UUID().uuidString, createdAt: useDate, carbs: equivalent, fat: 0, protein: 0, note: nil,
+                        id: fpuID, createdAt: useDate, carbs: equivalent, fat: 0, protein: 0, note: nil,
                         enteredBy: CarbsEntry.manual, isFPU: true,
                         fpuID: fpuID
                     )
@@ -143,11 +143,12 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self)?.reversed() ?? []
     }
 
-    func deleteCarbs(at date: Date) {
+    func deleteCarbs(at id: String, complex: Bool?) {
         processQueue.sync {
             var allValues = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self) ?? []
 
-            guard let entryIndex = allValues.firstIndex(where: { $0.createdAt == date }) else {
+            guard let entryIndex = allValues.firstIndex(where: { $0.id == id }) else {
+                debug(.default, "Didn't find anything to delete. Date to search for: " + id.description)
                 return
             }
 
@@ -166,6 +167,17 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
                     $0.carbsDidUpdate(allValues)
                 }
             }
+            if let deleteComplexEntriesAlso = complex {
+                guard let fpuIndex = allValues.firstIndex(where: { $0.id == (id + ".fpu") }) else {
+                    debug(
+                        .default,
+                        "Didn't find any complex fat and protein entries to delete. Date to search for: " + id.description
+                    )
+                    return
+                }
+                allValues.removeAll(where: { $0.id == (id + ".fpu") })
+                storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
+            }
         }
     }
 

+ 36 - 11
FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift

@@ -18,6 +18,8 @@ extension AddCarbs {
         @Published var summation: [String] = []
         @Published var maxCarbs: Decimal = 0
         @Published var note: String = ""
+        @Published var id_: String = ""
+        @Published var summary: String = ""
 
         let coredataContext = CoreDataStack.shared.persistentContainer.viewContext
 
@@ -34,24 +36,35 @@ extension AddCarbs {
             }
             carbs = min(carbs, maxCarbs)
 
+            id_ = UUID().uuidString
+
+            let carbsToStore = [CarbsEntry(
+                id: id_,
+                createdAt: date,
+                carbs: carbs,
+                fat: fat,
+                protein: protein,
+                note: note,
+                enteredBy: CarbsEntry.manual,
+                isFPU: false, fpuID: nil
+            )]
+
             carbsStorage.storeCarbs(
-                [CarbsEntry(
-                    id: UUID().uuidString,
-                    createdAt: date,
-                    carbs: carbs,
-                    fat: fat,
-                    protein: protein,
-                    note: note,
-                    enteredBy: CarbsEntry.manual,
-                    isFPU: false, fpuID: nil
-                )]
+                carbsToStore
             )
 
+            /*
+             let entries = Meals(
+                 carbs: carbs, protein: protein, fat: fat, note: note, summary: waitersNotepad(), id: id_, date: date,
+                 enteredBy: CarbsEntry.manual, isFPU: false, fpuID: nil
+             )
+              */
+
             if settingsManager.settings.skipBolusScreenAfterCarbs {
                 apsManager.determineBasalSync()
                 showModal(for: nil)
             } else {
-                showModal(for: .bolus(waitForSuggestion: true))
+                showModal(for: .bolus(waitForSuggestion: true, meal: carbsToStore))
             }
         }
 
@@ -160,5 +173,17 @@ extension AddCarbs {
             }
             return waitersNotepadString
         }
+
+        func loadEntries(_ editMode: Bool, _ meal: [CarbsEntry]?) {
+            if editMode {
+                if let entries = meal {
+                    carbs = entries.first?.carbs ?? 0
+                    fat = entries.first?.fat ?? 0
+                    protein = entries.first?.protein ?? 0
+                    note = entries.first?.note ?? ""
+                    id_ = entries.first?.id ?? ""
+                }
+            }
+        }
     }
 }

+ 7 - 1
FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift

@@ -5,6 +5,8 @@ import Swinject
 extension AddCarbs {
     struct RootView: BaseView {
         let resolver: Resolver
+        let editMode: Bool
+        let meal: [CarbsEntry]?
         @StateObject var state = StateModel()
         @State var dish: String = ""
         @State var isPromptPresented = false
@@ -129,7 +131,11 @@ extension AddCarbs {
                     }
                 }
             }
-            .onAppear(perform: configureView)
+            .onAppear {
+                configureView {
+                    state.loadEntries(editMode, meal)
+                }
+            }
             .navigationTitle("Add Meals")
             .navigationBarTitleDisplayMode(.inline)
             .navigationBarItems(leading: Button("Close", action: state.hideModal))

+ 10 - 0
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -12,6 +12,7 @@ extension Bolus {
         // added for bolus calculator
         @Injected() var glucoseStorage: GlucoseStorage!
         @Injected() var settings: SettingsManager!
+        @Injected() var nsManager: NightscoutManager!
 
         @Published var suggestion: Suggestion?
         @Published var amount: Decimal = 0
@@ -209,6 +210,15 @@ extension Bolus {
                 self.getDeltaBG()
             }
         }
+
+        func backToCarbsView(_ meal: [CarbsEntry], _ complexEntry: Bool) {
+            debug(.apsManager, "Start deleting carbs")
+            nsManager.deleteCarbs(
+                at: meal.first?.id ?? "", isFPU: nil, fpuID: nil, syncID: meal.first?.id ?? "",
+                complex: complexEntry
+            )
+            showModal(for: .addCarbs(editMode: true, meal: meal))
+        }
     }
 }
 

+ 109 - 3
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -6,6 +6,7 @@ extension Bolus {
     struct AlternativeBolusCalcRootView: BaseView {
         let resolver: Resolver
         let waitForSuggestion: Bool
+        let meal: [CarbsEntry]?
         @ObservedObject var state: StateModel
 
         @State private var showInfo = false
@@ -97,15 +98,65 @@ extension Bolus {
                             }
                         }
                     }
+                } header: { Text("Values") }
+
+                if changed {
+                    Section {
+                        VStack {
+                            if let mealEntry = meal {
+                                if (mealEntry.first?.carbs ?? 0) > 0 {
+                                    HStack {
+                                        Text("Carbs")
+                                        Spacer()
+                                        Text((mealEntry.first?.carbs ?? 0).formatted())
+                                        Text("g")
+                                    }.foregroundColor(.secondary)
+                                }
+                                if (mealEntry.first?.fat ?? 0) > 0 {
+                                    HStack {
+                                        Text("Fat")
+                                        Spacer()
+                                        Text((mealEntry.first?.fat ?? 0).formatted())
+                                        Text("g")
+                                    }.foregroundColor(.secondary)
+                                }
+                                if (mealEntry.first?.protein ?? 0) > 0 {
+                                    HStack {
+                                        Text("Protein")
+                                        Spacer()
+                                        Text((mealEntry.first?.protein ?? 0).formatted())
+                                        Text("g")
+                                    }.foregroundColor(.secondary)
+                                }
+                                if (mealEntry.first?.note ?? "") != "" {
+                                    HStack {
+                                        Text("Note")
+                                        Spacer()
+                                        Text(mealEntry.first?.note ?? "")
+                                    }.foregroundColor(.secondary)
+                                }
+                            }
+                        }
+                    } header: { Text("Meal Summary") }
+                }
+
+                if changed {
+                    Section {
+                        Button {
+                            if let exists = meal {
+                                state.backToCarbsView(exists, hasFatOrProtein)
+                            }
+                        }
+                        label: { Text("Edit Meal") }.frame(maxWidth: .infinity, alignment: .center)
+                    }
                 }
-                header: { Text("Values") }
 
                 Section {
                     if state.waitForSuggestion {
                         HStack {
                             Text("Wait please").foregroundColor(.secondary)
                             Spacer()
-                            ActivityIndicator(isAnimating: .constant(true), style: .medium) // fix iOS 15 bug
+                            ActivityIndicator(isAnimating: .constant(true), style: .medium)
                         }
                     } else {
                         HStack {
@@ -172,6 +223,7 @@ extension Bolus {
                     configureView {
                         state.waitForSuggestionInitial = waitForSuggestion
                         state.waitForSuggestion = waitForSuggestion
+                        insulinCalculated = state.calculateInsulin()
                     }
                 }
                 .navigationTitle("Enact Bolus")
@@ -184,6 +236,20 @@ extension Bolus {
             }
         }
 
+        var changed: Bool {
+            if let exists = meal {
+                return ((exists.first?.carbs ?? 0) > 0 || (exists.first?.fat ?? 0) > 0 || (exists.first?.protein ?? 0) > 0)
+            }
+            return false
+        }
+
+        var hasFatOrProtein: Bool {
+            if let exists = meal {
+                return ((exists.first?.fat ?? 0) > 0 || (exists.first?.protein ?? 0) > 0)
+            }
+            return false
+        }
+
         // calculation showed in popup
         var bolusInfoAlternativeCalculator: some View {
             let unit = NSLocalizedString(
@@ -193,7 +259,7 @@ extension Bolus {
 
             return VStack {
                 VStack {
-                    VStack {
+                    VStack(spacing: 5) {
                         HStack {
                             Text("Calculations")
                                 .font(.title3)
@@ -201,6 +267,46 @@ extension Bolus {
                             Spacer()
                         }
                         .padding(.vertical, 10)
+
+                        if changed {
+                            VStack(spacing: 3) {
+                                if let mealEntry = meal {
+                                    if (mealEntry.first?.note ?? "") != "" {
+                                        HStack {
+                                            Text("Note")
+                                                .foregroundColor(.secondary)
+                                            Spacer()
+                                            Text(mealEntry.first?.note ?? "").foregroundColor(.secondary)
+                                        }
+                                    }
+                                    if (mealEntry.first?.carbs ?? 0) > 0 {
+                                        HStack {
+                                            Text("Carbs")
+                                                .foregroundColor(.secondary)
+                                            Spacer()
+                                            Text((mealEntry.first?.carbs ?? 0).formatted())
+                                        }
+                                    }
+                                    if (mealEntry.first?.protein ?? 0) > 0 {
+                                        HStack {
+                                            Text("Protein")
+                                                .foregroundColor(.secondary)
+                                            Spacer()
+                                            Text((mealEntry.first?.protein ?? 0).formatted())
+                                        }
+                                    }
+                                    if (mealEntry.first?.fat ?? 0) > 0 {
+                                        HStack {
+                                            Text("Fat")
+                                                .foregroundColor(.secondary)
+                                            Spacer()
+                                            Text((mealEntry.first?.fat ?? 0).formatted())
+                                        }
+                                    }
+                                }
+                            }.padding(.bottom, 20)
+                        }
+
                         HStack {
                             Text("Carb Ratio")
                                 .foregroundColor(.secondary)

+ 3 - 2
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -5,15 +5,16 @@ extension Bolus {
     struct RootView: BaseView {
         let resolver: Resolver
         let waitForSuggestion: Bool
+        let meal: [CarbsEntry]?
         @StateObject var state = StateModel()
 
         var body: some View {
             if state.useCalc {
                 // show alternative bolus calc based on toggle in bolus calc settings
-                AlternativeBolusCalcRootView(resolver: resolver, waitForSuggestion: waitForSuggestion, state: state)
+                AlternativeBolusCalcRootView(resolver: resolver, waitForSuggestion: waitForSuggestion, meal: meal, state: state)
             } else {
                 // show iAPS standard bolus calc
-                DefaultBolusCalcRootView(resolver: resolver, waitForSuggestion: waitForSuggestion, state: state)
+                DefaultBolusCalcRootView(resolver: resolver, waitForSuggestion: waitForSuggestion, meal: meal, state: state)
             }
         }
     }

+ 1 - 0
FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift

@@ -5,6 +5,7 @@ extension Bolus {
     struct DefaultBolusCalcRootView: BaseView {
         let resolver: Resolver
         let waitForSuggestion: Bool
+        let meal: [CarbsEntry]?
         @StateObject var state = StateModel()
 
         @State private var isAddInsulinAlertPresented = false

+ 2 - 2
FreeAPS/Sources/Modules/DataTable/DataTableProvider.swift

@@ -33,10 +33,10 @@ extension DataTable {
 
         func deleteCarbs(_ treatement: Treatment) {
             nightscoutManager.deleteCarbs(
-                at: treatement.date,
+                at: treatement.id,
                 isFPU: treatement.isFPU,
                 fpuID: treatement.fpuID,
-                syncID: treatement.id
+                syncID: treatement.id, complex: nil
             )
         }
 

+ 1 - 1
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -196,7 +196,7 @@ extension Home {
         }
 
         func addCarbs() {
-            showModal(for: .addCarbs)
+            showModal(for: .addCarbs(editMode: false, meal: nil))
         }
 
         func runLoop() {

+ 5 - 2
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -481,7 +481,7 @@ extension Home {
                 Rectangle().fill(Color.gray.opacity(0.3)).frame(height: 50 + geo.safeAreaInsets.bottom)
 
                 HStack {
-                    Button { state.showModal(for: .addCarbs) }
+                    Button { state.showModal(for: .addCarbs(editMode: false, meal: nil)) }
                     label: {
                         ZStack(alignment: Alignment(horizontal: .trailing, vertical: .bottom)) {
                             Image("carbs")
@@ -512,7 +512,10 @@ extension Home {
                     .buttonStyle(.borderless)
                     Spacer()
                     Button {
-                        state.showModal(for: .bolus(waitForSuggestion: true))
+                        state.showModal(for: .bolus(
+                            waitForSuggestion: true,
+                            meal: nil
+                        ))
                     }
                     label: {
                         Image("bolus")

+ 6 - 6
FreeAPS/Sources/Router/Screen.swift

@@ -14,9 +14,9 @@ enum Screen: Identifiable, Hashable {
     case crEditor
     case targetsEditor
     case preferencesEditor
-    case addCarbs
+    case addCarbs(editMode: Bool, meal: [CarbsEntry]?)
     case addTempTarget
-    case bolus(waitForSuggestion: Bool)
+    case bolus(waitForSuggestion: Bool, meal: [CarbsEntry]?)
     case manualTempBasal
     case autotuneConfig
     case dataTable
@@ -64,12 +64,12 @@ extension Screen {
             TargetsEditor.RootView(resolver: resolver)
         case .preferencesEditor:
             PreferencesEditor.RootView(resolver: resolver)
-        case .addCarbs:
-            AddCarbs.RootView(resolver: resolver)
+        case let .addCarbs(editMode, meal):
+            AddCarbs.RootView(resolver: resolver, editMode: editMode, meal: meal)
         case .addTempTarget:
             AddTempTarget.RootView(resolver: resolver)
-        case let .bolus(waitForSuggestion):
-            Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion)
+        case let .bolus(waitForSuggestion, meal):
+            Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion, meal: meal)
         case .manualTempBasal:
             ManualTempBasal.RootView(resolver: resolver)
         case .autotuneConfig:

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

@@ -141,7 +141,7 @@ extension NightscoutAPI {
             .eraseToAnyPublisher()
     }
 
-    func deleteCarbs(at date: Date) -> AnyPublisher<Void, Swift.Error> {
+    func deleteCarbs(at date: String) -> AnyPublisher<Void, Swift.Error> {
         var components = URLComponents()
         components.scheme = url.scheme
         components.host = url.host
@@ -150,8 +150,8 @@ extension NightscoutAPI {
         components.queryItems = [
             URLQueryItem(name: "find[carbs][$exists]", value: "true"),
             URLQueryItem(
-                name: "find[created_at][$eq]",
-                value: Formatter.iso8601withFractionalSeconds.string(from: date)
+                name: "find[id][$eq]",
+                value: date
             )
         ]
 

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

@@ -9,7 +9,7 @@ protocol NightscoutManager: GlucoseSource {
     func fetchCarbs() -> AnyPublisher<[CarbsEntry], Never>
     func fetchTempTargets() -> AnyPublisher<[TempTarget], Never>
     func fetchAnnouncements() -> AnyPublisher<[Announcement], Never>
-    func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String)
+    func deleteCarbs(at date: String, isFPU: Bool?, fpuID: String?, syncID: String, complex: Bool?)
     func deleteInsulin(at date: Date)
     func deleteManualGlucose(at: Date)
     func uploadStatus()
@@ -177,12 +177,12 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
             .eraseToAnyPublisher()
     }
 
-    func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String) {
+    func deleteCarbs(at date: String, isFPU: Bool?, fpuID: String?, syncID: String, complex: Bool?) {
         // remove in AH
         healthkitManager.deleteCarbs(syncID: syncID, isFPU: isFPU, fpuID: fpuID)
 
         guard let nightscout = nightscoutAPI, isUploadEnabled else {
-            carbsStorage.deleteCarbs(at: date)
+            carbsStorage.deleteCarbs(at: date, complex: complex)
             return
         }
 
@@ -192,16 +192,16 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
             let dates = allValues.filter { $0.fpuID == fpuID }.map(\.createdAt).removeDublicates()
 
             let publishers = dates
-                .map { d -> AnyPublisher<Void, Swift.Error> in
+                .map { _ -> AnyPublisher<Void, Swift.Error> in
                     nightscout.deleteCarbs(
-                        at: d
+                        at: date
                     )
                 }
 
             Publishers.MergeMany(publishers)
                 .collect()
                 .sink { completion in
-                    self.carbsStorage.deleteCarbs(at: date)
+                    self.carbsStorage.deleteCarbs(at: date, complex: complex)
                     switch completion {
                     case .finished:
                         debug(.nightscout, "Carbs deleted")
@@ -219,7 +219,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
         } else {
             nightscout.deleteCarbs(at: date)
                 .sink { completion in
-                    self.carbsStorage.deleteCarbs(at: date)
+                    self.carbsStorage.deleteCarbs(at: date, complex: complex)
                     switch completion {
                     case .finished:
                         debug(.nightscout, "Carbs deleted")