93 lines
2.9 KiB
Swift
93 lines
2.9 KiB
Swift
//
|
|
// EQNRealtimeAlert.swift
|
|
// Earthquake Network
|
|
//
|
|
// Created by Andrea Busi on 17/06/22.
|
|
// Copyright © 2022 Earthquake Network. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import CoreLocation
|
|
import Shogun
|
|
|
|
|
|
@objc
|
|
class EQNRealtimeAlert: NSObject {
|
|
|
|
typealias NotificationPayload = [String: Any]
|
|
|
|
/// Title to display
|
|
var title: String = ""
|
|
/// Earthquake coordinate
|
|
let coordinate: CLLocation
|
|
/// Earthquake intensity
|
|
let intensity: Int
|
|
/// Earthquake wave speed
|
|
let waveSpeed: Double
|
|
/// Calculated timestamp for earthquake on user position
|
|
let impactTimestamp: Date
|
|
|
|
// MARK: - Init
|
|
|
|
@objc
|
|
init?(notification: [String: Any]) {
|
|
guard let alert = Self.getPushAlertPayload(from: notification),
|
|
let coordinate = Self.getCoordinate(from: notification),
|
|
let impactTimestamp = EQNUtility.calculateUserSeismicTimestamp(fromUserInfo: notification) else {
|
|
return nil
|
|
}
|
|
|
|
self.coordinate = coordinate
|
|
self.impactTimestamp = impactTimestamp
|
|
if let title = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
|
|
self.title = String(format: NSLocalizedString(title, comment: ""), arg)
|
|
}
|
|
self.intensity = notification.integer(forKey: "intensity", orDefault: 0)
|
|
self.waveSpeed = notification.double(forKey: "wave_speed", orDefault: 0.0) * 1000 // m/s
|
|
}
|
|
|
|
func distanceFromUser() -> CLLocationDistance {
|
|
EQNUser.default().lastPosition?.distance(from: coordinate) ?? 0.0
|
|
}
|
|
|
|
/// Remaining time before earthquake gets user position
|
|
func currentCountdown() -> Int {
|
|
let now = Date()
|
|
let difference = lround(max(impactTimestamp.timeIntervalSince(now), 0))
|
|
return difference
|
|
}
|
|
|
|
@objc
|
|
func isCountdownExpired() -> Bool {
|
|
currentCountdown() <= 0
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
/// Get `aps.alert` object inside a given notification payload
|
|
/// - Parameter notification: Notification payload
|
|
/// - Returns: `aps.alert` object if found, nil otherwise
|
|
static func getPushAlertPayload(
|
|
from notification: NotificationPayload
|
|
) -> NotificationPayload? {
|
|
guard let aps = notification["aps"] as? [String: Any],
|
|
let alert = aps["alert"] as? [String: Any] else {
|
|
return nil
|
|
}
|
|
return alert
|
|
}
|
|
|
|
/// Retrieve coordinate of earthquake from the notification payload
|
|
/// - Parameter notification: Notification payload
|
|
/// - Returns: Coordinate if found, nil otherwise
|
|
static func getCoordinate(
|
|
from notification: NotificationPayload
|
|
) -> CLLocation? {
|
|
guard let latitude = notification.double(forKey: "latitude"),
|
|
let longitude = notification.double(forKey: "longitude") else {
|
|
return nil
|
|
}
|
|
return CLLocation(latitude: latitude, longitude: longitude)
|
|
}
|
|
}
|