From f2056aa1ac7b33533437fc1449d68986f3256d0f Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 20 Jan 2024 14:05:29 -0800 Subject: [PATCH] Add path to notifications --- Meshtastic/Helpers/BLEManager.swift | 8 ++- .../Helpers/LocalNotificationManager.swift | 17 ++++-- Meshtastic/Helpers/MeshPackets.swift | 57 ++++++++++++------- Meshtastic/Info.plist | 39 ++++++------- Meshtastic/MeshtasticApp.swift | 1 + Meshtastic/MeshtasticAppDelegate.swift | 2 + 6 files changed, 77 insertions(+), 47 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 26014859..2d7bcc77 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -215,7 +215,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate id: (peripheral.identifier.uuidString), title: "Radio Disconnected", subtitle: "\(peripheral.name ?? "unknown".localized)", - content: e.localizedDescription + content: e.localizedDescription, + target: "bluetooth", + path: "meshtastic://bluetooth" ) ] manager.schedule() @@ -233,7 +235,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate id: (peripheral.identifier.uuidString), title: "Radio Disconnected", subtitle: "\(peripheral.name ?? "unknown".localized)", - content: e.localizedDescription + content: e.localizedDescription, + target: "bluetooth", + path: "meshtastic://bluetooth" ) ] manager.schedule() diff --git a/Meshtastic/Helpers/LocalNotificationManager.swift b/Meshtastic/Helpers/LocalNotificationManager.swift index c5efe48e..5ae3df98 100644 --- a/Meshtastic/Helpers/LocalNotificationManager.swift +++ b/Meshtastic/Helpers/LocalNotificationManager.swift @@ -31,15 +31,19 @@ class LocalNotificationManager { // This function iterates over the Notification objects in the notifications array and schedules them for delivery in the future private func scheduleNotifications() { for notification in notifications { - let content = UNMutableNotificationContent() - content.subtitle = notification.subtitle - content.title = notification.title - content.body = notification.content - content.sound = .default - content.interruptionLevel = .timeSensitive + let content = UNMutableNotificationContent() + content.subtitle = notification.subtitle + content.title = notification.title + content.body = notification.content + content.sound = .default + content.interruptionLevel = .timeSensitive + if notification.target != nil { content.userInfo["target"] = notification.target } + if notification.path != nil { + content.userInfo["path"] = notification.path + } let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: trigger) @@ -69,4 +73,5 @@ struct Notification { var subtitle: String var content: String var target: String? + var path: String? } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 3fab145b..a5a9b4f1 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -660,23 +660,37 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage // Connected Device Metrics // ------------------------ // Low Battery notification - if telemetry.batteryLevel > 0 && telemetry.batteryLevel < 5 { - let content = UNMutableNotificationContent() - content.title = "Critically Low Battery!" - content.body = "Time to charge your radio, there is \(telemetry.batteryLevel)% battery remaining." - content.userInfo["target"] = "node" - let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) - let uuidString = UUID().uuidString - let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger) - let notificationCenter = UNUserNotificationCenter.current() - notificationCenter.add(request) { (error) in - if error != nil { - // Handle any errors. - print("Error creating local low battery notification: \(error?.localizedDescription ?? "no description")") - } else { - print("Created local low battery notification.") - } - } + if telemetry.batteryLevel > 0 && telemetry.batteryLevel < 4 { + let manager = LocalNotificationManager() + manager.notifications = [ + Notification( + id: ("notification.id.\(UUID().uuidString)"), + title: "Critically Low Battery!", + subtitle: "AKA \(telemetry.nodeTelemetry?.user?.shortName ?? "UNK")", + content: "Time to charge your radio, there is \(telemetry.batteryLevel)% battery remaining.", + target: "nodes", + path: "meshtastic://nodes/\(telemetry.nodeTelemetry?.num ?? 0)/devicetelemetrylog" + ) + ] + manager.schedule() + +// let content = UNMutableNotificationContent() +// content.title = "Critically Low Battery!" +// content.body = "Time to charge your radio, there is \(telemetry.batteryLevel)% battery remaining." +// content.userInfo["target"] = "node" +// content.userInfo["path"] = "meshtastic://node/\(telemetry.nodeTelemetry?.num ?? 0)" +// let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) +// let uuidString = UUID().uuidString +// let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger) +// let notificationCenter = UNUserNotificationCenter.current() +// notificationCenter.add(request) { (error) in +// if error != nil { +// // Handle any errors. +// print("Error creating local low battery notification: \(error?.localizedDescription ?? "no description")") +// } else { +// print("Created local low battery notification.") +// } +// } } // Update our live activity if there is one running, not available on mac iOS >= 16.2 #if !targetEnvironment(macCatalyst) @@ -781,7 +795,8 @@ func textMessageAppPacket(packet: MeshPacket, blockRangeTest: Bool, connectedNod title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", content: messageText, - target: "message" + target: "message", + path: "meshtastic://messages/dm/user/\(newMessage.fromUser?.num ?? 0)/message/\(newMessage.messageId)" ) ] manager.schedule() @@ -812,7 +827,8 @@ func textMessageAppPacket(packet: MeshPacket, blockRangeTest: Bool, connectedNod title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", content: messageText, - target: "message") + target: "message", + path: "meshtastic://messages/channel/\(newMessage.messageId)") ] manager.schedule() print("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") @@ -878,7 +894,8 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) { title: "New Waypoint Received", subtitle: "\(icon) \(waypoint.name ?? "Dropped Pin")", content: "\(waypoint.longDescription ?? "\(latitude), \(longitude)")", - target: "map" + target: "map", + path: "meshtastic://map/waypoint/\(waypoint.id)" ) ] manager.schedule() diff --git a/Meshtastic/Info.plist b/Meshtastic/Info.plist index ae02c2b4..a2fde04b 100644 --- a/Meshtastic/Info.plist +++ b/Meshtastic/Info.plist @@ -31,6 +31,21 @@ $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString $(MARKETING_VERSION) + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLIconFile + alpha + CFBundleURLName + org.meshtastic + CFBundleURLSchemes + + meshtastic + + + CFBundleVersion $(CURRENT_PROJECT_VERSION) INIntentsSupported @@ -52,17 +67,17 @@ NSBluetoothAlwaysUsageDescription We use bluetooth to connect to nearby Meshtastic Devices NSBluetoothPeripheralUsageDescription - Bluetooth is used to connect an iPhone to a user's meshtastic device to allow text messaging and location data for the mesh network. + Bluetooth is used to connect an iPhone to a user's meshtastic device to allow text messaging and location data for the mesh network. NSCameraUsageDescription We use the camera to share channels using a QR Code + NSLocationAlwaysAndWhenInUseUsageDescription + We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. Route Recording uses location in the background. + NSLocationAlwaysUsageDescription + We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. NSLocationUsageDescription We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. NSLocationWhenInUseUsageDescription We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. - NSLocationAlwaysUsageDescription - We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. - NSLocationAlwaysAndWhenInUseUsageDescription - We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device. Route Recording uses location in the background. NSSupportsLiveActivities Privacy – Bluetooth Always Usage Description @@ -71,20 +86,6 @@ UIApplicationSupportsMultipleScenes - UISceneConfigurations - - CPTemplateApplicationSceneSessionRoleApplication - - - UISceneClassName - CPTemplateApplicationScene - UISceneDelegateClassName - $(SWIFT_MODULE_NAME).CarPlaySceneDelegate - UISceneConfigurationName - CarPlay scene - - - UIApplicationSupportsIndirectInputEvents diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index 48e4c020..e21b96e9 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -153,4 +153,5 @@ class AppState: ObservableObject { @Published var unreadChannelMessages: Int = 0 @Published var firmwareVersion: String = "0.0.0" @Published var connectedNode: NodeInfoEntity? + @Published var navigationPath: String? } diff --git a/Meshtastic/MeshtasticAppDelegate.swift b/Meshtastic/MeshtasticAppDelegate.swift index ab108787..94a6df6c 100644 --- a/Meshtastic/MeshtasticAppDelegate.swift +++ b/Meshtastic/MeshtasticAppDelegate.swift @@ -33,6 +33,8 @@ class MeshtasticAppDelegate: NSObject, UIApplicationDelegate, UNUserNotification func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo let targetValue = userInfo["target"] as? String + AppState.shared.navigationPath = userInfo["path"] as? String + print("\(AppState.shared.navigationPath ?? "EMPTY")") if targetValue == "map" { AppState.shared.tabSelection = Tab.map } else if targetValue == "message" {