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" {