Ivan Valkou 4 éve
szülő
commit
711239836d

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -203,6 +203,7 @@
 		38E8755B27568A6800975559 /* ConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8755A27568A6700975559 /* ConfirmationView.swift */; };
 		38E8757927579D9200975559 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE5525C9D4D500A708ED /* Publisher.swift */; };
 		38E8757B2757B1C300975559 /* TempTargetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8757A2757B1C300975559 /* TempTargetsView.swift */; };
+		38E8757D2757C45D00975559 /* BolusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8757C2757C45D00975559 /* BolusView.swift */; };
 		38E989DD25F5021400C0CED0 /* PumpStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E989DC25F5021400C0CED0 /* PumpStatus.swift */; };
 		38E98A2325F52C9300C0CED0 /* Signpost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A1B25F52C9300C0CED0 /* Signpost.swift */; };
 		38E98A2425F52C9300C0CED0 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A1C25F52C9300C0CED0 /* Logger.swift */; };
@@ -588,6 +589,7 @@
 		38E8755627564B6100975559 /* FreeAPSWatch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FreeAPSWatch.entitlements; sourceTree = "<group>"; };
 		38E8755A27568A6700975559 /* ConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationView.swift; sourceTree = "<group>"; };
 		38E8757A2757B1C300975559 /* TempTargetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetsView.swift; sourceTree = "<group>"; };
+		38E8757C2757C45D00975559 /* BolusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusView.swift; sourceTree = "<group>"; };
 		38E989DC25F5021400C0CED0 /* PumpStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpStatus.swift; sourceTree = "<group>"; };
 		38E98A1B25F52C9300C0CED0 /* Signpost.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Signpost.swift; sourceTree = "<group>"; };
 		38E98A1C25F52C9300C0CED0 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
@@ -1376,6 +1378,7 @@
 				38E87549275550BB00975559 /* CarbsView.swift */,
 				38E8755A27568A6700975559 /* ConfirmationView.swift */,
 				38E8757A2757B1C300975559 /* TempTargetsView.swift */,
+				38E8757C2757C45D00975559 /* BolusView.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -2218,6 +2221,7 @@
 			files = (
 				38E8757927579D9200975559 /* Publisher.swift in Sources */,
 				38E8755B27568A6800975559 /* ConfirmationView.swift in Sources */,
+				38E8757D2757C45D00975559 /* BolusView.swift in Sources */,
 				38E8752E27554D5700975559 /* NotificationController.swift in Sources */,
 				38E8754C2755548F00975559 /* WatchStateModel.swift in Sources */,
 				38E8754A275550BB00975559 /* CarbsView.swift in Sources */,

+ 22 - 2
FreeAPS/Sources/Services/WatchManager/WatchManager.swift

@@ -17,6 +17,8 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
     @Injected() private var carbsStorage: CarbsStorage!
     @Injected() private var tempTargetsStorage: TempTargetsStorage!
 
+    private var lifetime = Lifetime()
+
     init(resolver: Resolver, session: WCSession = .default) {
         self.session = session
         super.init()
@@ -74,6 +76,8 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
                         until: untilDate
                     )
                 }
+            self.state.bolusAfterCarbs = !self.settingsManager.settings.skipBolusScreenAfterCarbs
+
             self.sendState()
         }
     }
@@ -199,8 +203,18 @@ extension BaseWatchManager: WCSessionDelegate {
                 CarbsEntry(createdAt: Date(), carbs: Decimal(carbs), enteredBy: CarbsEntry.manual)
             ])
 
-            replyHandler(["confirmation": true])
-            return
+            if settingsManager.settings.skipBolusScreenAfterCarbs {
+                apsManager.determineBasalSync()
+                replyHandler(["confirmation": true])
+                return
+            } else {
+                apsManager.determineBasal()
+                    .sink { _ in
+                        replyHandler(["confirmation": true])
+                    }
+                    .store(in: &lifetime)
+                return
+            }
         }
 
         if let tempTargetID = message["tempTarget"] as? String {
@@ -225,6 +239,12 @@ extension BaseWatchManager: WCSessionDelegate {
             }
         }
 
+        if let bolus = message["bolus"] as? Double, bolus > 0 {
+            apsManager.enactBolus(amount: bolus, isSMB: false)
+            replyHandler(["confirmation": true])
+            return
+        }
+
         replyHandler(["confirmation": false])
     }
 

+ 1 - 0
FreeAPSWatch WatchKit Extension/DataFlow.swift

@@ -14,6 +14,7 @@ struct WatchState: Codable {
     var iob: Decimal?
     var cob: Decimal?
     var tempTargets: [TempTargetWatchPreset] = []
+    var bolusAfterCarbs: Bool?
 }
 
 struct TempTargetWatchPreset: Codable, Identifiable {

+ 86 - 0
FreeAPSWatch WatchKit Extension/Views/BolusView.swift

@@ -0,0 +1,86 @@
+import SwiftUI
+
+struct BolusView: View {
+    @EnvironmentObject var state: WatchStateModel
+
+    @State var steps = 0.0
+
+    var numberFormatter: NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.minimum = 0
+        formatter.maximum = Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)) as NSNumber
+        formatter.maximumFractionDigits = 2
+        formatter.minimumFractionDigits = 2
+        formatter.allowsFloats = true
+        return formatter
+    }
+
+    var body: some View {
+        VStack(spacing: 16) {
+            HStack {
+                Button {
+                    let newValue = steps - 1
+                    steps = max(newValue, 0)
+                } label: { Image(systemName: "minus") }
+                    .frame(width: 50)
+                Spacer()
+                Text(numberFormatter.string(from: (steps * Double(state.bolusIncrement ?? 0.1)) as NSNumber)! + " U")
+                    .font(.headline)
+                    .focusable(true)
+                    .digitalCrownRotation(
+                        $steps,
+                        from: 0,
+                        through: Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)),
+                        by: 1,
+                        sensitivity: .medium,
+                        isContinuous: false,
+                        isHapticFeedbackEnabled: true
+                    )
+                Spacer()
+                Button {
+                    let newValue = steps + 1
+                    steps = min(newValue, Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)))
+                } label: { Image(systemName: "plus") }
+                    .frame(width: 50)
+            }
+
+            HStack {
+                Button {
+                    state.isBolusViewActive = false
+                }
+                label: {
+                    Image(systemName: "xmark.circle.fill")
+                        .resizable()
+                        .foregroundColor(.loopRed)
+                        .frame(width: 30, height: 30)
+                }
+                Button {
+                    enactBolus()
+                }
+                label: {
+                    Image(systemName: "checkmark.circle.fill")
+                        .resizable()
+                        .foregroundColor(.loopGreen)
+                        .frame(width: 30, height: 30)
+                }
+                .disabled(steps <= 0)
+            }
+        }
+        .navigationTitle("Enact Bolus")
+        .onAppear {
+            steps = Double((state.bolusRecommended ?? 0) / (state.bolusIncrement ?? 0.1))
+        }
+    }
+
+    private func enactBolus() {
+        let amount = steps * Double(state.bolusIncrement ?? 0.1)
+        state.enactBolus(amount: amount)
+    }
+}
+
+struct BolusView_Previews: PreviewProvider {
+    static var previews: some View {
+        BolusView().environmentObject(WatchStateModel())
+    }
+}

+ 1 - 1
FreeAPSWatch WatchKit Extension/Views/CarbsView.swift

@@ -30,7 +30,7 @@ struct CarbsView: View {
                     .digitalCrownRotation(
                         $amount,
                         from: 0,
-                        through: 120,
+                        through: Double(state.maxCOB ?? 120),
                         by: 1,
                         sensitivity: .medium,
                         isContinuous: false,

+ 2 - 1
FreeAPSWatch WatchKit Extension/Views/MainView.swift

@@ -95,7 +95,8 @@ struct MainView: View {
             }
 
             NavigationLink(isActive: $state.isBolusViewActive) {
-                EmptyView()
+                BolusView()
+                    .environmentObject(state)
             } label: {
                 Image("bolus", bundle: nil)
                     .renderingMode(.template)

+ 23 - 1
FreeAPSWatch WatchKit Extension/Views/WatchStateModel.swift

@@ -19,6 +19,7 @@ class WatchStateModel: NSObject, ObservableObject {
     @Published var iob: Decimal?
     @Published var cob: Decimal?
     @Published var tempTargets: [TempTargetWatchPreset] = []
+    @Published var bolusAfterCarbs = true
 
     @Published var isCarbsViewActive = false
     @Published var isTempTargetViewActive = false
@@ -40,7 +41,14 @@ class WatchStateModel: NSObject, ObservableObject {
         confirmationSuccess = nil
         isConfirmationViewActive = true
         isCarbsViewActive = false
-        session.sendMessage(["carbs": carbs], replyHandler: completionHandler) { error in
+        session.sendMessage(["carbs": carbs], replyHandler: { reply in
+            self.completionHandler(reply)
+            if let ok = reply["confirmation"] as? Bool, ok, self.bolusAfterCarbs {
+                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+                    self.isBolusViewActive = true
+                }
+            }
+        }) { error in
             print(error.localizedDescription)
             DispatchQueue.main.async {
                 self.confirmation(false)
@@ -60,6 +68,18 @@ class WatchStateModel: NSObject, ObservableObject {
         }
     }
 
+    func enactBolus(amount: Double) {
+        confirmationSuccess = nil
+        isConfirmationViewActive = true
+        isBolusViewActive = false
+        session.sendMessage(["bolus": amount], replyHandler: completionHandler) { error in
+            print(error.localizedDescription)
+            DispatchQueue.main.async {
+                self.confirmation(false)
+            }
+        }
+    }
+
     func requestState() {
         session.sendMessage(["stateRequest": true], replyHandler: nil) { error in
             print("WatchStateModel error: " + error.localizedDescription)
@@ -99,11 +119,13 @@ class WatchStateModel: NSObject, ObservableObject {
         lastLoopDate = state.lastLoopDate
         bolusIncrement = state.bolusIncrement
         maxCOB = state.maxCOB
+        maxBolus = state.maxBolus
         bolusRecommended = state.bolusRecommended
         carbsRequired = state.carbsRequired
         iob = state.iob
         cob = state.cob
         tempTargets = state.tempTargets
+        bolusAfterCarbs = state.bolusAfterCarbs ?? true
     }
 }