mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Remove up and downlink from QR codes
Open node details view from new node notification Fix speed Simple deep linking structure
This commit is contained in:
parent
8e07453afd
commit
a4c1fc4fe6
13 changed files with 123 additions and 216 deletions
|
|
@ -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 = "<group>"; };
|
||||
DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryEnums.swift; sourceTree = "<group>"; };
|
||||
DDA9515D2BC6F56F00CEA535 /* IndoorAirQuality.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndoorAirQuality.swift; sourceTree = "<group>"; };
|
||||
DDAA632D2BE7F84E00CC22D3 /* DeepLinkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLinkManager.swift; sourceTree = "<group>"; };
|
||||
DDAB580B2B0D913500147258 /* MeshtasticDataModelV20.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV20.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDAB580C2B0DAA9E00147258 /* Routes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Routes.swift; sourceTree = "<group>"; };
|
||||
DDAB580E2B0DAFBC00147258 /* LocationEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEntityExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -766,14 +764,6 @@
|
|||
path = Channels;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDAA632C2BE7F83400CC22D3 /* DeepLinks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDAA632D2BE7F84E00CC22D3 /* DeepLinkManager.swift */,
|
||||
);
|
||||
path = DeepLinks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 */,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<NodeInfoEntity>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit f92900c5f884b04388fb7abf61d4df66783015e4
|
||||
Subproject commit dd7d64cc038a6365c119ec7508762cc45f405948
|
||||
Loading…
Add table
Add a link
Reference in a new issue