Merge pull request #1214 from gitbisector/issue#1155nav

Fix TraceRoute notification navigation to correct node (#1115)
This commit is contained in:
Garth Vander Houwen 2025-05-10 12:37:52 -07:00 committed by GitHub
commit da3f79c20d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 3 deletions

View file

@ -940,7 +940,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
subtitle: "TR received back from \(destinationHop.name ?? "unknown")",
content: "Hops from: \(tr.hopsTowards), Hops back: \(tr.hopsBack)\n\(tr.routeText ?? "Unknown".localized)\n\(tr.routeBackText ?? "Unknown".localized)",
target: "nodes",
path: "meshtastic:///nodes?nodenum=\(connectedNode.user?.num ?? 0)"
path: "meshtastic:///nodes?nodenum=\(tr.node?.num ?? 0)"
)
]
manager.schedule()

View file

@ -97,7 +97,22 @@ class MeshtasticAppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificat
if let targetValue = userInfo["target"] as? String,
let deepLink = userInfo["path"] as? String,
let url = URL(string: deepLink) {
Logger.services.info("userNotificationCenter didReceiveResponse \(targetValue, privacy: .public) \(deepLink, privacy: .public)")
Logger.services.info("userNotificationCenter didReceiveResponse handling deeplink: \(targetValue, privacy: .public) \(deepLink, privacy: .public)")
// Handle TraceRoute notifications specially to ensure they navigate correctly
if deepLink.contains("meshtastic:///nodes") && deepLink.contains("nodenum=") {
// First extract the node number from the URL
if let nodeNumString = deepLink.components(separatedBy: "nodenum=").last,
let nodeNum = Int64(nodeNumString) {
Logger.services.info("Navigation to specific node via notification: \(nodeNum, privacy: .public)")
self.router?.navigationState.selectedTab = .nodes
// Post a notification to trigger app-wide refresh
NotificationCenter.default.post(name: NSNotification.Name("ForceNavigationRefresh"),
object: nil,
userInfo: ["nodeNum": nodeNum])
self.router?.navigationState.nodeListSelectedNodeNum = nodeNum
}
}
// Still call the regular router in all cases
router?.route(url: url)
} else {
Logger.services.error("Failed to handle notification response: \(userInfo, privacy: .public)")

View file

@ -28,6 +28,8 @@ struct NodeList: View {
@State private var isFavorite = false
@State private var isIgnored = false
@State private var isEnvironment = false
// Force refresh ID to make SwiftUI rebuild the view hierarchy
@State private var forceRefreshID = UUID()
@State private var distanceFilter = false
@State private var maxDistance: Double = 800000
@State private var hopsAway: Double = -1.0
@ -131,6 +133,7 @@ struct NodeList: View {
}
var body: some View {
// Use forceRefreshID to completely rebuild the view when notifications update the selected node
NavigationSplitView(columnVisibility: $columnVisibility) {
List(nodes, id: \.self, selection: $selectedNode) { node in
NodeListItem(
@ -315,16 +318,41 @@ struct NodeList: View {
}
.onChange(of: router.navigationState) {
if let selected = router.navigationState.nodeListSelectedNodeNum {
self.selectedNode = getNodeInfo(id: selected, context: context)
// Force a complete view rebuild by generating a new UUID
Logger.services.info("Forcing view rebuild with new ID: \(self.forceRefreshID)")
// First clear selection
self.forceRefreshID = UUID()
self.selectedNode = nil
// Then after a short delay, set the new selection. Makes it obvious to use page is refreshing too.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
// Generate another UUID to ensure view gets rebuilt
self.forceRefreshID = UUID()
self.selectedNode = getNodeInfo(id: selected, context: context)
Logger.services.info("Complete view refresh with node: \(selected, privacy: .public)")
}
} else {
self.selectedNode = nil
}
}
.onAppear {
// Set up notification observer for forced refreshes from notifications
NotificationCenter.default.addObserver(forName: NSNotification.Name("ForceNavigationRefresh"), object: nil, queue: .main) { notification in
if let nodeNum = notification.userInfo?["nodeNum"] as? Int64 {
// Force complete refresh of view
self.forceRefreshID = UUID()
self.selectedNode = getNodeInfo(id: nodeNum, context: self.context)
Logger.services.info("NodeList directly updated from notification for node: \(nodeNum, privacy: .public)")
}
}
Task {
await searchNodeList()
}
}
.onDisappear {
// Remove observer when view disappears
NotificationCenter.default.removeObserver(self, name: NSNotification.Name("ForceNavigationRefresh"), object: nil)
}
}
private func searchNodeList() async {