From a4c1fc4fe6a9afa22ab35994c5a95656e519e0fe Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 14 May 2024 22:39:07 -0700 Subject: [PATCH] Remove up and downlink from QR codes Open node details view from new node notification Fix speed Simple deep linking structure --- Meshtastic.xcodeproj/project.pbxproj | 12 --- Meshtastic/DeepLinks/DeepLinkManager.swift | 100 ------------------ Meshtastic/Helpers/BLEManager.swift | 67 ++++++------ Meshtastic/Helpers/MeshPackets.swift | 7 +- Meshtastic/MeshtasticApp.swift | 22 ++-- Meshtastic/MeshtasticAppDelegate.swift | 7 +- Meshtastic/Persistence/UpdateCoreData.swift | 6 +- Meshtastic/Views/ContentView.swift | 5 +- Meshtastic/Views/Messages/Messages.swift | 6 -- Meshtastic/Views/Nodes/MeshMap.swift | 60 ++++++----- Meshtastic/Views/Nodes/NodeList.swift | 43 ++++++-- Meshtastic/Views/Settings/ShareChannels.swift | 2 - protobufs | 2 +- 13 files changed, 123 insertions(+), 216 deletions(-) delete mode 100644 Meshtastic/DeepLinks/DeepLinkManager.swift diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 3ec5015c..c1a9f681 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -128,7 +128,6 @@ DDA9515A2BC6624100CEA535 /* TelemetryWeather.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA951592BC6624100CEA535 /* TelemetryWeather.swift */; }; DDA9515C2BC6631200CEA535 /* TelemetryEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */; }; DDA9515E2BC6F56F00CEA535 /* IndoorAirQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9515D2BC6F56F00CEA535 /* IndoorAirQuality.swift */; }; - DDAA632E2BE7F84E00CC22D3 /* DeepLinkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAA632D2BE7F84E00CC22D3 /* DeepLinkManager.swift */; }; DDAB580D2B0DAA9E00147258 /* Routes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAB580C2B0DAA9E00147258 /* Routes.swift */; }; DDAB580F2B0DAFBC00147258 /* LocationEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAB580E2B0DAFBC00147258 /* LocationEntityExtension.swift */; }; DDAD49ED2AFB39DC00B4425D /* MeshMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAD49EC2AFB39DC00B4425D /* MeshMap.swift */; }; @@ -387,7 +386,6 @@ DDA951592BC6624100CEA535 /* TelemetryWeather.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelemetryWeather.swift; sourceTree = ""; }; DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryEnums.swift; sourceTree = ""; }; DDA9515D2BC6F56F00CEA535 /* IndoorAirQuality.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndoorAirQuality.swift; sourceTree = ""; }; - DDAA632D2BE7F84E00CC22D3 /* DeepLinkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLinkManager.swift; sourceTree = ""; }; DDAB580B2B0D913500147258 /* MeshtasticDataModelV20.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV20.xcdatamodel; sourceTree = ""; }; DDAB580C2B0DAA9E00147258 /* Routes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Routes.swift; sourceTree = ""; }; DDAB580E2B0DAFBC00147258 /* LocationEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEntityExtension.swift; sourceTree = ""; }; @@ -766,14 +764,6 @@ path = Channels; sourceTree = ""; }; - DDAA632C2BE7F83400CC22D3 /* DeepLinks */ = { - isa = PBXGroup; - children = ( - DDAA632D2BE7F84E00CC22D3 /* DeepLinkManager.swift */, - ); - path = DeepLinks; - sourceTree = ""; - }; DDAD49EB2AFAE82500B4425D /* Map */ = { isa = PBXGroup; children = ( @@ -835,7 +825,6 @@ children = ( DD7709392AA1ABA1007A8BF0 /* Tips */, DD90860A26F645B700DC5189 /* Meshtastic.entitlements */, - DDAA632C2BE7F83400CC22D3 /* DeepLinks */, DD8ED9C6289CE4A100B3B0AB /* Enums */, DD86D40D2881BDB300BAEB7A /* Export */, DDDB443E29F79A9400EE2349 /* Extensions */, @@ -1253,7 +1242,6 @@ DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */, DD15E4F32B8BA56E00654F61 /* PaxCounterConfig.swift in Sources */, DDDB445229F8ACF900EE2349 /* Date.swift in Sources */, - DDAA632E2BE7F84E00CC22D3 /* DeepLinkManager.swift in Sources */, DDC4D568275499A500A4208E /* Persistence.swift in Sources */, DDD6EEAF29BC024700383354 /* Firmware.swift in Sources */, DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */, diff --git a/Meshtastic/DeepLinks/DeepLinkManager.swift b/Meshtastic/DeepLinks/DeepLinkManager.swift deleted file mode 100644 index 037f50a1..00000000 --- a/Meshtastic/DeepLinks/DeepLinkManager.swift +++ /dev/null @@ -1,100 +0,0 @@ -// -// DeepLinkManager.swift -// Meshtastic -// -// Copyright(c) Garth Vander Houwen 5/5/24. -// - -import Foundation - -protocol DeepLinkTabManager { - func handle(deepLink: String, selectedTab: inout Tab) -> Bool -} - -@available(iOS 17.0, *) -@Observable -class DeepLinkManager { - var selectedTab: Tab = .ble - var features: [DeepLinkTabManager] - - init() { - self.features = [ - DeepLinkManagerMessages(), - DeepLinkManagerBluetooth(), - DeepLinkManagerNodes(), - DeepLinkManagerMap(), - DeepLinkManagerSettings() - ] - } - - func handleDeepLink(deepLink: String) { - for handler in features { - if handler.handle(deepLink: deepLink, selectedTab: &selectedTab) { - return - } - } - } -} - -class DeepLinkManagerBluetooth: DeepLinkTabManager { - func handle(deepLink: String, selectedTab: inout Tab) -> Bool { - if deepLink.contains("bluetooth") { - selectedTab = .ble - return true - } - return false - } -} - -class DeepLinkManagerMessages: DeepLinkTabManager { - - var channel: String = "" - var messageId: String = "" - - func handle(deepLink: String, selectedTab: inout Tab) -> Bool { - if deepLink.contains("messages") { - selectedTab = .messages - extractData(from: deepLink) - return true - } - - return false - } - private func extractData(from deepLink: String) { - let temp = deepLink.replacingOccurrences(of: "meshtastic://messages?", with: "") - let params = temp.components(separatedBy: "&") - guard params.count == 2 else { return } - channel = params[0].replacingOccurrences(of: "channel=", with: "") - messageId = params[1].replacingOccurrences(of: "messageId=", with: "") - } -} - -class DeepLinkManagerMap: DeepLinkTabManager { - func handle(deepLink: String, selectedTab: inout Tab) -> Bool { - if deepLink.contains("map") { - selectedTab = .map - return true - } - return false - } -} - -class DeepLinkManagerNodes: DeepLinkTabManager { - func handle(deepLink: String, selectedTab: inout Tab) -> Bool { - if deepLink.contains("nodes") { - selectedTab = .nodes - return true - } - return false - } -} - -class DeepLinkManagerSettings: DeepLinkTabManager { - func handle(deepLink: String, selectedTab: inout Tab) -> Bool { - if deepLink.contains("settings") { - selectedTab = .settings - return true - } - return false - } -} diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 3c5b4d51..cc5d7c7f 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1008,52 +1008,45 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate public func getPositionFromPhoneGPS(destNum: Int64) -> Position? { var positionPacket = Position() - do { - if #available(iOS 17.0, macOS 14.0, *) { + if #available(iOS 17.0, macOS 14.0, *) { - if let lastLocation = LocationsHandler.shared.locationsArray.last { - - positionPacket.latitudeI = Int32(lastLocation.coordinate.latitude * 1e7) - positionPacket.longitudeI = Int32(lastLocation.coordinate.longitude * 1e7) - let timestamp = lastLocation.timestamp - positionPacket.time = UInt32(timestamp.timeIntervalSince1970) - positionPacket.timestamp = UInt32(timestamp.timeIntervalSince1970) - positionPacket.altitude = Int32(lastLocation.altitude) - positionPacket.satsInView = UInt32(LocationsHandler.satsInView) - - let currentSpeed = lastLocation.speed - if currentSpeed > 0 && (!currentSpeed.isNaN || !currentSpeed.isInfinite) { - positionPacket.groundSpeed = UInt32(currentSpeed * 3.6) - } - let currentHeading = lastLocation.course - if currentHeading > 0 && (!currentHeading.isNaN || !currentHeading.isInfinite) { - positionPacket.groundTrack = UInt32(currentHeading) - } - } + if let lastLocation = LocationsHandler.shared.locationsArray.last { - } else { - if destNum <= 0 || LocationHelper.currentLocation.distance(from: LocationHelper.DefaultLocation) == 0.0 { - return nil - } - - positionPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7) - positionPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7) - let timestamp = LocationHelper.shared.locationManager.location?.timestamp ?? Date() + positionPacket.latitudeI = Int32(lastLocation.coordinate.latitude * 1e7) + positionPacket.longitudeI = Int32(lastLocation.coordinate.longitude * 1e7) + let timestamp = lastLocation.timestamp positionPacket.time = UInt32(timestamp.timeIntervalSince1970) positionPacket.timestamp = UInt32(timestamp.timeIntervalSince1970) - positionPacket.altitude = Int32(LocationHelper.shared.locationManager.location?.altitude ?? 0) - positionPacket.satsInView = UInt32(LocationHelper.satsInView) - let currentSpeed = LocationHelper.shared.locationManager.location?.speed ?? 0 + positionPacket.altitude = Int32(lastLocation.altitude) + positionPacket.satsInView = UInt32(LocationsHandler.satsInView) + + let currentSpeed = lastLocation.speed if currentSpeed > 0 && (!currentSpeed.isNaN || !currentSpeed.isInfinite) { - positionPacket.groundSpeed = UInt32(currentSpeed * 3.6) + positionPacket.groundSpeed = UInt32(currentSpeed) } - let currentHeading = LocationHelper.shared.locationManager.location?.course ?? 0 - if currentHeading > 0 && (!currentHeading.isNaN || !currentHeading.isInfinite) { + let currentHeading = lastLocation.course + if (currentHeading > 0 && currentHeading <= 360) && (!currentHeading.isNaN || !currentHeading.isInfinite) { positionPacket.groundTrack = UInt32(currentHeading) } } - } catch { - return nil + + } else { + + positionPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7) + positionPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7) + let timestamp = LocationHelper.shared.locationManager.location?.timestamp ?? Date() + positionPacket.time = UInt32(timestamp.timeIntervalSince1970) + positionPacket.timestamp = UInt32(timestamp.timeIntervalSince1970) + positionPacket.altitude = Int32(LocationHelper.shared.locationManager.location?.altitude ?? 0) + positionPacket.satsInView = UInt32(LocationHelper.satsInView) + let currentSpeed = LocationHelper.shared.locationManager.location?.speed ?? 0 + if currentSpeed > 0 && (!currentSpeed.isNaN || !currentSpeed.isInfinite) { + positionPacket.groundSpeed = UInt32(currentSpeed) + } + let currentHeading = LocationHelper.shared.locationManager.location?.course ?? 0 + if (currentHeading > 0 && currentHeading <= 360) && (!currentHeading.isNaN || !currentHeading.isInfinite) { + positionPacket.groundTrack = UInt32(currentHeading) + } } return positionPacket } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index cad532fa..d436aef7 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -315,7 +315,7 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje position.longitudeI = nodeInfo.position.longitudeI position.altitude = nodeInfo.position.altitude position.satsInView = Int32(nodeInfo.position.satsInView) - position.speed = Int32(nodeInfo.position.groundSpeed * UInt32(3.6)) + position.speed = Int32(nodeInfo.position.groundSpeed) position.heading = Int32(nodeInfo.position.groundTrack) position.time = Date(timeIntervalSince1970: TimeInterval(Int64(nodeInfo.position.time))) var newPostions = [PositionEntity]() @@ -738,7 +738,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage 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" + path: "meshtastic://nodes?nodenum=\(telemetry.nodeTelemetry?.num ?? 0)" ) ] manager.schedule() @@ -972,9 +972,10 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) { subtitle: "\(icon) \(waypoint.name ?? "Dropped Pin")", content: "\(waypoint.longDescription ?? "\(latitude), \(longitude)")", target: "map", - path: "meshtastic://open-waypoint?id=\(waypoint.id)" + path: "meshtastic://map?waypontid=\(waypoint.id)" ) ] + print("meshtastic://map?waypontid=\(waypoint.id)") manager.schedule() } catch { context.rollback() diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index cd21ec67..2a8e37d1 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -9,9 +9,7 @@ import TipKit @available(iOS 17.0, *) @main struct MeshtasticAppleApp: App { - - let deepLinkManager = DeepLinkManager() - + @UIApplicationDelegateAdaptor(MeshtasticAppDelegate.self) var appDelegate let persistenceController = PersistenceController.shared @ObservedObject private var bleManager: BLEManager = BLEManager.shared @@ -26,7 +24,7 @@ struct MeshtasticAppleApp: App { var body: some Scene { WindowGroup { - ContentView(deepLinkManager: deepLinkManager) + ContentView() .environment(\.managedObjectContext, persistenceController.container.viewContext) .environmentObject(bleManager) .sheet(isPresented: $saveChannels) { @@ -56,10 +54,6 @@ struct MeshtasticAppleApp: App { } } .onOpenURL(perform: { (url) in - - if url.absoluteString.lowercased().contains("meshtastic://") { - deepLinkManager.handleDeepLink(deepLink: url.absoluteString.lowercased()) - } print("Some sort of URL was received \(url)") self.incomingUrl = url @@ -70,7 +64,15 @@ struct MeshtasticAppleApp: App { self.saveChannels = true print("User wants to open a Channel Settings URL: \(self.incomingUrl?.absoluteString ?? "No QR Code Link")") } else if url.absoluteString.lowercased().contains("meshtastic://") { - deepLinkManager.handleDeepLink(deepLink: url.absoluteString.lowercased()) + appState.navigationPath = url.absoluteString + let path = appState.navigationPath ?? "" + if path.starts(with: "meshtastic://map") { + AppState.shared.tabSelection = Tab.map + } else if path.starts(with: "meshtastic://nodes") { + AppState.shared.tabSelection = Tab.nodes + } + + } else { saveChannels = false print("User wants to import a MBTILES offline map file: \(self.incomingUrl?.absoluteString ?? "No Tiles link")") @@ -166,6 +168,6 @@ class AppState: ObservableObject { @Published var unreadDirectMessages: Int = 0 @Published var unreadChannelMessages: Int = 0 @Published var firmwareVersion: String = "0.0.0" - @Published var connectedNode: NodeInfoEntity? + //@Published var connectedNode: NodeInfoEntity? @Published var navigationPath: String? } diff --git a/Meshtastic/MeshtasticAppDelegate.swift b/Meshtastic/MeshtasticAppDelegate.swift index 94a6df6c..ee4177cf 100644 --- a/Meshtastic/MeshtasticAppDelegate.swift +++ b/Meshtastic/MeshtasticAppDelegate.swift @@ -33,13 +33,14 @@ 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")") + let deepLink = userInfo["path"] as? String + AppState.shared.navigationPath = deepLink if targetValue == "map" { AppState.shared.tabSelection = Tab.map + } else if targetValue == "message" { AppState.shared.tabSelection = Tab.messages - } else if targetValue == "node" { + } else if targetValue == "nodes" { AppState.shared.tabSelection = Tab.nodes } completionHandler() diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 69893911..093e8872 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -196,8 +196,8 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) title: "New Node", subtitle: "\(newUser.longName ?? "unknown".localized)", content: "New Node has been discovered", - target: "nodeInfo", - path: "meshtastic://nodes?num=\(newUser.num)" + target: "nodes", + path: "meshtastic://nodes?nodenum=\(newUser.num)" ) ] manager.schedule() @@ -345,7 +345,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext) position.longitudeI = positionMessage.longitudeI position.altitude = positionMessage.altitude position.satsInView = Int32(positionMessage.satsInView) - position.speed = Int32(positionMessage.groundSpeed * UInt32(3.6)) + position.speed = Int32(positionMessage.groundSpeed) position.heading = Int32(positionMessage.groundTrack) position.precisionBits = Int32(positionMessage.precisionBits) if positionMessage.timestamp != 0 { diff --git a/Meshtastic/Views/ContentView.swift b/Meshtastic/Views/ContentView.swift index ffd8feee..da24c465 100644 --- a/Meshtastic/Views/ContentView.swift +++ b/Meshtastic/Views/ContentView.swift @@ -6,12 +6,11 @@ import SwiftUI @available(iOS 17.0, *) struct ContentView: View { - @State var deepLinkManager: DeepLinkManager @StateObject var appState = AppState.shared var body: some View { TabView(selection: $appState.tabSelection) { - Messages(deepLinkManager: deepLinkManager.features[0] as? DeepLinkManagerMessages) + Messages() .tabItem { Label("messages", systemImage: "message") } @@ -22,7 +21,7 @@ struct ContentView: View { Label("bluetooth", systemImage: "antenna.radiowaves.left.and.right") } .tag(Tab.ble) - NodeList(deepLinkManager: deepLinkManager.features[2] as? DeepLinkManagerNodes) + NodeList() .tabItem { Label("nodes", systemImage: "flipphone") } diff --git a/Meshtastic/Views/Messages/Messages.swift b/Meshtastic/Views/Messages/Messages.swift index 871923ac..056e1630 100644 --- a/Meshtastic/Views/Messages/Messages.swift +++ b/Meshtastic/Views/Messages/Messages.swift @@ -13,8 +13,6 @@ import TipKit struct Messages: View { - @State var deepLinkManager: DeepLinkManagerMessages - @StateObject var appState = AppState.shared @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager @@ -29,10 +27,6 @@ struct Messages: View { case groupMessages case directMessages } - - init (deepLinkManager: DeepLinkManagerMessages? = nil) { - self.deepLinkManager = deepLinkManager ?? .init() - } var body: some View { diff --git a/Meshtastic/Views/Nodes/MeshMap.swift b/Meshtastic/Views/Nodes/MeshMap.swift index 5a848908..9eb3e718 100644 --- a/Meshtastic/Views/Nodes/MeshMap.swift +++ b/Meshtastic/Views/Nodes/MeshMap.swift @@ -35,9 +35,11 @@ struct MeshMap: View { @State var selectedPosition: PositionEntity? @State var editingWaypoint: WaypointEntity? @State var selectedWaypoint: WaypointEntity? + @State var selectedWaypointId: String? @State var newWaypointCoord: CLLocationCoordinate2D? @State var isMeshMap = true + var body: some View { NavigationStack { @@ -106,33 +108,33 @@ struct MeshMap: View { .sheet(isPresented: $isEditingSettings) { MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap) } - .onChange(of: (appState.navigationPath)) { newPath in - - if ((newPath?.hasPrefix("meshtastic://open-waypoint")) != nil) { - guard let url = URL(string: appState.navigationPath ?? "NONE") else { - print("Invalid URL") - return - } - guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { - print("Invalid URL Components") - return - } - guard let action = components.host, action == "open-waypoint" else { - print("Unknown waypoint URL action") - return - } - guard let waypointId = components.queryItems?.first(where: { $0.name == "id" })?.value else { - print("Waypoint id not found") - return - } -// guard let waypoint = waypoints.first(where: { $0.id == Int64(waypointId) }) else { -// print("Waypoint not found") +// .onChange(of: (appState.navigationPath)) { newPath in +// +// if ((newPath?.hasPrefix("meshtastic://open-waypoint")) != nil) { +// guard let url = URL(string: appState.navigationPath ?? "NONE") else { +// print("Invalid URL") +// return +// } +// guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { +// print("Invalid URL Components") // return // } - //showWaypoints = true - //position = .camera(MapCamera(centerCoordinate: waypoint.coordinate, distance: 1000, heading: 0, pitch: 60)) - } - } +// guard let action = components.host, action == "open-waypoint" else { +// print("Unknown waypoint URL action") +// return +// } +// guard let waypointId = components.queryItems?.first(where: { $0.name == "id" })?.value else { +// print("Waypoint id not found") +// return +// } +//// guard let waypoint = waypoints.first(where: { $0.id == Int64(waypointId) }) else { +//// print("Waypoint not found") +//// return +//// } +// //showWaypoints = true +// //position = .camera(MapCamera(centerCoordinate: waypoint.coordinate, distance: 1000, heading: 0, pitch: 60)) +// } +// } .onChange(of: (selectedMapLayer)) { newMapLayer in switch selectedMapLayer { case .standard: @@ -174,6 +176,14 @@ struct MeshMap: View { if self.bleManager.context == nil { self.bleManager.context = context } + + + // if deepLinkManager.waypointId.length > 0 { + // let wayPointEntity = getWaypoint(id: Int64(deepLinkManager.waypointId) ?? -1, context: context) + //if wayPointEntity.id > 0 { + // position = .camera(MapCamera(centerCoordinate: wayPointEntity.coordinate, distance: 1000, heading: 0, pitch: 60)) + //} + switch selectedMapLayer { case .standard: mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) diff --git a/Meshtastic/Views/Nodes/NodeList.swift b/Meshtastic/Views/Nodes/NodeList.swift index 1f11b567..90c3d37b 100644 --- a/Meshtastic/Views/Nodes/NodeList.swift +++ b/Meshtastic/Views/Nodes/NodeList.swift @@ -9,7 +9,7 @@ import CoreLocation struct NodeList: View { - @State var deepLinkManager: DeepLinkManagerNodes + @StateObject var appState = AppState.shared @State private var columnVisibility = NavigationSplitViewVisibility.all @State private var selectedNode: NodeInfoEntity? @State private var isPresentingTraceRouteSentAlert = false @@ -42,13 +42,17 @@ struct NodeList: View { var nodes: FetchedResults - init (deepLinkManager: DeepLinkManagerNodes? = nil) { - self.deepLinkManager = deepLinkManager ?? .init() - } - var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { +// HStack { +// Button("Open Node") { +// UIApplication +// .shared +// .open(URL(string: "meshtastic://nodes?nodeNum=530606484")!) +// } +// } + let connectedNodeNum = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0) let connectedNode = nodes.first(where: { $0.num == connectedNodeNum }) List(nodes, id: \.self, selection: $selectedNode) { node in @@ -208,6 +212,7 @@ struct NodeList: View { .disableAutocorrection(true) .scrollDismissesKeyboard(.immediately) .navigationTitle(String.localizedStringWithFormat("nodes %@".localized, String(nodes.count))) + .listStyle(.plain) .confirmationDialog( @@ -218,12 +223,11 @@ struct NodeList: View { Button("Delete Node") { let deleteNode = getNodeInfo(id: deleteNodeId, context: context) if connectedNode != nil { - - } - if deleteNode != nil { - let success = bleManager.removeNode(node: deleteNode!, connectedNodeNum: Int64(connectedNodeNum)) - if !success { - print("Failed to delete node \(deleteNode?.user?.longName ?? "unknown".localized)") + if deleteNode != nil { + let success = bleManager.removeNode(node: deleteNode!, connectedNodeNum: Int64(connectedNodeNum)) + if !success { + print("Failed to delete node \(deleteNode?.user?.longName ?? "unknown".localized)") + } } } } @@ -310,6 +314,23 @@ struct NodeList: View { .onChange(of: distanceFilter) { _ in searchNodeList() } + .onChange(of: (appState.navigationPath)) { newPath in + + if ((newPath?.hasPrefix("meshtastic://nodes")) != nil) { + + if let urlComponent = URLComponents(string: newPath ?? "") { + let queryItems = urlComponent.queryItems + let nodeNum = queryItems?.first(where: { $0.name == "nodenum" })?.value + if nodeNum == nil { + print("nodeNum not found") + } + else { + selectedNode = nodes.first(where: { $0.num == Int64(nodeNum ?? "-1") }) + AppState.shared.navigationPath = nil + } + } + } + } .onAppear { if self.bleManager.context == nil { self.bleManager.context = context diff --git a/Meshtastic/Views/Settings/ShareChannels.swift b/Meshtastic/Views/Settings/ShareChannels.swift index 686af46f..b2e2f1c3 100644 --- a/Meshtastic/Views/Settings/ShareChannels.swift +++ b/Meshtastic/Views/Settings/ShareChannels.swift @@ -278,8 +278,6 @@ struct ShareChannels: View { channelSettings.name = ch.name! channelSettings.psk = ch.psk! channelSettings.id = UInt32(ch.id) - channelSettings.uplinkEnabled = ch.uplinkEnabled - channelSettings.downlinkEnabled = ch.downlinkEnabled channelSet.settings.append(channelSettings) } } diff --git a/protobufs b/protobufs index f92900c5..dd7d64cc 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit f92900c5f884b04388fb7abf61d4df66783015e4 +Subproject commit dd7d64cc038a6365c119ec7508762cc45f405948