added intent and button

This commit is contained in:
Benjamin Faershtein 2025-02-09 11:29:24 -08:00
parent 41a252649a
commit 2a68a36d84
4 changed files with 125 additions and 0 deletions

View file

@ -0,0 +1,61 @@
//
// NavigateToNodeIntent.swift
// Meshtastic
//
// Created by Benjamin Faershtein on 2/8/25.
//
import Foundation
import AppIntents
import CoreLocation
import CoreData
import UIKit
@available(iOS 16.4, *)
struct NavigateToNodeIntent: ForegroundContinuableIntent {
static var title: LocalizedStringResource = "Navigate to Node Position"
static var openAppWhenRun: Bool = false
@Parameter(title: "Node Number")
var nodeNum: Int
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
if !BLEManager.shared.isConnected {
throw AppIntentErrors.AppIntentError.notConnected
}
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
guard let fetchedNode = try PersistenceController.shared.container.viewContext.fetch(fetchNodeInfoRequest) as? [NodeInfoEntity],
fetchedNode.count == 1 else {
throw $nodeNum.needsValueError("Could not find node")
}
let nodeInfo = fetchedNode[0]
if let latitude = nodeInfo.latestPosition?.coordinate.latitude,
let longitude = nodeInfo.latestPosition?.coordinate.longitude {
let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)")
if let mapURL = url, UIApplication.shared.canOpenURL(mapURL) {
// Request to continue in foreground before opening the app
try await requestToContinueInForeground()
// Open Apple Maps for navigation
UIApplication.shared.open(mapURL, options: [:], completionHandler: nil)
return .result(dialog: "Navigating to node location.")
} else {
throw AppIntentErrors.AppIntentError.message("Unable to open Apple Maps.")
}
} else {
throw AppIntentErrors.AppIntentError.message("Node does not have a recorded position.")
}
} catch {
throw AppIntentErrors.AppIntentError.message("Failed to fetch node data.")
}
}
}

View file

@ -0,0 +1,58 @@
//
// NavigateToButton.swift
// Meshtastic
//
// Created by Benjamin Faershtein on 2/8/25.
//
import SwiftUI
import CoreLocation
import CoreData
import OSLog
struct NavigateToButton: View {
var node: NodeInfoEntity
var body: some View {
Button {
guard let userNum = node.user?.num else {
Logger.services.error("NavigateToAction: Selected node does not exist")
return
}
Logger.services.info("Fetching NodeInfoEntity for userNum: \(userNum)")
let fetchRequest: NSFetchRequest<NodeInfoEntity> = NSFetchRequest(entityName: "NodeInfoEntity")
fetchRequest.predicate = NSPredicate(format: "num == %lld", Int64(userNum))
do {
let fetchedNodes = try PersistenceController.shared.container.viewContext.fetch(fetchRequest)
guard let nodeInfo = fetchedNodes.first else {
Logger.services.error("NavigateToAction: Node with userNum \(userNum) not found in Core Data")
return
}
if let latitude = nodeInfo.latestPosition?.latitude,
let longitude = nodeInfo.latestPosition?.longitude {
if let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
Logger.services.error("Failed to create URL for navigation")
}
} else {
Logger.services.warning("NavigateToAction: Node \(userNum) has invalid or missing coordinates")
}
} catch {
Logger.services.error("NavigateToAction: Failed to fetch node with userNum \(userNum): \(error.localizedDescription)")
}
} label: {
Label {
Text("Navigate to node")
} icon: {
Image(systemName: "map")
.symbolRenderingMode(.hierarchical)
}
}
}
}

View file

@ -378,6 +378,9 @@ struct NodeDetail: View {
node: node
)
}
if node.hasPositions {
NavigateToButton(node: node)
}
IgnoreNodeButton(
bleManager: bleManager,
context: context,

View file

@ -54,6 +54,7 @@ struct PositionLog: View {
let degrees = Angle.degrees(Double(position.heading))
let heading = Measurement(value: degrees.degrees, unit: UnitAngle.degrees).reciprocal()
Text(heading.formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))
.textSelection(.enabled)
}
TableColumn("SNR") { position in
Text("\(String(format: "%.2f", position.snr)) dB")
@ -63,6 +64,8 @@ struct PositionLog: View {
}
.width(min: 180)
}
.textSelection(.enabled)
} else {
ScrollView {