Add history view (shows all location reports for a single accessory)

This commit is contained in:
Milan Stute
2021-03-15 18:49:53 +01:00
parent 2db31902d4
commit 76a01c187b
6 changed files with 49 additions and 15 deletions

View File

@@ -69,6 +69,7 @@ class AccessoryController: ObservableObject {
accessory.lastLocation = report?.location
accessory.locationTimestamp = report?.timestamp
accessory.locations = device.decryptedReports
}
}
}

View File

@@ -31,6 +31,7 @@ class Accessory: ObservableObject, Codable, Identifiable, Equatable, Hashable {
@Published var name: String
let id: Int
let privateKey: Data
@Published var locations: [FindMyLocationReport]?
@Published var color: Color
@Published var icon: String
@Published var lastLocation: CLLocation?

View File

@@ -103,3 +103,11 @@ class AccessoryAnnotation: NSObject, MKAnnotation {
self.accessory = accessory
}
}
class AccessoryHistoryAnnotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
}
}

View File

@@ -14,7 +14,8 @@ import SwiftUI
struct AccessoryMapView: NSViewControllerRepresentable {
@ObservedObject var accessoryController: AccessoryController
@Binding var mapType: MKMapType
var focusedAccessory: Accessory?
@Binding var focusedAccessory: Accessory?
@Binding var showHistory: Bool
func makeNSViewController(context: Context) -> MapViewController {
return MapViewController(nibName: NSNib.Name("MapViewController"), bundle: nil)
@@ -23,8 +24,14 @@ struct AccessoryMapView: NSViewControllerRepresentable {
func updateNSViewController(_ nsViewController: MapViewController, context: Context) {
let accessories = self.accessoryController.accessories
nsViewController.zoom(on: focusedAccessory)
nsViewController.addLastLocations(from: accessories)
nsViewController.focusedAccessory = focusedAccessory
if showHistory {
nsViewController.addAllLocations(from: focusedAccessory!)
nsViewController.zoomInOnAll()
} else {
nsViewController.addLastLocations(from: accessories)
nsViewController.zoomInOnSelection()
}
nsViewController.changeMapType(mapType)
}
}

View File

@@ -28,6 +28,7 @@ struct OpenHaystackMainView: View {
@State var mapType: MKMapType = .standard
@State var isLoading = false
@State var focusedAccessory: Accessory?
@State var historyMapView = false
@State var accessoryToDeploy: Accessory?
@State var showMailPlugInPopover = false
@@ -48,7 +49,7 @@ struct OpenHaystackMainView: View {
.frame(minWidth: 250, idealWidth: 280, maxWidth: .infinity, minHeight: 300, idealHeight: 400, maxHeight: .infinity, alignment: .center)
ZStack {
AccessoryMapView(accessoryController: self.accessoryController, mapType: self.$mapType, focusedAccessory: self.focusedAccessory)
AccessoryMapView(accessoryController: self.accessoryController, mapType: self.$mapType, focusedAccessory: self.$focusedAccessory, showHistory: self.$historyMapView)
.overlay(self.mapOverlay)
if self.popUpAlertType != nil {
VStack {
@@ -108,6 +109,10 @@ struct OpenHaystackMainView: View {
/// All toolbar items shown
var toolbarView: some View {
Group {
Toggle(isOn: $historyMapView) {
Label("Show location history", systemImage: "clock")
}
.disabled(self.focusedAccessory == nil)
Picker("", selection: self.$mapType) {
Text("Satellite").tag(MKMapType.hybrid)

View File

@@ -19,11 +19,7 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
super.viewDidLoad()
self.mapView.delegate = self
self.mapView.register(AccessoryAnnotationView.self, forAnnotationViewWithReuseIdentifier: "Accessory")
}
func zoom(on accessory: Accessory?) {
self.focusedAccessory = accessory
self.zoomInOnSelection()
self.mapView.register(MKPinAnnotationView.self, forAnnotationViewWithReuseIdentifier: "AccessoryHistory")
}
func addLastLocations(from accessories: [Accessory]) {
@@ -34,15 +30,11 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
let annotation = AccessoryAnnotation(accessory: accessory)
self.mapView.addAnnotation(annotation)
}
self.zoomInOnSelection()
}
func zoomInOnSelection() {
var annotations = [MKAnnotation]()
if focusedAccessory == nil {
// Show all locations
annotations = self.mapView.annotations
zoomInOnAll()
} else {
// Show focused accessory
let focusedAnnotation: MKAnnotation? = self.mapView.annotations.first(where: { annotation in
@@ -50,9 +42,16 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
return accessoryAnnotation.accessory == self.focusedAccessory
})
if let annotation = focusedAnnotation {
annotations = [annotation]
zoomInOn(annotations: [annotation])
}
}
}
func zoomInOnAll() {
zoomInOn(annotations: self.mapView.annotations)
}
func zoomInOn(annotations: [MKAnnotation]) {
DispatchQueue.main.async {
self.mapView.showAnnotations(annotations, animated: true)
}
@@ -62,12 +61,25 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
self.mapView.mapType = mapType
}
func addAllLocations(from accessory: Accessory) {
self.mapView.removeAnnotations(self.mapView.annotations)
for location in accessory.locations ?? [] {
let coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude)
let annotation = AccessoryHistoryAnnotation(coordinate: coordinate)
self.mapView.addAnnotation(annotation)
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
switch annotation {
case is AccessoryAnnotation:
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "Accessory", for: annotation)
annotationView.annotation = annotation
return annotationView
case is AccessoryHistoryAnnotation:
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AccessoryHistory", for: annotation)
annotationView.annotation = annotation
return annotationView
default:
return nil
}