Files
eqn.ios/Sources/Earthquake Network/Controllers/Alerts/PasquakesMapViewController.swift
T
2024-06-10 22:14:01 +02:00

166 lines
6.1 KiB
Swift

//
// PasquakesMapViewController.swift
// Earthquake Network
//
// Created by Andrea Busi on 10/03/21.
// Copyright © 2021 Earthquake Network. All rights reserved.
//
import Foundation
import MapKit
class PasquakesMapViewController: EQNBaseMapViewController {
override var availableFilters: [EQNBaseMapFilter] {
[ .oneMonth, .oneWeek, .oneDay, .oneHour ]
}
// MARK: - Internal
/// Pasquakes currently showned on the map
private var filteredPastquakes = [EQNPastquakes]()
/// Keep track of the evaluated center, to show circles around it
private var centerLocation: CLLocation?
/// Contains circles drawed on the map
private var mapCircles = [MKCircle]()
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Public
override func registerMapAnnotationViews() {
mapView.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
}
override func loadDataSource() {
guard let list = EQNManager.manager().datiPastQuakes else { return }
// set the base filter
setDefaultFilter(for: list)
// filter report based on selected filter
let filterDate = filter.date
filteredPastquakes = list.filter { $0.date > filterDate }
// create annotations to display on the map
let annotations = filteredPastquakes.compactMap { EQNMapAnnotationPastquake(pastquake: $0) }
// elaborate the center
centerLocation = elaborateCenter(for: filteredPastquakes)
// update map and center
updateMap(with: annotations)
if let centerLocation = centerLocation {
addCircles(for: centerLocation)
}
}
override func elaborateMapCenter() {
guard let centerLocation = centerLocation else { return }
setMapCenter(for: centerLocation)
}
override func didTapAnnotation(_ annotation: MKAnnotation) {
mapView.deselectAnnotation(annotation, animated: true)
guard let annotation = annotation as? EQNMapAnnotationPastquake, let pastquake = annotation.pastquake else {
return
}
let difference = Int(Date().timeIntervalSince(pastquake.date) / 60.0)
let title = EQNUtility.formattedString(forTimeDifference: difference)
let message = ""
+ "📱 " + String(format: NSLocalizedString("map_number", comment: ""), "\(pastquake.users)")
+ "\n" + EQNUtility.formattedDate(from: pastquake.date) + " \(NSLocalizedString("share_yourtime", comment: ""))"
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("official_close", comment: ""), style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
// MARK: - Private
private func elaborateCenter(for pastquakes: [EQNPastquakes]) -> CLLocation? {
var center: CLLocation?
// Se c'è un rilevamento distante dall'utente meno del raggio di notifica,
// allora il centro è su quel rilevamento
if let userPosition = CLLocationManager().location {
let nearestPastquake = filteredPastquakes
.sorted(by: { (pastquake1, pastquake2) -> Bool in
abs(userPosition.distance(from: pastquake1.coordinate)) < abs(userPosition.distance(from: pastquake2.coordinate))
})
.first
// controlliamo che sia inferiore al raggio massimo impostato per le notifiche
if let radiusLow = Double(EQNSettingRealTimeAlert.shared.raggioSismiLievi),
let radiusStrong = Double(EQNSettingRealTimeAlert.shared.raggioSismiForti),
let nearestPastquake = nearestPastquake {
let radius = max(radiusLow, radiusStrong)
if abs(nearestPastquake.coordinate.distance(from: userPosition)) < radius {
center = nearestPastquake.coordinate
}
}
}
// altrimenti il centro è sul rilevamento più recente
if center == nil, let newestPastquake = filteredPastquakes.sorted(by: { $0.date > $1.date }).first {
center = newestPastquake.coordinate
}
return center
}
private func addCircles(for location: CLLocation) {
// aggiungiamo 3 cerchi concentrici per il punto specificato
// li inseriamo a a 50, 100 e 200 km.
let circles = [
MKCircle(center: location.coordinate, radius: 25_000),
MKCircle(center: location.coordinate, radius: 100_000),
MKCircle(center: location.coordinate, radius: 200_000)
]
// elimino vecchie circonferenze
mapView.removeOverlays(mapCircles)
// !!note: is important to assign here the circles
// otherwise `addOverlays` will not work
mapCircles = circles
// creo nuovi cerchi
mapView.addOverlays(circles)
}
// MARK: - Map
override func setupAnnotationView(for annotation: MKAnnotation, on mapView: MKMapView) -> MKAnnotationView? {
guard let annotation = annotation as? EQNMapAnnotationPastquake else {
return nil
}
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
annotationView.image = annotation.image
annotationView.title = annotation.title
return annotationView
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let circleOverlay = overlay as? MKCircle else {
return MKOverlayRenderer(overlay: overlay)
}
let circle = MKCircleRenderer(overlay: circleOverlay)
circle.strokeColor = AppTheme.Colors.darkGray
circle.lineWidth = 1.0
return circle
}
}