mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #1209 from RCGV1/FixWaypointState
Fixed waypoint updating logic and waypoint notification
This commit is contained in:
commit
25060fd07c
2 changed files with 90 additions and 32 deletions
|
|
@ -8,6 +8,7 @@
|
|||
import SwiftUI
|
||||
import CoreLocation
|
||||
import OSLog
|
||||
import CoreData
|
||||
|
||||
// Shared state that manages the `CLLocationManager` and `CLBackgroundActivitySession`.
|
||||
@MainActor class LocationsHandler: ObservableObject {
|
||||
|
|
@ -109,15 +110,43 @@ import OSLog
|
|||
} else {
|
||||
locationsArray = [location]
|
||||
}
|
||||
UserDefaults.standard.set(location.coordinate.latitude, forKey: "lastKnownLatitude")
|
||||
UserDefaults.standard.set(location.coordinate.longitude, forKey: "lastKnownLongitude")
|
||||
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastKnownLocationTimestamp")
|
||||
return true
|
||||
}
|
||||
|
||||
static let DefaultLocation = CLLocationCoordinate2D(latitude: 37.3346, longitude: -122.0090)
|
||||
static var currentLocation: CLLocationCoordinate2D {
|
||||
guard let location = shared.manager.location else {
|
||||
if let location = shared.manager.location {
|
||||
return location.coordinate
|
||||
} else {
|
||||
// Check authorization status
|
||||
let status = shared.manager.authorizationStatus
|
||||
switch status {
|
||||
case .notDetermined:
|
||||
Logger.services.info("📍 [App] Location permission not determined, requesting authorization")
|
||||
shared.manager.requestWhenInUseAuthorization()
|
||||
case .denied, .restricted:
|
||||
Logger.services.warning("📍 [App] Location access denied or restricted. Please enable location services in Settings to get accurate positioning!")
|
||||
shared.manager.requestWhenInUseAuthorization()
|
||||
default:
|
||||
break
|
||||
}
|
||||
// Fallback 1: Last known location from UserDefaults (if within 4 hours)
|
||||
if let lat = UserDefaults.standard.object(forKey: "lastKnownLatitude") as? Double,
|
||||
let lon = UserDefaults.standard.object(forKey: "lastKnownLongitude") as? Double,
|
||||
let timestamp = UserDefaults.standard.object(forKey: "lastKnownLocationTimestamp") as? Double,
|
||||
lat >= -90 && lat <= 90,
|
||||
lon >= -180 && lon <= 180,
|
||||
Date().timeIntervalSince1970 - timestamp <= 14_400 { // 4 hours in seconds
|
||||
Logger.services.info("📍 [App] Falling back to last known location (age: \(Int(Date().timeIntervalSince1970 - timestamp)) seconds)")
|
||||
return CLLocationCoordinate2D(latitude: lat, longitude: lon)
|
||||
}
|
||||
|
||||
// Fallback 2: Default location
|
||||
Logger.services.warning("📍 [App] No Location and no last known location, something is really wrong. Teleporting user to Apple Park")
|
||||
return DefaultLocation
|
||||
}
|
||||
return location.coordinate
|
||||
}
|
||||
|
||||
static var satsInView: Int {
|
||||
|
|
|
|||
|
|
@ -1035,22 +1035,35 @@ func textMessageAppPacket(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
|
||||
|
||||
let logString = String.localizedStringWithFormat("Waypoint Packet received from node: %@".localized, String(packet.from))
|
||||
Logger.mesh.info("📍 \(logString, privacy: .public)")
|
||||
|
||||
let fetchWaypointRequest = WaypointEntity.fetchRequest()
|
||||
fetchWaypointRequest.predicate = NSPredicate(format: "id == %lld", Int64(packet.id))
|
||||
|
||||
do {
|
||||
|
||||
if let waypointMessage = try? Waypoint(serializedBytes: packet.decoded.payload) {
|
||||
let fetchedWaypoint = try context.fetch(fetchWaypointRequest)
|
||||
if fetchedWaypoint.isEmpty {
|
||||
let waypoint = WaypointEntity(context: context)
|
||||
// Fetch waypoint by waypointMessage.id, not packet.id
|
||||
let fetchWaypointRequest = WaypointEntity.fetchRequest()
|
||||
fetchWaypointRequest.predicate = NSPredicate(format: "id == %lld", Int64(waypointMessage.id))
|
||||
|
||||
waypoint.id = Int64(packet.id)
|
||||
let fetchedWaypoint = try context.fetch(fetchWaypointRequest)
|
||||
// Fetch the node info to get the short name
|
||||
var nodeShortName: String = "?"
|
||||
let fetchNodeRequest = NodeInfoEntity.fetchRequest()
|
||||
fetchNodeRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
|
||||
do {
|
||||
let fetchedNode = try context.fetch(fetchNodeRequest)
|
||||
if let node = fetchedNode.first, let user = node.user {
|
||||
nodeShortName = user.shortName ?? node.user?.userId ?? String(packet.from.toHex())
|
||||
}
|
||||
} catch {
|
||||
Logger.data.error("Failed to fetch NodeInfoEntity for node \(packet.from.toHex(), privacy: .public): \(error)")
|
||||
}
|
||||
if fetchedWaypoint.isEmpty {
|
||||
// Create a new waypoint
|
||||
let waypoint = WaypointEntity(context: context)
|
||||
waypoint.id = Int64(waypointMessage.id) // Use waypointMessage.id
|
||||
waypoint.name = waypointMessage.name
|
||||
waypoint.longDescription = waypointMessage.description_p
|
||||
waypoint.latitudeI = waypointMessage.latitudeI
|
||||
|
|
@ -1073,7 +1086,7 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
|
|||
manager.notifications = [
|
||||
Notification(
|
||||
id: ("notification.id.\(waypoint.id)"),
|
||||
title: "New Waypoint Received",
|
||||
title: "New Waypoint From \(nodeShortName)",
|
||||
subtitle: "\(icon) \(waypoint.name ?? "Dropped Pin")",
|
||||
content: "\(waypoint.longDescription ?? "\(latitude), \(longitude)")",
|
||||
target: "map",
|
||||
|
|
@ -1088,26 +1101,42 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
|
|||
Logger.data.error("Error Saving WaypointEntity from WAYPOINT_APP \(nsError, privacy: .public)")
|
||||
}
|
||||
} else {
|
||||
fetchedWaypoint[0].id = Int64(packet.id)
|
||||
fetchedWaypoint[0].name = waypointMessage.name
|
||||
fetchedWaypoint[0].longDescription = waypointMessage.description_p
|
||||
fetchedWaypoint[0].latitudeI = waypointMessage.latitudeI
|
||||
fetchedWaypoint[0].longitudeI = waypointMessage.longitudeI
|
||||
fetchedWaypoint[0].icon = Int64(waypointMessage.icon)
|
||||
fetchedWaypoint[0].locked = Int64(waypointMessage.lockedTo)
|
||||
if waypointMessage.expire >= 1 {
|
||||
fetchedWaypoint[0].expire = Date(timeIntervalSince1970: TimeInterval(Int64(waypointMessage.expire)))
|
||||
} else {
|
||||
fetchedWaypoint[0].expire = nil
|
||||
}
|
||||
fetchedWaypoint[0].lastUpdated = Date()
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Updated Node Waypoint App Packet For: \(fetchedWaypoint[0].id, privacy: .public)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
Logger.data.error("Error Saving WaypointEntity from WAYPOINT_APP \(nsError, privacy: .public)")
|
||||
// Update existing waypoint
|
||||
let existingWaypoint = fetchedWaypoint[0]
|
||||
if existingWaypoint.locked == 0 || existingWaypoint.locked == packet.from {
|
||||
let currentTime = Int64(Date().timeIntervalSince1970)
|
||||
if waypointMessage.expire > 0 && waypointMessage.expire <= currentTime {
|
||||
context.delete(existingWaypoint)
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Deleted a waypoint")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
Logger.data.error("Error Saving WaypointEntity from WAYPOINT_APP \(nsError, privacy: .public)")
|
||||
}
|
||||
} else {
|
||||
existingWaypoint.name = waypointMessage.name
|
||||
existingWaypoint.longDescription = waypointMessage.description_p
|
||||
existingWaypoint.latitudeI = waypointMessage.latitudeI
|
||||
existingWaypoint.longitudeI = waypointMessage.longitudeI
|
||||
existingWaypoint.icon = Int64(waypointMessage.icon)
|
||||
existingWaypoint.locked = Int64(waypointMessage.lockedTo)
|
||||
if waypointMessage.expire >= 1 {
|
||||
existingWaypoint.expire = Date(timeIntervalSince1970: TimeInterval(Int64(waypointMessage.expire)))
|
||||
} else {
|
||||
existingWaypoint.expire = nil
|
||||
}
|
||||
existingWaypoint.lastUpdated = Date()
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Updated Node Waypoint App Packet For: \(existingWaypoint.id, privacy: .public)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
Logger.data.error("Error Saving WaypointEntity from WAYPOINT_APP \(nsError, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue