ソースを参照

Open Snooze view on glucose alert

Ivan Valkou 4 年 前
コミット
17a4a922a3

+ 1 - 0
Dependencies/LibreTransmitter/Sources/LibreTransmitter/Common/NotificationHelper.swift

@@ -217,6 +217,7 @@ public enum NotificationHelper {
                 titles.append(NSLocalizedString("(Snoozed)", comment: "(Snoozed)"))
             } else if alarm.isAlarming() {
                 content.sound = .default
+                content.userInfo = ["action": "snooze"]
                 playSoundIfNeeded()
             }
             titles.append(glucoseDesc)

+ 4 - 1
Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreTransmitterUI/LibreTransmitterManager+UI.swift

@@ -62,12 +62,14 @@ public struct LibreTransmitterSettingsView: UIViewControllerRepresentable {
     private let glucoseUnit: HKUnit
     private let delete: (() -> Void)?
     private let completion: (() -> Void)?
+    private let openSnooze: Bool
 
-    public init(manager: LibreTransmitterManager, glucoseUnit: HKUnit, delete: (() -> Void)? = nil , completion: (() -> Void)? = nil) {
+    public init(manager: LibreTransmitterManager, openSnooze: Bool = false, glucoseUnit: HKUnit, delete: (() -> Void)? = nil , completion: (() -> Void)? = nil) {
         self.manager = manager
         self.glucoseUnit = glucoseUnit
         self.delete = delete
         self.completion = completion
+        self.openSnooze = openSnooze
     }
 
     public func makeUIViewController(context: Context) -> UIViewController {
@@ -76,6 +78,7 @@ public struct LibreTransmitterSettingsView: UIViewControllerRepresentable {
 
         let settings = SettingsView.asHostedViewController(
             glucoseUnit: glucoseUnit,
+            openSnooze: openSnooze,
             //displayGlucoseUnitObservable: displayGlucoseUnitObservable,
             notifyComplete: doneNotifier,
             notifyDelete: wantToTerminateNotifier,

+ 4 - 1
Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreTransmitterUI/Views/Settings/SettingsView.swift

@@ -94,6 +94,7 @@ class SettingsModel : ObservableObject {
 }
 
 struct SettingsView: View {
+    @State var openSnooze = false
 
     //@ObservedObject private var displayGlucoseUnitObservable: DisplayGlucoseUnitObservable
     @ObservedObject private var transmitterInfo: LibreTransmitter.TransmitterInfo
@@ -117,6 +118,7 @@ struct SettingsView: View {
 
     static func asHostedViewController(
         glucoseUnit: HKUnit,
+        openSnooze: Bool,
         //displayGlucoseUnitObservable: DisplayGlucoseUnitObservable,
         notifyComplete: GenericObservableObject,
         notifyDelete: GenericObservableObject,
@@ -126,6 +128,7 @@ struct SettingsView: View {
         alarmStatus: LibreTransmitter.AlarmStatus) -> UIHostingController<SettingsView> {
         UIHostingController(rootView: self.init(
             //displayGlucoseUnitObservable: displayGlucoseUnitObservable,
+            openSnooze: openSnooze,
             transmitterInfo: transmitterInfoObservable, sensorInfo: sensorInfoObervable, glucoseMeasurement: glucoseInfoObservable, notifyComplete: notifyComplete, notifyDelete: notifyDelete, alarmStatus: alarmStatus, glucoseUnit: glucoseUnit
 
         ))
@@ -186,7 +189,7 @@ struct SettingsView: View {
 
     var snoozeSection: some View {
         Section {
-            NavigationLink(destination: SnoozeView(isAlarming: $alarmStatus.isAlarming, activeAlarms: $alarmStatus.glucoseScheduleAlarmResult)) {
+            NavigationLink(destination: SnoozeView(isAlarming: $alarmStatus.isAlarming, activeAlarms: $alarmStatus.glucoseScheduleAlarmResult), isActive: $openSnooze) {
                 if alarmStatus.isAlarming {
                     Text("Snooze Alerts").frame(alignment: .center)
                         .padding(.top, 30)

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -163,6 +163,7 @@
 		38D0B3D925EC07C400CB6E88 /* CarbsEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38D0B3D825EC07C400CB6E88 /* CarbsEntry.swift */; };
 		38DAB280260CBB7F00F74C1A /* PumpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DAB27F260CBB7F00F74C1A /* PumpView.swift */; };
 		38DAB28A260D349500F74C1A /* FetchGlucoseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DAB289260D349500F74C1A /* FetchGlucoseManager.swift */; };
+		38E4451E274DB04600EC9A94 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E4451D274DB04600EC9A94 /* AppDelegate.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 */; };
@@ -467,6 +468,7 @@
 		38D0B3D825EC07C400CB6E88 /* CarbsEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbsEntry.swift; sourceTree = "<group>"; };
 		38DAB27F260CBB7F00F74C1A /* PumpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpView.swift; sourceTree = "<group>"; };
 		38DAB289260D349500F74C1A /* FetchGlucoseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchGlucoseManager.swift; sourceTree = "<group>"; };
+		38E4451D274DB04600EC9A94 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.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>"; };
@@ -874,6 +876,7 @@
 		3811DEDE25C9E2DD00A708ED /* Application */ = {
 			isa = PBXGroup;
 			children = (
+				38E4451D274DB04600EC9A94 /* AppDelegate.swift */,
 				388E595B25AD948C0019842D /* FreeAPSApp.swift */,
 			);
 			path = Application;
@@ -1822,6 +1825,7 @@
 				33E198D3039045D98C3DC5D4 /* AddCarbsStateModel.swift in Sources */,
 				28089E07169488CF6DCC2A31 /* AddCarbsRootView.swift in Sources */,
 				D2165E9D78EFF692C1DED1C6 /* AddTempTargetDataFlow.swift in Sources */,
+				38E4451E274DB04600EC9A94 /* AppDelegate.swift in Sources */,
 				5BFA1C2208114643B77F8CEB /* AddTempTargetProvider.swift in Sources */,
 				919DBD08F13BAFB180DF6F47 /* AddTempTargetStateModel.swift in Sources */,
 				8BC2F5A29AD1ED08AC0EE013 /* AddTempTargetRootView.swift in Sources */,

+ 29 - 0
FreeAPS/Sources/Application/AppDelegate.swift

@@ -0,0 +1,29 @@
+import SwiftUI
+import UIKit
+import UserNotifications
+
+class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
+    @Published var notificationAction: NotificationAction? = nil
+
+    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
+        UNUserNotificationCenter.current().delegate = self
+        return true
+    }
+}
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+    func userNotificationCenter(
+        _: UNUserNotificationCenter,
+        didReceive response: UNNotificationResponse,
+        withCompletionHandler completionHandler: @escaping () -> Void
+    ) {
+        if let action = response.notification.request.content.userInfo["action"] as? String {
+            notificationAction = NotificationAction(rawValue: action)
+        }
+        completionHandler()
+    }
+}
+
+enum NotificationAction: String {
+    case snoozeAlert = "snooze"
+}

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

@@ -3,6 +3,7 @@ import Swinject
 
 @main struct FreeAPSApp: App {
     @Environment(\.scenePhase) var scenePhase
+    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
 
     // Dependencies Assembler
     // contain all dependencies Assemblies
@@ -43,6 +44,7 @@ import Swinject
     var body: some Scene {
         WindowGroup {
             Main.RootView(resolver: resolver)
+                .environmentObject(appDelegate)
         }
         .onChange(of: scenePhase) { newScenePhase in
             debug(.default, "APPLICATION PHASE: \(newScenePhase)")

+ 5 - 0
FreeAPS/Sources/Modules/LibreConfig/View/LibreConfigRootView.swift

@@ -6,12 +6,14 @@ extension LibreConfig {
     struct RootView: BaseView {
         let resolver: Resolver
         @StateObject var state = StateModel()
+        @EnvironmentObject var appDelegate: AppDelegate
 
         var body: some View {
             Group {
                 if state.configured, let manager = state.source.manager {
                     LibreTransmitterSettingsView(
                         manager: manager,
+                        openSnooze: appDelegate.notificationAction == .snoozeAlert,
                         glucoseUnit: state.unit
                     ) {
                         self.state.source.manager = nil
@@ -19,6 +21,9 @@ extension LibreConfig {
                     } completion: {
                         state.hideModal()
                     }
+                    .onAppear {
+                        appDelegate.notificationAction = nil
+                    }
                 } else {
                     LibreTransmitterSetupView { manager in
                         self.state.source.manager = manager

+ 8 - 0
FreeAPS/Sources/Modules/Main/View/MainRootView.swift

@@ -5,6 +5,7 @@ extension Main {
     struct RootView: BaseView {
         let resolver: Resolver
         @StateObject var state = StateModel()
+        @EnvironmentObject var appDelegate: AppDelegate
 
         var body: some View {
             router.view(for: .home)
@@ -23,6 +24,13 @@ extension Main {
                     )
                 }
                 .onAppear(perform: configureView)
+                .onReceive(appDelegate.$notificationAction) { action in
+                    switch action {
+                    case .snoozeAlert:
+                        state.showModal(for: .libreConfig)
+                    default: break
+                    }
+                }
         }
     }
 }