mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Location cleanup
Sizing cleanup for timestamps on iPadOS and macOS tables.
This commit is contained in:
parent
5a532392ab
commit
0c9acee6d6
6 changed files with 79 additions and 51 deletions
|
|
@ -16,8 +16,6 @@ class LocationHelper: NSObject, ObservableObject, CLLocationManagerDelegate {
|
|||
locationManager.pausesLocationUpdatesAutomatically = true
|
||||
locationManager.allowsBackgroundLocationUpdates = true
|
||||
locationManager.activityType = .otherNavigation
|
||||
//locationManager.requestWhenInUseAuthorization()
|
||||
//locationManager.startUpdatingLocation()
|
||||
}
|
||||
|
||||
// Apple Park
|
||||
|
|
@ -89,10 +87,7 @@ class LocationHelper: NSObject, ObservableObject, CLLocationManagerDelegate {
|
|||
}
|
||||
return sats
|
||||
}
|
||||
//}
|
||||
|
||||
//extension LocationHelper: CLLocationManagerDelegate {
|
||||
|
||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||
switch manager.authorizationStatus {
|
||||
case .authorizedWhenInUse:
|
||||
|
|
@ -114,11 +109,11 @@ class LocationHelper: NSObject, ObservableObject, CLLocationManagerDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
print("Location manager error: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
|
||||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
print("Location manager error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,10 +120,9 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
let latest = positions
|
||||
.filter { $0.latest == true }
|
||||
.sorted { $0.nodePosition?.num ?? 0 > $1.nodePosition?.num ?? -1 }
|
||||
|
||||
let annotationCount = waypoints.count + (showNodeHistory ? positions.count : latest.count)
|
||||
|
||||
|
||||
// if annotationCount != mapView.annotations.count {
|
||||
if annotationCount != mapView.annotations.count {
|
||||
print("Annotation Count: \(annotationCount) Map Annotations: \(mapView.annotations.count)")
|
||||
mapView.removeAnnotations(mapView.annotations)
|
||||
mapView.addAnnotations(waypoints)
|
||||
|
|
@ -168,7 +167,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
mapView.showsUserLocation = true
|
||||
}
|
||||
mapView.setUserTrackingMode(userTrackingMode, animated: true)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ struct DeviceMetricsLog: View {
|
|||
TableColumn("timestamp") { dm in
|
||||
Text(dm.time?.formattedDate(format: dateFormatString) ?? NSLocalizedString("unknown.age", comment: ""))
|
||||
}
|
||||
.width(min: 180)
|
||||
}
|
||||
} else {
|
||||
ScrollView {
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ struct EnvironmentMetricsLog: View {
|
|||
TableColumn("timestamp") { em in
|
||||
Text(em.time?.formattedDate(format: dateFormatString) ?? NSLocalizedString("unknown.age", comment: ""))
|
||||
}
|
||||
.width(min: 180)
|
||||
}
|
||||
} else {
|
||||
ScrollView {
|
||||
|
|
|
|||
|
|
@ -7,34 +7,42 @@
|
|||
import SwiftUI
|
||||
|
||||
struct PositionLog: View {
|
||||
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
|
||||
var useGrid: Bool {
|
||||
let result = (verticalSizeClass == .regular || verticalSizeClass == .compact) && horizontalSizeClass == .compact
|
||||
return result
|
||||
}
|
||||
|
||||
@State var isExporting = false
|
||||
@State var exportString = ""
|
||||
|
||||
|
||||
var node: NodeInfoEntity
|
||||
|
||||
|
||||
@State private var isPresentingClearLogConfirm = false
|
||||
|
||||
@State private var sortOrder = [KeyPathComparator(\PositionEntity.latitude)]
|
||||
|
||||
var body: some View {
|
||||
|
||||
|
||||
NavigationStack {
|
||||
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
|
||||
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
if UIDevice.current.userInterfaceIdiom == .pad && !useGrid || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
// Add a table for mac and ipad
|
||||
Table(node.positions?.reversed() as? [PositionEntity] ?? []) {
|
||||
TableColumn("SeqNo") { position in
|
||||
Text(String(position.seqNo))
|
||||
}
|
||||
var positions = node.positions?.reversed() as? [PositionEntity] ?? []
|
||||
|
||||
Table(positions) {
|
||||
TableColumn("Latitude") { position in
|
||||
Text(String(format: "%.5f", position.latitude ?? 0))
|
||||
}
|
||||
.width(min: 120)
|
||||
TableColumn("Longitude") { position in
|
||||
Text(String(format: "%.5f", position.longitude ?? 0))
|
||||
}
|
||||
.width(min: 120)
|
||||
TableColumn("Altitude") { position in
|
||||
let altitude = Measurement(value: Double(position.altitude), unit: UnitLength.meters)
|
||||
Text(String(altitude.formatted()))
|
||||
|
|
@ -55,10 +63,11 @@ struct PositionLog: View {
|
|||
TableColumn("Time Stamp") { position in
|
||||
Text(position.time?.formattedDate(format: dateFormatString) ?? NSLocalizedString("unknown.age", comment: ""))
|
||||
}
|
||||
.width(min: 180)
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
ScrollView {
|
||||
// Use a grid on iOS as a table only shows a single column
|
||||
let columns = [
|
||||
|
|
@ -69,9 +78,8 @@ struct PositionLog: View {
|
|||
GridItem(spacing: 0)
|
||||
]
|
||||
LazyVGrid(columns: columns, alignment: .leading, spacing: 1) {
|
||||
|
||||
|
||||
GridRow {
|
||||
|
||||
Text("Latitude")
|
||||
.font(.caption2)
|
||||
.fontWeight(.bold)
|
||||
|
|
@ -107,9 +115,9 @@ struct PositionLog: View {
|
|||
}
|
||||
.padding(.leading)
|
||||
}
|
||||
|
||||
|
||||
HStack {
|
||||
|
||||
|
||||
Button(role: .destructive) {
|
||||
isPresentingClearLogConfirm = true
|
||||
} label: {
|
||||
|
|
@ -127,41 +135,41 @@ struct PositionLog: View {
|
|||
Button("Delete all positions?", role: .destructive) {
|
||||
if clearPositions(destNum: node.num, context: context) {
|
||||
print("Successfully Cleared Position Log")
|
||||
|
||||
|
||||
} else {
|
||||
print("Clear Position Log Failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
|
||||
|
||||
exportString = positionToCsvFile(positions: node.positions!.array as? [PositionEntity] ?? [])
|
||||
isExporting = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
|
||||
} label: {
|
||||
|
||||
Label("save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.fileExporter(
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
}
|
||||
.fileExporter(
|
||||
isPresented: $isExporting,
|
||||
document: CsvDocument(emptyCsv: exportString),
|
||||
contentType: .commaSeparatedText,
|
||||
defaultFilename: String("\(node.user?.longName ?? "Node") Position Log"),
|
||||
onCompletion: { result in
|
||||
|
||||
|
||||
if case .success = result {
|
||||
|
||||
|
||||
print("Position log download succeeded.")
|
||||
self.isExporting = false
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
print("Position log download failed: \(result).")
|
||||
}
|
||||
}
|
||||
|
|
@ -169,13 +177,13 @@ struct PositionLog: View {
|
|||
}
|
||||
.navigationTitle("Position Log \(node.positions?.count ?? 0) Points")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
|
||||
self.bleManager.context = context
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,30 @@ struct AppSettings: View {
|
|||
}
|
||||
|
||||
Section(header: Text("phone.gps")) {
|
||||
let accuracy = Measurement(value: locationHelper.locationManager.location?.horizontalAccuracy ?? 300, unit: UnitLength.meters)
|
||||
let altitiude = Measurement(value: locationHelper.locationManager.location?.altitude ?? 0, unit: UnitLength.meters)
|
||||
let speed = Measurement(value: locationHelper.locationManager.location?.speed ?? 0, unit: UnitSpeed.kilometersPerHour)
|
||||
HStack {
|
||||
Label("Accuracy \(accuracy.formatted())", systemImage: "scope")
|
||||
.font(.callout)
|
||||
Label("Sats \(LocationHelper.satsInView)", systemImage: "sparkles")
|
||||
.font(.callout)
|
||||
}
|
||||
Label("Coordinates \(String(format: "%.5f", locationHelper.locationManager.location?.coordinate.latitude ?? 0)), \(String(format: "%.5f", locationHelper.locationManager.location?.coordinate.longitude ?? 0))", systemImage: "mappin")
|
||||
.font(.callout)
|
||||
.textSelection(.enabled)
|
||||
if locationHelper.locationManager.location?.verticalAccuracy ?? 0 > 0 {
|
||||
Label("Altitude \(altitiude.formatted())", systemImage: "mountain.2")
|
||||
.font(.callout)
|
||||
}
|
||||
if locationHelper.locationManager.location?.courseAccuracy ?? 0 > 0 {
|
||||
Label("Heading \(String(format: "%.2f", locationHelper.locationManager.location?.course ?? 0))°", systemImage: "location.circle")
|
||||
.font(.callout)
|
||||
}
|
||||
if locationHelper.locationManager.location?.speedAccuracy ?? 0 > 0 {
|
||||
Label("Speed \(speed.formatted())", systemImage: "speedometer")
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
Toggle(isOn: $userSettings.provideLocation) {
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue