Ivan Valkou 4 роки тому
батько
коміт
ab6922ec4e

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

@@ -345,6 +345,7 @@ extension Home.StateModel:
         allowManualTemp = !settings.closedLoop
         closedLoop = settingsManager.settings.closedLoop
         units = settingsManager.settings.units
+        setupGlucose()
     }
 
     func pumpHistoryDidUpdate(_: [PumpHistoryEvent]) {

+ 2 - 0
FreeAPS/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift

@@ -4,6 +4,7 @@ struct CurrentGlucoseView: View {
     @Binding var recentGlucose: BloodGlucose?
     @Binding var delta: Int?
     @Binding var units: GlucoseUnits
+    @Binding var alarm: GlucoseAlarm?
 
     private var glucoseFormatter: NumberFormatter {
         let formatter = NumberFormatter()
@@ -43,6 +44,7 @@ struct CurrentGlucoseView: View {
                 )
                 .font(.system(size: 24, weight: .bold))
                 .fixedSize()
+                .foregroundColor(alarm == nil ? .primary : .loopRed)
                 image.padding(.bottom, 2)
 
             }.padding(.leading, 4)

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

@@ -55,7 +55,8 @@ extension Home {
                 CurrentGlucoseView(
                     recentGlucose: $state.recentGlucose,
                     delta: $state.glucoseDelta,
-                    units: $state.units
+                    units: $state.units,
+                    alarm: $state.alarm
                 )
                 .onTapGesture {
                     if state.alarm == nil {
@@ -67,7 +68,11 @@ extension Home {
                 .onLongPressGesture {
                     let impactHeavy = UIImpactFeedbackGenerator(style: .heavy)
                     impactHeavy.impactOccurred()
-                    state.showModal(for: .snooze)
+                    if state.alarm == nil {
+                        state.showModal(for: .snooze)
+                    } else {
+                        state.openCGM()
+                    }
                 }
 
                 Spacer()

+ 4 - 2
FreeAPS/Sources/Modules/NotificationsConfig/NotificationsConfigStateModel.swift

@@ -21,14 +21,16 @@ extension NotificationsConfig {
                 addSourceInfoToGlucoseNotifications = $0 }
 
             subscribeSetting(\.lowGlucose, on: $lowGlucose, initial: {
-                lowGlucose = units == .mmolL ? $0.asMmolL : $0
+                let value = max(min($0, 400), 40)
+                lowGlucose = units == .mmolL ? value.asMmolL : value
             }, map: {
                 guard units == .mmolL else { return $0 }
                 return $0.asMgdL
             })
 
             subscribeSetting(\.highGlucose, on: $highGlucose, initial: {
-                highGlucose = units == .mmolL ? $0.asMmolL : $0
+                let value = max(min($0, 400), 40)
+                highGlucose = units == .mmolL ? value.asMmolL : value
             }, map: {
                 guard units == .mmolL else { return $0 }
                 return $0.asMgdL

+ 8 - 1
FreeAPS/Sources/Modules/Snooze/SnoozeStateModel.swift

@@ -2,6 +2,13 @@ import SwiftUI
 
 extension Snooze {
     final class StateModel: BaseStateModel<Provider> {
-        override func subscribe() {}
+        @Persisted(key: "UserNotificationsManager.snoozeUntilDate") var snoozeUntilDate: Date = .distantPast
+        @Injected() var glucoseStogare: GlucoseStorage!
+
+        @Published var alarm: GlucoseAlarm?
+
+        override func subscribe() {
+            alarm = glucoseStogare.alarm
+        }
     }
 }

+ 150 - 4
FreeAPS/Sources/Modules/Snooze/View/SnoozeRootView.swift

@@ -1,3 +1,4 @@
+import AudioToolbox
 import SwiftUI
 import Swinject
 
@@ -6,11 +7,156 @@ extension Snooze {
         let resolver: Resolver
         @StateObject var state = StateModel()
 
+        @State private var selectedInterval = 0
+        @State private var snoozeDescription = "nothing to see here"
+
+        private var pickerTimes: [TimeInterval] {
+            var arr: [TimeInterval] = []
+
+            let mins10 = 0.166_67
+            let mins20 = mins10 * 2
+            let mins30 = mins10 * 3
+            // let mins40 = mins10 * 4
+
+            for hr in 0 ..< 2 {
+                for min in [0.0, mins20, mins20 * 2] {
+                    arr.append(TimeInterval(hours: Double(hr) + min))
+                }
+            }
+            for hr in 2 ..< 4 {
+                for min in [0.0, mins30] {
+                    arr.append(TimeInterval(hours: Double(hr) + min))
+                }
+            }
+
+            for hr in 4 ... 8 {
+                arr.append(TimeInterval(hours: Double(hr)))
+            }
+
+            return arr
+        }
+
+        private var formatter: DateComponentsFormatter {
+            let formatter = DateComponentsFormatter()
+            formatter.allowsFractionalUnits = false
+            formatter.unitsStyle = .full
+            return formatter
+        }
+
+        private var dateFormatter: DateFormatter {
+            let formatter = DateFormatter()
+            formatter.timeStyle = .short
+            return formatter
+        }
+
+        private func formatInterval(_ interval: TimeInterval) -> String {
+            formatter.string(from: interval)!
+        }
+
+        func getSnoozeDescription() -> String {
+            var snoozeDescription = ""
+            var celltext = ""
+
+            switch state.alarm {
+            case .high:
+                celltext = NSLocalizedString("High Glucose Alarm active", comment: "High Glucose Alarm active")
+            case .low:
+                celltext = NSLocalizedString("Low Glucose Alarm active", comment: "Low Glucose Alarm active")
+            case .none:
+                celltext = NSLocalizedString("No Glucose Alarm active", comment: "No Glucose Alarm active")
+            }
+
+            if state.snoozeUntilDate > Date() {
+                snoozeDescription = String(
+                    format: NSLocalizedString("snoozing until %@", comment: "snoozing until %@"),
+                    dateFormatter.string(from: state.snoozeUntilDate)
+                )
+            } else {
+                snoozeDescription = NSLocalizedString("not snoozing", comment: "not snoozing")
+            }
+
+            return [celltext, snoozeDescription].joined(separator: ", ")
+        }
+
+        var snoozeButton: some View {
+            VStack(alignment: .leading) {
+                Button {
+                    let interval = pickerTimes[selectedInterval]
+                    let snoozeFor = formatter.string(from: interval)!
+                    let untilDate = Date() + interval
+                    state.snoozeUntilDate = untilDate < Date() ? .distantPast : untilDate
+                    debug(.default, "will snooze for \(snoozeFor) until \(dateFormatter.string(from: untilDate))")
+                    snoozeDescription = getSnoozeDescription()
+                    AudioServicesDisposeSystemSoundID(1336)
+                } label: {
+                    Text("Click to Snooze Alerts")
+                        .padding()
+                }
+            }
+        }
+
+        private var snoozePicker: some View {
+            VStack {
+                Picker(selection: $selectedInterval, label: Text("Strength")) {
+                    ForEach(0 ..< pickerTimes.count) {
+                        Text(formatInterval(self.pickerTimes[$0]))
+                    }
+                }
+                .pickerStyle(.wheel)
+            }
+        }
+
+        var snoozeDesc: some View {
+            VStack(alignment: .leading) {
+                Text(snoozeDescription)
+            }
+        }
+
         var body: some View {
-            Text("Snooze root view")
-                .navigationBarTitle("Snooze Alerts")
-                .navigationBarTitleDisplayMode(.automatic)
-                .onAppear(perform: configureView)
+            Form {
+                snoozeDesc
+                snoozePicker
+                snoozeButton
+            }
+            .navigationBarTitle("Snooze Alerts")
+            .navigationBarTitleDisplayMode(.automatic)
+            .navigationBarItems(leading: Button("Close", action: state.hideModal))
+            .onAppear {
+                configureView()
+                snoozeDescription = getSnoozeDescription()
+            }
         }
     }
 }
+
+extension TimeInterval {
+    static func seconds(_ seconds: Double) -> TimeInterval {
+        seconds
+    }
+
+    static func minutes(_ minutes: Double) -> TimeInterval {
+        TimeInterval(minutes: minutes)
+    }
+
+    static func hours(_ hours: Double) -> TimeInterval {
+        TimeInterval(hours: hours)
+    }
+
+    init(minutes: Double) {
+        // self.init(minutes * 60)
+        let m = minutes * 60
+        self.init(m)
+    }
+
+    init(hours: Double) {
+        self.init(minutes: hours * 60)
+    }
+
+    var minutes: Double {
+        self / 60.0
+    }
+
+    var hours: Double {
+        minutes / 60.0
+    }
+}

+ 1 - 1
FreeAPS/Sources/Services/SettingsManager/SettingsManager.swift

@@ -14,7 +14,7 @@ final class BaseSettingsManager: SettingsManager, Injectable {
     @Injected() var broadcaster: Broadcaster!
     @Injected() var storage: FileStorage!
 
-    var settings: FreeAPSSettings {
+    @SyncAccess var settings: FreeAPSSettings {
         didSet {
             if oldValue != settings {
                 save()

+ 7 - 1
FreeAPS/Sources/Services/UserNotifiactions/UserNotificationsManager.swift

@@ -21,6 +21,8 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
     @Injected() private var glucoseStorage: GlucoseStorage!
     @Injected(as: FetchGlucoseManager.self) private var sourceInfoProvider: SourceInfoProvider!
 
+    @Persisted(key: "UserNotificationsManager.snoozeUntilDate") private var snoozeUntilDate: Date = .distantPast
+
     private let center = UNUserNotificationCenter.current()
 
     init(resolver: Resolver) {
@@ -80,6 +82,10 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
                 self.playSoundIfNeeded()
             }
 
+            if self.snoozeUntilDate > Date() {
+                titles.append(NSLocalizedString("(Snoozed)", comment: "(Snoozed)"))
+            }
+
             let delta = glucose.count >= 2 ? glucoseValue - (glucose[glucose.count - 2].glucose ?? 0) : nil
 
             let body = self.glucoseText(glucoseValue: glucoseValue, delta: delta, direction: lastGlucose.direction) + self
@@ -198,7 +204,7 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
     }
 
     private func playSoundIfNeeded() {
-        guard settingsManager.settings.useAlarmSound else { return }
+        guard settingsManager.settings.useAlarmSound, snoozeUntilDate < Date() else { return }
         playSound()
     }