227 lines
8.0 KiB
Swift
227 lines
8.0 KiB
Swift
//
|
|
// RealtimeAlertView.swift
|
|
// Earthquake Network
|
|
//
|
|
// Created by Andrea Busi on 15/06/22.
|
|
// Copyright © 2022 Earthquake Network. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import MapKit
|
|
|
|
|
|
class RealtimeAlertContainerView: UIView {
|
|
|
|
lazy var alertView: RealtimeAlertView = {
|
|
let view = RealtimeAlertView()
|
|
view.translatesAutoresizingMaskIntoConstraints = false
|
|
view.eqn_applyRoundedCorners()
|
|
view.clipsToBounds = true
|
|
return view
|
|
}()
|
|
|
|
var animationColor: UIColor = .white
|
|
|
|
// MARK: - Init
|
|
|
|
convenience init() {
|
|
self.init(frame: .zero)
|
|
configureUI()
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func configureUI() {
|
|
backgroundColor = .white
|
|
|
|
addSubview(alertView)
|
|
|
|
let margin: CGFloat = 24
|
|
alertView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: margin).isActive = true
|
|
alertView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -margin).isActive = true
|
|
alertView.topAnchor.constraint(equalTo: topAnchor, constant: margin).isActive = true
|
|
alertView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -margin).isActive = true
|
|
}
|
|
|
|
// MARK: - Public
|
|
|
|
func startBackgroundAnimation() {
|
|
let animation = CABasicAnimation(keyPath: "backgroundColor")
|
|
animation.fromValue = UIColor.white.cgColor
|
|
animation.toValue = animationColor.cgColor
|
|
animation.duration = 2.0
|
|
animation.beginTime = CACurrentMediaTime() + 1
|
|
animation.autoreverses = true
|
|
animation.repeatCount = .infinity
|
|
|
|
layer.add(animation, forKey: "backgroundColor")
|
|
}
|
|
}
|
|
|
|
class RealtimeAlertView: UIView {
|
|
|
|
let titleLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.translatesAutoresizingMaskIntoConstraints = false
|
|
label.font = .preferredFont(forTextStyle: .title2)
|
|
label.text = NSLocalizedString("app_name", comment: "")
|
|
return label
|
|
}()
|
|
|
|
let descriptionLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.translatesAutoresizingMaskIntoConstraints = false
|
|
label.font = .preferredFont(forTextStyle: .body)
|
|
label.numberOfLines = 0
|
|
label.textAlignment = .center
|
|
return label
|
|
}()
|
|
|
|
let waveTimeLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.translatesAutoresizingMaskIntoConstraints = false
|
|
label.font = .preferredFont(forTextStyle: .largeTitle)
|
|
label.textColor = AppTheme.Colors.red
|
|
label.text = String.localizedStringWithFormat(NSLocalizedString("alert_wave", comment: ""), 0)
|
|
label.textAlignment = .center
|
|
label.numberOfLines = 2
|
|
label.isHidden = true
|
|
return label
|
|
}()
|
|
|
|
let intensityLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.translatesAutoresizingMaskIntoConstraints = false
|
|
label.font = .preferredFont(forTextStyle: .largeTitle)
|
|
label.textColor = AppTheme.Colors.red
|
|
label.textAlignment = .center
|
|
label.numberOfLines = 2
|
|
return label
|
|
}()
|
|
|
|
lazy var mapView: MKMapView = {
|
|
let map = MKMapView()
|
|
map.translatesAutoresizingMaskIntoConstraints = false
|
|
map.delegate = self
|
|
map.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
|
map.showsUserLocation = true
|
|
return map
|
|
}()
|
|
|
|
let closeButton: EQNBlurredCloseButton = {
|
|
let button = EQNBlurredCloseButton()
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
button.setTitleColor(.darkGray, for: .normal)
|
|
return button
|
|
}()
|
|
|
|
// MARK: - Init
|
|
|
|
convenience init() {
|
|
self.init(frame: .zero)
|
|
configureUI()
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func configureUI() {
|
|
backgroundColor = AppTheme.Colors.lightGray
|
|
|
|
addSubview(closeButton)
|
|
addSubview(titleLabel)
|
|
addSubview(descriptionLabel)
|
|
addSubview(mapView)
|
|
|
|
closeButton.addDefaultConstraint(to: self)
|
|
|
|
titleLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
|
titleLabel.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor, constant: -10.0).isActive = true
|
|
titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 10.0).isActive = true
|
|
|
|
descriptionLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
|
descriptionLabel.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true
|
|
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20.0).isActive = true
|
|
|
|
let stackView = UIStackView(arrangedSubviews: [waveTimeLabel, intensityLabel])
|
|
stackView.translatesAutoresizingMaskIntoConstraints = false
|
|
stackView.axis = .vertical
|
|
stackView.distribution = .equalSpacing
|
|
stackView.spacing = 20.0
|
|
addSubview(stackView)
|
|
|
|
stackView.leadingAnchor.constraint(equalTo: descriptionLabel.leadingAnchor).isActive = true
|
|
stackView.trailingAnchor.constraint(equalTo: descriptionLabel.trailingAnchor).isActive = true
|
|
stackView.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 20.0).isActive = true
|
|
|
|
mapView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
|
mapView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
|
mapView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 20.0).isActive = true
|
|
mapView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
|
}
|
|
|
|
// MARK: - Public
|
|
|
|
func addMapCircle(
|
|
center: CLLocationCoordinate2D,
|
|
radius: CLLocationDistance,
|
|
overlayId: String
|
|
) {
|
|
// remove any other existing overlays
|
|
let overlays = mapView.overlays.filter { $0.title == overlayId }
|
|
mapView.removeOverlays(overlays)
|
|
|
|
// add new overlay
|
|
let circle = MKCircle(center: center, radius: radius)
|
|
circle.title = overlayId
|
|
mapView.addOverlay(circle)
|
|
}
|
|
|
|
func addMapLine(
|
|
coordinates: [CLLocationCoordinate2D]
|
|
) {
|
|
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
|
|
mapView.addOverlay(polyline)
|
|
}
|
|
|
|
func addMapAnnotation(
|
|
title: String = "",
|
|
center: CLLocationCoordinate2D,
|
|
intensity: Int
|
|
) {
|
|
let annotation = EQNMapAnnotationPastquake(title: title, coordinate: center, intensity: intensity)
|
|
mapView.addAnnotation(annotation)
|
|
}
|
|
}
|
|
|
|
extension RealtimeAlertView: MKMapViewDelegate {
|
|
|
|
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
|
switch overlay {
|
|
case let circle as MKCircle:
|
|
let circleRenderer = MKCircleRenderer(overlay: circle)
|
|
circleRenderer.strokeColor = AppTheme.Colors.red
|
|
circleRenderer.fillColor = AppTheme.Colors.red.withAlphaComponent(0.2)
|
|
circleRenderer.lineWidth = 3.0
|
|
return circleRenderer
|
|
case let polyline as MKPolyline:
|
|
let polylineRenderer = MKPolylineRenderer(polyline: polyline)
|
|
polylineRenderer.strokeColor = .blue
|
|
polylineRenderer.lineWidth = 2.0
|
|
return polylineRenderer
|
|
default:
|
|
return MKOverlayRenderer(overlay: overlay)
|
|
}
|
|
}
|
|
|
|
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> 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
|
|
}
|
|
}
|