mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Add setting for user tracking mode
This commit is contained in:
parent
57268576c4
commit
b214b34d64
8 changed files with 117 additions and 47 deletions
|
|
@ -39,7 +39,7 @@ enum CenteringMode: Int, CaseIterable, Identifiable {
|
|||
|
||||
case allAnnotations = 0
|
||||
case allPositions = 1
|
||||
case clientGps = 2
|
||||
case phoneGps = 2
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
|
|
@ -49,8 +49,8 @@ enum CenteringMode: Int, CaseIterable, Identifiable {
|
|||
return "All Annotations"// NSLocalizedString("default", comment: "Default Keyboard")
|
||||
case .allPositions:
|
||||
return "All Node Postions"// NSLocalizedString("ascii.capable", comment: "ASCII Capable Keyboard")
|
||||
case .clientGps:
|
||||
return "Client GPS"//NSLocalizedString("email.address", comment: "Email Address Keyboard")
|
||||
case .phoneGps:
|
||||
return "Phone GPS"//NSLocalizedString("email.address", comment: "Email Address Keyboard")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +105,39 @@ enum MeshMapType: String, CaseIterable, Identifiable {
|
|||
}
|
||||
}
|
||||
|
||||
enum UserTrackingModes: Int, CaseIterable, Identifiable {
|
||||
|
||||
case none = 0
|
||||
case follow = 1
|
||||
case followWithHeading = 2
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .none:
|
||||
return NSLocalizedString("map.usertrackingmode.none", comment: "None")
|
||||
case .follow:
|
||||
return NSLocalizedString("map.usertrackingmode.follow", comment: "Follow")
|
||||
case .followWithHeading:
|
||||
return NSLocalizedString("map.usertrackingmode.followwithheading", comment: "Follow with Heading")
|
||||
}
|
||||
}
|
||||
}
|
||||
func MKUserTrackingModeValue() -> MKUserTrackingMode {
|
||||
|
||||
switch self {
|
||||
case .none:
|
||||
return MKUserTrackingMode.none
|
||||
case .follow:
|
||||
return MKUserTrackingMode.follow
|
||||
case .followWithHeading:
|
||||
return MKUserTrackingMode.followWithHeading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
|
||||
|
||||
case fiveSeconds = 5
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
case routerClient = 3
|
||||
case repeater = 4
|
||||
case tracker = 5
|
||||
case sensor = 6
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var name: String {
|
||||
|
|
@ -34,6 +35,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return "Repeater"
|
||||
case .tracker:
|
||||
return "Tracker"
|
||||
case .sensor:
|
||||
return "Sensor"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +56,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return NSLocalizedString("device.role.repeater", comment: "Repeater - Mesh packets will prefer to be routed over this node. This role eliminates unnecessary overhead such as NodeInfo, DeviceTelemetry, and any other mesh packet, resulting in the device not appearing as part of the network. Please see Rebroadcast Mode for additional settings specific to this role.")
|
||||
case .tracker:
|
||||
return NSLocalizedString("device.role.tracker", comment: "Tracker - For use with devices intended as a GPS tracker. Position packets sent from this device will be higher priority, with position broadcasting every two minutes. Smart Position Broadcast will default to off.")
|
||||
case .sensor:
|
||||
return NSLocalizedString("device.role.sensor", comment: "Sensor - For use with remote telemetry sensors. Setting this role will turn on environment telemetry. Telemetry packets sent from this device will be higher priority, with telemetry broadcasting every 7 minutes")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +77,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return Config.DeviceConfig.Role.repeater
|
||||
case .tracker:
|
||||
return Config.DeviceConfig.Role.tracker
|
||||
case .sensor:
|
||||
return Config.DeviceConfig.Role.sensor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
self.lastConnectionError = ""
|
||||
self.connectedVersion = "0.0.0"
|
||||
super.init()
|
||||
//centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
//centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
|
||||
}
|
||||
|
||||
// MARK: Scanning for BLE Devices
|
||||
|
|
|
|||
|
|
@ -62,7 +62,13 @@ class UserSettings: ObservableObject {
|
|||
UserDefaults.standard.set(meshMapCustomTileServer, forKey: "meshMapCustomTileServer")
|
||||
}
|
||||
}
|
||||
|
||||
@Published var meshMapUserTrackingMode: Int {
|
||||
didSet {
|
||||
UserDefaults.standard.set(meshMapUserTrackingMode, forKey: "meshMapUserTrackingMode")
|
||||
UserDefaults.standard.synchronize()
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
self.meshtasticUsername = UserDefaults.standard.object(forKey: "meshtasticusername") as? String ?? ""
|
||||
|
|
@ -75,5 +81,6 @@ class UserSettings: ObservableObject {
|
|||
self.meshMapCenteringMode = UserDefaults.standard.object(forKey: "meshMapCenteringMode") as? Int ?? 0
|
||||
self.meshMapRecentering = UserDefaults.standard.object(forKey: "meshMapRecentering") as? Bool ?? true
|
||||
self.meshMapCustomTileServer = UserDefaults.standard.string(forKey: "meshMapCustomTileServer") ?? ""
|
||||
self.meshMapUserTrackingMode = UserDefaults.standard.object(forKey: "meshMapUserTrackingMode") as? Int ?? 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
|
||||
let centerOnPositionsOnly: Bool
|
||||
@AppStorage("meshMapRecentering") private var recenter = false
|
||||
@AppStorage("meshMapUserTrackingMode") private var userTrackingModeId = 0
|
||||
|
||||
// Offline Maps
|
||||
//make this view dependent on the UserDefault that is updated when importing a new map file
|
||||
|
|
@ -39,18 +40,18 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
mapView.addAnnotations(waypoints)
|
||||
// Logic to manage the map centering options
|
||||
switch centeringMode {
|
||||
case .allAnnotations:
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.fitAllAnnotations()
|
||||
case .allPositions:
|
||||
mapView.fit(annotations: positions, andShow: true)
|
||||
case .clientGps:
|
||||
|
||||
let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003)
|
||||
let center = CLLocationCoordinate2D(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
|
||||
let region = MKCoordinateRegion(center: center, span: span)
|
||||
mapView.setRegion(region, animated: true)
|
||||
mapView.addAnnotations(positions)
|
||||
case .allAnnotations:
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.fitAllAnnotations()
|
||||
case .allPositions:
|
||||
mapView.fit(annotations: positions, andShow: true)
|
||||
case .phoneGps:
|
||||
|
||||
let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003)
|
||||
let center = CLLocationCoordinate2D(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
|
||||
let region = MKCoordinateRegion(center: center, span: span)
|
||||
mapView.setRegion(region, animated: true)
|
||||
mapView.addAnnotations(positions)
|
||||
}
|
||||
|
||||
// Other MKMapView Settings
|
||||
|
|
@ -116,34 +117,36 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
DispatchQueue.main.async {
|
||||
mapView.removeAnnotations(mapView.annotations)
|
||||
mapView.addAnnotations(waypoints)
|
||||
switch centeringMode {
|
||||
case .allAnnotations:
|
||||
mapView.addAnnotations(positions)
|
||||
if recenter {
|
||||
mapView.fitAllAnnotations()
|
||||
}
|
||||
case .allPositions:
|
||||
if recenter {
|
||||
mapView.fit(annotations: positions, andShow: true)
|
||||
} else {
|
||||
mapView.addAnnotations(positions)
|
||||
}
|
||||
case .clientGps:
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.showsUserLocation = true
|
||||
mapView.setUserTrackingMode(.followWithHeading, animated: true)
|
||||
if recenter {
|
||||
// create a 3D Camera
|
||||
let mapCamera = MKMapCamera()
|
||||
mapCamera.centerCoordinate = LocationHelper.currentLocation
|
||||
mapCamera.pitch = 45
|
||||
mapCamera.altitude = 500 // example altitude
|
||||
mapCamera.heading = 45
|
||||
mapView.setUserTrackingMode(UserTrackingModes(rawValue: userTrackingModeId )?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none, animated: true)
|
||||
|
||||
// set the camera property
|
||||
mapView.camera = mapCamera
|
||||
mapView.centerCoordinate = LocationHelper.currentLocation
|
||||
}
|
||||
switch centeringMode {
|
||||
case .allAnnotations:
|
||||
mapView.addAnnotations(positions)
|
||||
if recenter {
|
||||
mapView.fitAllAnnotations()
|
||||
}
|
||||
case .allPositions:
|
||||
if recenter {
|
||||
mapView.fit(annotations: positions, andShow: true)
|
||||
} else {
|
||||
mapView.addAnnotations(positions)
|
||||
}
|
||||
case .phoneGps:
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.showsUserLocation = true
|
||||
|
||||
if recenter {
|
||||
// create a 3D Camera
|
||||
// let mapCamera = MKMapCamera()
|
||||
// mapCamera.centerCoordinate = LocationHelper.currentLocation
|
||||
// mapCamera.pitch = 45
|
||||
// mapCamera.altitude = 500 // example altitude
|
||||
// mapCamera.heading = 45
|
||||
// // set the camera property
|
||||
// mapView.camera = mapCamera
|
||||
|
||||
mapView.centerCoordinate = LocationHelper.currentLocation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -176,7 +179,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
|
||||
case _ as MKClusterAnnotation:
|
||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "nodeGroup") as? MKMarkerAnnotationView ?? MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "WaypointGroup")
|
||||
annotationView.markerTintColor = .brown//.systemRed
|
||||
annotationView.markerTintColor = .brown
|
||||
annotationView.displayPriority = .defaultLow
|
||||
annotationView.tag = -1
|
||||
return annotationView
|
||||
|
|
@ -220,6 +223,9 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
annotationView.glyphImage = UIImage(systemName: "wifi.router.fill")
|
||||
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.tracker {
|
||||
annotationView.glyphImage = UIImage(systemName: "location.viewfinder")
|
||||
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.sensor {
|
||||
annotationView.glyphImage = UIImage(systemName: "sensor")
|
||||
|
||||
}
|
||||
|
||||
let pf = PositionFlags(rawValue: Int(positionAnnotation.nodePosition?.metadata?.positionFlags ?? 3))
|
||||
|
|
|
|||
|
|
@ -58,6 +58,15 @@ struct AppSettings: View {
|
|||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
Picker("map.usertrackingmode", selection: $userSettings.meshMapUserTrackingMode) {
|
||||
ForEach(UserTrackingModes.allCases) { utm in
|
||||
Text(utm.description)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("map.usertrackingmode.description")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
|
||||
Section(header: Text("map options")) {
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@
|
|||
"map.centering"="Centering";
|
||||
"map.recentering"="Automatic Re-centering";
|
||||
"map.type"="kartentyp";
|
||||
"map.usertrackingmode"="User tracking mode";
|
||||
"map.usertrackingmode.none"="None";
|
||||
"map.usertrackingmode.follow"="Follow";
|
||||
"map.usertrackingmode.followwithheading"="Follow with heading";
|
||||
"mesh.log"="Mesh Log";
|
||||
"mesh.log.bluetooth.config %@"="Bluetooth Konfiguration empfangen: %@";
|
||||
"mesh.log.cannedmessage.config %@"="Canned Message module config received: %@";
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@
|
|||
"interval.eighteen.hours"="Eighteen Hours";
|
||||
"interval.twentyfour.hours"="Twenty Four Hours";
|
||||
"interval.thirtysix.hours"="Thirty Six Hours";
|
||||
"interval.fortyeight.hours"="Forty Eight Hours Hours";
|
||||
"interval.fortyeight.hours"="Forty Eight Hours";
|
||||
"interval.seventytwo.hours"="Seventy Two Hours";
|
||||
"keyboard.type"="Keyboard Type";
|
||||
"logging"="Logging";
|
||||
|
|
@ -140,6 +140,10 @@
|
|||
"map.type"="Default Type";
|
||||
"map.centering"="Centering Mode";
|
||||
"map.recentering"="Automatic Re-centering";
|
||||
"map.usertrackingmode"="User tracking mode";
|
||||
"map.usertrackingmode.none"="None";
|
||||
"map.usertrackingmode.follow"="Follow";
|
||||
"map.usertrackingmode.followwithheading"="Follow with heading";
|
||||
"mesh.log"="Mesh Log";
|
||||
"mesh.log.bluetooth.config %@"="Bluetooth config received: %@";
|
||||
"mesh.log.cannedmessage.config %@"="Canned Message module config received: %@";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue