Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f85c60fdda | |||
| 5f2a083789 | |||
| 9e54f74847 | |||
| b6f9232f56 | |||
| dee14dea0f | |||
| db0bde2f59 | |||
| 79d0d27ec5 | |||
| 68012ec406 | |||
| 59feb7699b | |||
| 388f4e8b89 | |||
| ca3c9ebd83 | |||
| f23c19bce7 | |||
| 276fa2032a | |||
| 09f0d4d4d8 | |||
| 25f061ad5a | |||
| b9d9f7579c | |||
| 39f5ff0249 | |||
| af68d70be5 | |||
| dab999a78d | |||
| f5ede5c26d | |||
| 6d4c1eb979 | |||
| 9bf6b75dac | |||
| 69b83e9944 | |||
| 5061e36a45 | |||
| 8919f3c08f | |||
| 9cf9ef8a64 | |||
| 9ee3a478f0 | |||
| 8744595b56 | |||
| fa05d6b5c4 | |||
| 471ccc9e4a | |||
| 55de6f5ba0 | |||
| b12a9cc476 | |||
| a2f740b0a8 | |||
| 9cf93e652b |
@@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 5.11
|
||||||
|
- Numeri romani in etichette shakemaps
|
||||||
|
- Aggiunta barra di recap dei filtri in Lista Sismi
|
||||||
|
- Riscritta NotificationContent in Swift
|
||||||
|
- Aggiunta animazione onda sismica in NotificationContent (+ altre modifiche grafiche)
|
||||||
|
|
||||||
|
## 5.10
|
||||||
|
- Usato endpoint cache per distquake_download_areacheck
|
||||||
|
- Aggiunta impostazione per non riprodurre suono notifiche per simsi deboli
|
||||||
|
|
||||||
|
## Versione 5.9.1
|
||||||
|
- Corretto ordinamento in sottoscrizioni attive (prima Top10k)
|
||||||
|
- Modificato parsing per risolvere crash con valori nulli
|
||||||
|
|
||||||
## Versione 5.9
|
## Versione 5.9
|
||||||
- Aggiunta barra laterale in lista sismi
|
- Aggiunta barra laterale in lista sismi
|
||||||
- Aggiunto filtro "sismi percepiti"
|
- Aggiunto filtro "sismi percepiti"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="M4Y-Lb-cyx">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="M4Y-Lb-cyx">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -11,37 +11,45 @@
|
|||||||
<!--Notification View Controller-->
|
<!--Notification View Controller-->
|
||||||
<scene sceneID="cwh-vc-ff4">
|
<scene sceneID="cwh-vc-ff4">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="M4Y-Lb-cyx" userLabel="Notification View Controller" customClass="NotificationViewController" sceneMemberID="viewController">
|
<viewController id="M4Y-Lb-cyx" userLabel="Notification View Controller" customClass="NotificationContentViewController" customModule="EQNNotificationContent" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN">
|
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="330"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pCT-Wh-lut">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pCT-Wh-lut">
|
||||||
<rect key="frame" x="8" y="216" width="304" height="20.5"/>
|
<rect key="frame" x="8" y="350" width="304" height="20.5"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bT3-3m-qLh">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bT3-3m-qLh">
|
||||||
<rect key="frame" x="8" y="285" width="304" height="29"/>
|
<rect key="frame" x="8" y="417" width="304" height="53"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
|
||||||
<color key="textColor" red="0.91764705879999997" green="0.46274509800000002" blue="0.0078431372550000003" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.91764705879999997" green="0.46274509800000002" blue="0.0078431372550000003" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="4ID-Zb-OQF">
|
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" showsUserLocation="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4ID-Zb-OQF">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
|
<rect key="frame" x="0.0" y="20" width="320" height="320"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="200" id="Pgl-8e-ePq"/>
|
<constraint firstAttribute="width" secondItem="4ID-Zb-OQF" secondAttribute="height" multiplier="1:1" id="yXb-UG-FZY"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="delegate" destination="M4Y-Lb-cyx" id="Cs2-OY-eT2"/>
|
<outlet property="delegate" destination="M4Y-Lb-cyx" id="Cs2-OY-eT2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</mapView>
|
</mapView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f3d-th-bgU">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f3d-th-bgU">
|
||||||
<rect key="frame" x="8" y="244.5" width="304" height="20.5"/>
|
<rect key="frame" x="8" y="380.5" width="304" height="26.5"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="s7c-ag-zBA" customClass="EQNBlurredCloseButton" customModule="EQNNotificationContent" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="103" y="26" width="114" height="35"/>
|
||||||
|
<state key="normal" title="Button"/>
|
||||||
|
<buttonConfiguration key="configuration" style="plain" title="Tap to open"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="openAppTapped:" destination="M4Y-Lb-cyx" eventType="touchUpInside" id="Sw3-xS-cXi"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="2BE-c3-nQJ"/>
|
<viewLayoutGuide key="safeArea" id="2BE-c3-nQJ"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -49,23 +57,26 @@
|
|||||||
<constraint firstItem="f3d-th-bgU" firstAttribute="leading" secondItem="pCT-Wh-lut" secondAttribute="leading" id="7qA-vV-ocI"/>
|
<constraint firstItem="f3d-th-bgU" firstAttribute="leading" secondItem="pCT-Wh-lut" secondAttribute="leading" id="7qA-vV-ocI"/>
|
||||||
<constraint firstItem="2BE-c3-nQJ" firstAttribute="trailing" secondItem="pCT-Wh-lut" secondAttribute="trailing" constant="8" id="CAC-UM-SaJ"/>
|
<constraint firstItem="2BE-c3-nQJ" firstAttribute="trailing" secondItem="pCT-Wh-lut" secondAttribute="trailing" constant="8" id="CAC-UM-SaJ"/>
|
||||||
<constraint firstItem="f3d-th-bgU" firstAttribute="trailing" secondItem="pCT-Wh-lut" secondAttribute="trailing" id="Dd7-BF-iOG"/>
|
<constraint firstItem="f3d-th-bgU" firstAttribute="trailing" secondItem="pCT-Wh-lut" secondAttribute="trailing" id="Dd7-BF-iOG"/>
|
||||||
<constraint firstItem="f3d-th-bgU" firstAttribute="top" secondItem="pCT-Wh-lut" secondAttribute="bottom" constant="8" id="FJ8-nn-ydU"/>
|
<constraint firstItem="f3d-th-bgU" firstAttribute="top" secondItem="pCT-Wh-lut" secondAttribute="bottom" constant="10" id="FJ8-nn-ydU"/>
|
||||||
<constraint firstItem="2BE-c3-nQJ" firstAttribute="bottom" secondItem="bT3-3m-qLh" secondAttribute="bottom" constant="16" id="I71-6U-jK3"/>
|
<constraint firstItem="s7c-ag-zBA" firstAttribute="top" secondItem="2BE-c3-nQJ" secondAttribute="top" constant="6" id="Gsp-ye-V4M"/>
|
||||||
<constraint firstItem="pCT-Wh-lut" firstAttribute="top" secondItem="4ID-Zb-OQF" secondAttribute="bottom" constant="16" id="It9-RA-906"/>
|
<constraint firstItem="2BE-c3-nQJ" firstAttribute="bottom" secondItem="bT3-3m-qLh" secondAttribute="bottom" constant="10" id="I71-6U-jK3"/>
|
||||||
|
<constraint firstItem="pCT-Wh-lut" firstAttribute="top" secondItem="4ID-Zb-OQF" secondAttribute="bottom" constant="10" id="It9-RA-906"/>
|
||||||
<constraint firstItem="bT3-3m-qLh" firstAttribute="trailing" secondItem="f3d-th-bgU" secondAttribute="trailing" id="KXf-x4-iZs"/>
|
<constraint firstItem="bT3-3m-qLh" firstAttribute="trailing" secondItem="f3d-th-bgU" secondAttribute="trailing" id="KXf-x4-iZs"/>
|
||||||
<constraint firstItem="bT3-3m-qLh" firstAttribute="leading" secondItem="f3d-th-bgU" secondAttribute="leading" id="QlJ-Vh-oi4"/>
|
<constraint firstItem="bT3-3m-qLh" firstAttribute="leading" secondItem="f3d-th-bgU" secondAttribute="leading" id="QlJ-Vh-oi4"/>
|
||||||
<constraint firstItem="bT3-3m-qLh" firstAttribute="top" secondItem="f3d-th-bgU" secondAttribute="bottom" constant="20" id="UUO-2F-eE7"/>
|
<constraint firstItem="bT3-3m-qLh" firstAttribute="top" secondItem="f3d-th-bgU" secondAttribute="bottom" constant="10" id="UUO-2F-eE7"/>
|
||||||
<constraint firstItem="4ID-Zb-OQF" firstAttribute="trailing" secondItem="2BE-c3-nQJ" secondAttribute="trailing" id="buf-BU-I5b"/>
|
<constraint firstItem="4ID-Zb-OQF" firstAttribute="trailing" secondItem="2BE-c3-nQJ" secondAttribute="trailing" id="buf-BU-I5b"/>
|
||||||
<constraint firstItem="4ID-Zb-OQF" firstAttribute="leading" secondItem="2BE-c3-nQJ" secondAttribute="leading" id="e8D-ji-t64"/>
|
<constraint firstItem="4ID-Zb-OQF" firstAttribute="leading" secondItem="2BE-c3-nQJ" secondAttribute="leading" id="e8D-ji-t64"/>
|
||||||
<constraint firstItem="4ID-Zb-OQF" firstAttribute="top" secondItem="2BE-c3-nQJ" secondAttribute="top" id="hL6-gc-S6i"/>
|
<constraint firstItem="4ID-Zb-OQF" firstAttribute="top" secondItem="2BE-c3-nQJ" secondAttribute="top" id="hL6-gc-S6i"/>
|
||||||
|
<constraint firstItem="s7c-ag-zBA" firstAttribute="centerX" secondItem="S3S-Oj-5AN" secondAttribute="centerX" id="mKj-2O-QDw"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<extendedEdge key="edgesForExtendedLayout"/>
|
<extendedEdge key="edgesForExtendedLayout"/>
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
<size key="freeformSize" width="320" height="330"/>
|
<size key="freeformSize" width="320" height="480"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="descriptionLabel" destination="f3d-th-bgU" id="Aym-KJ-DqY"/>
|
<outlet property="descriptionLabel" destination="f3d-th-bgU" id="Aym-KJ-DqY"/>
|
||||||
<outlet property="mapView" destination="4ID-Zb-OQF" id="x8o-nT-bL4"/>
|
<outlet property="mapView" destination="4ID-Zb-OQF" id="x8o-nT-bL4"/>
|
||||||
|
<outlet property="tapToOpenButton" destination="s7c-ag-zBA" id="4aZ-hT-1vc"/>
|
||||||
<outlet property="titleLabel" destination="pCT-Wh-lut" id="uIg-dn-Wms"/>
|
<outlet property="titleLabel" destination="pCT-Wh-lut" id="uIg-dn-Wms"/>
|
||||||
<outlet property="waveLabel" destination="bT3-3m-qLh" id="AkJ-nd-d2R"/>
|
<outlet property="waveLabel" destination="bT3-3m-qLh" id="AkJ-nd-d2R"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// NotificationContentViewController.swift
|
||||||
|
// EQNNotificationContent
|
||||||
|
//
|
||||||
|
// Created by Andrea Busi on 24/07/25.
|
||||||
|
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MapKit
|
||||||
|
import UserNotifications
|
||||||
|
import UserNotificationsUI
|
||||||
|
|
||||||
|
class NotificationContentViewController: UIViewController {
|
||||||
|
|
||||||
|
// MARK: - UI
|
||||||
|
|
||||||
|
@IBOutlet private weak var titleLabel: UILabel!
|
||||||
|
@IBOutlet private weak var descriptionLabel: UILabel!
|
||||||
|
@IBOutlet private weak var waveLabel: UILabel!
|
||||||
|
@IBOutlet private weak var mapView: MKMapView!
|
||||||
|
@IBOutlet private weak var tapToOpenButton: UIButton!
|
||||||
|
|
||||||
|
private var animator: MapSeismicWaveAnimator?
|
||||||
|
|
||||||
|
// MARK: - View
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
let tapRecognizer = UITapGestureRecognizer(
|
||||||
|
target: self,
|
||||||
|
action: #selector(openAppTapped(_:))
|
||||||
|
)
|
||||||
|
view.addGestureRecognizer(tapRecognizer)
|
||||||
|
|
||||||
|
mapView
|
||||||
|
.register(
|
||||||
|
EQNCustomAnnotationView.self,
|
||||||
|
forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier
|
||||||
|
)
|
||||||
|
mapView
|
||||||
|
.register(
|
||||||
|
EQNCustomAnnotationView.self,
|
||||||
|
forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SmallIdentifier
|
||||||
|
)
|
||||||
|
tapToOpenButton.setTitle("tap_to_open".localized, for: .normal)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
|
||||||
|
animator?.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Actions
|
||||||
|
|
||||||
|
@IBAction private func openAppTapped(_ sender: Any) {
|
||||||
|
extensionContext?.performNotificationDefaultAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NotificationContentViewController: UNNotificationContentExtension {
|
||||||
|
|
||||||
|
func didReceive(_ notification: UNNotification) {
|
||||||
|
let content = notification.request.content
|
||||||
|
|
||||||
|
titleLabel.text = content.title
|
||||||
|
descriptionLabel.text = content.body
|
||||||
|
|
||||||
|
let notification = EQNRealtimePushNotification.from(
|
||||||
|
userInfo: content.userInfo,
|
||||||
|
title: "",
|
||||||
|
displayTitle: content.title,
|
||||||
|
displayBody: content.body
|
||||||
|
)
|
||||||
|
if let notification {
|
||||||
|
let coordinate = notification.coordinate.coordinate
|
||||||
|
let span = MKCoordinateSpan(latitudeDelta: 6, longitudeDelta: 6)
|
||||||
|
let region = MKCoordinateRegion(
|
||||||
|
center: coordinate,
|
||||||
|
span: span
|
||||||
|
)
|
||||||
|
mapView.setCenter(coordinate, animated: false)
|
||||||
|
mapView.setRegion(region, animated: true)
|
||||||
|
|
||||||
|
switch notification.type.lowercased() {
|
||||||
|
case "eqn":
|
||||||
|
let annotation = EQNMapAnnotationPastquake(
|
||||||
|
title: "",
|
||||||
|
coordinate: coordinate,
|
||||||
|
intensity: notification.intensity
|
||||||
|
)
|
||||||
|
mapView.addAnnotation(annotation)
|
||||||
|
case "manual":
|
||||||
|
let annotation = EQNMapAnnotationUserReport(
|
||||||
|
magnitude: notification.magnitude,
|
||||||
|
coordinate: coordinate
|
||||||
|
)
|
||||||
|
mapView.addAnnotation(annotation)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// create animator to manage wave animation and countdown
|
||||||
|
animator = MapSeismicWaveAnimator(
|
||||||
|
realtimeAlert: notification,
|
||||||
|
mapView: mapView,
|
||||||
|
waveTimeLabel: waveLabel
|
||||||
|
)
|
||||||
|
animator?.start()
|
||||||
|
// set color based on intensity
|
||||||
|
descriptionLabel.textColor = notification.relativeIntensityColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NotificationContentViewController: MKMapViewDelegate {
|
||||||
|
|
||||||
|
func mapView(_ mapView: MKMapView, viewFor annotation: any MKAnnotation) -> MKAnnotationView? {
|
||||||
|
switch annotation {
|
||||||
|
case let pastquake as EQNMapAnnotationPastquake:
|
||||||
|
let annotationView = mapView.dequeueReusableAnnotationView(
|
||||||
|
withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier
|
||||||
|
) as! EQNCustomAnnotationView
|
||||||
|
annotationView.image = pastquake.image
|
||||||
|
annotationView.title = pastquake.title
|
||||||
|
return annotationView
|
||||||
|
case let report as EQNMapAnnotationUserReport:
|
||||||
|
let annotationView = mapView.dequeueReusableAnnotationView(
|
||||||
|
withIdentifier: EQNCustomAnnotationView.SmallIdentifier
|
||||||
|
) as! EQNCustomAnnotationView
|
||||||
|
annotationView.image = report.image(with: EQNCustomAnnotationView.SmallViewImageHeight)
|
||||||
|
annotationView.title = report.timeDifference
|
||||||
|
return annotationView
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||||
|
animator?.getOverlayRenderer(for: overlay) ?? MKOverlayRenderer(overlay: overlay)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
//
|
|
||||||
// NotificationViewController.h
|
|
||||||
// EQNNotificationContent
|
|
||||||
//
|
|
||||||
// Refactored by Andrea Busi on 14/10/2020.
|
|
||||||
// Copyright © 2020 Earthquake Network. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
@interface NotificationViewController : UIViewController
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
//
|
|
||||||
// NotificationViewController.m
|
|
||||||
// EQNNotificationContent
|
|
||||||
//
|
|
||||||
// Refactored by Andrea Busi on 14/10/2020.
|
|
||||||
// Copyright © 2020 Earthquake Network. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "NotificationViewController.h"
|
|
||||||
#import "EQNUtility.h"
|
|
||||||
#import "EQNNotificationContent-Swift.h"
|
|
||||||
|
|
||||||
@import UserNotifications;
|
|
||||||
@import UserNotificationsUI;
|
|
||||||
@import MapKit;
|
|
||||||
|
|
||||||
@interface NotificationViewController () <UNNotificationContentExtension, MKMapViewDelegate>
|
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
|
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
|
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *waveLabel;
|
|
||||||
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
|
|
||||||
|
|
||||||
/// This will be calculated as seismic date + warning time
|
|
||||||
@property (strong, nonatomic) NSDate *userSeismicTimestamp;
|
|
||||||
@property (strong, nonatomic) NSTimer *countdownTimer;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation NotificationViewController
|
|
||||||
|
|
||||||
- (void)setMapView:(MKMapView *)mapView
|
|
||||||
{
|
|
||||||
_mapView = mapView;
|
|
||||||
_mapView.scrollEnabled = NO;
|
|
||||||
_mapView.zoomEnabled = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - View Lifecycle
|
|
||||||
|
|
||||||
- (void)viewDidLoad
|
|
||||||
{
|
|
||||||
[super viewDidLoad];
|
|
||||||
|
|
||||||
[self.mapView registerClass:[EQNCustomAnnotationView class] forAnnotationViewWithReuseIdentifier:EQNCustomAnnotationView.SingleLineIdentifier];
|
|
||||||
[self.mapView registerClass:[EQNCustomAnnotationView class] forAnnotationViewWithReuseIdentifier:EQNCustomAnnotationView.SmallIdentifier];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)didReceiveNotification:(UNNotification *)notification
|
|
||||||
{
|
|
||||||
UNNotificationContent *content = notification.request.content;
|
|
||||||
NSDictionary *userInfo = content.userInfo;
|
|
||||||
|
|
||||||
// set title and description
|
|
||||||
self.titleLabel.text = content.title;
|
|
||||||
self.descriptionLabel.text = content.body;
|
|
||||||
|
|
||||||
// add annotation onthe map
|
|
||||||
CLLocation *coordinate = [[CLLocation alloc] initWithLatitude:[userInfo[@"latitude"] doubleValue]
|
|
||||||
longitude:[userInfo[@"longitude"] doubleValue]];
|
|
||||||
MKCoordinateSpan span = MKCoordinateSpanMake(10.5, 10.5);
|
|
||||||
MKCoordinateRegion region = MKCoordinateRegionMake(coordinate.coordinate, span);
|
|
||||||
[self.mapView setCenterCoordinate:coordinate.coordinate animated:NO];
|
|
||||||
[self.mapView setRegion:region animated:YES];
|
|
||||||
|
|
||||||
if ([userInfo[@"type"] isEqualToString:@"eqn"]) {
|
|
||||||
EQNMapAnnotationPastquake *annotation = [[EQNMapAnnotationPastquake alloc] initWithTitle:@""
|
|
||||||
coordinate:coordinate.coordinate
|
|
||||||
intensity:[userInfo[@"intensity"] intValue]];
|
|
||||||
[self.mapView addAnnotation:annotation];
|
|
||||||
|
|
||||||
} else if ([userInfo[@"type"] isEqualToString:@"manual"]){
|
|
||||||
EQNMapAnnotationUserReport *annotation = [[EQNMapAnnotationUserReport alloc] initWithMagnitude:[userInfo[@"magnitude"] intValue]
|
|
||||||
coordinate:coordinate.coordinate];
|
|
||||||
[self.mapView addAnnotation:annotation];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
self.userSeismicTimestamp = [EQNUtility calculateUserSeismicTimestampFromUserInfo:userInfo];
|
|
||||||
if (self.userSeismicTimestamp) {
|
|
||||||
// start the countdown
|
|
||||||
self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
|
|
||||||
target:self
|
|
||||||
selector:@selector(countdownFired:)
|
|
||||||
userInfo:nil
|
|
||||||
repeats:YES];
|
|
||||||
[self.countdownTimer fire];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Private
|
|
||||||
|
|
||||||
- (void)countdownFired:(id)sender
|
|
||||||
{
|
|
||||||
NSDate *now = [NSDate date];
|
|
||||||
NSTimeInterval difference = MAX([self.userSeismicTimestamp timeIntervalSinceDate:now], 0);
|
|
||||||
NSInteger seconds = (int)lround(difference);
|
|
||||||
|
|
||||||
self.waveLabel.text = [NSString localizedStringWithFormat:NSLocalizedString(@"alert_wave", @""), seconds];
|
|
||||||
|
|
||||||
if (difference <= 0) {
|
|
||||||
// stop the countdown
|
|
||||||
[self.countdownTimer invalidate];
|
|
||||||
self.countdownTimer = nil;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - MKMapViewDelegate
|
|
||||||
|
|
||||||
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
|
|
||||||
{
|
|
||||||
if ([annotation isKindOfClass:[EQNMapAnnotationPastquake class]]) {
|
|
||||||
EQNMapAnnotationPastquake *pastquake = (EQNMapAnnotationPastquake *)annotation;
|
|
||||||
|
|
||||||
EQNCustomAnnotationView *annotationView = (EQNCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:EQNCustomAnnotationView.SingleLineIdentifier];
|
|
||||||
annotationView.image = pastquake.image;
|
|
||||||
annotationView.title = pastquake.title;
|
|
||||||
return annotationView;
|
|
||||||
|
|
||||||
} else if ([annotation isKindOfClass:[EQNMapAnnotationUserReport class]]) {
|
|
||||||
EQNMapAnnotationUserReport *report = (EQNMapAnnotationUserReport *)annotation;
|
|
||||||
|
|
||||||
EQNCustomAnnotationView *annotationView = (EQNCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:EQNCustomAnnotationView.SmallIdentifier];
|
|
||||||
annotationView.image = [report imageWithHeight:EQNCustomAnnotationView.SmallViewImageHeight];
|
|
||||||
annotationView.title = report.timeDifference;
|
|
||||||
return annotationView;
|
|
||||||
}
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -51,6 +51,43 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
bestAttemptContent.sound = UNNotificationSound(named: Self.EQNSoundNotification)
|
bestAttemptContent.sound = UNNotificationSound(named: Self.EQNSoundNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// evaluate intensity and get proper string to display
|
||||||
|
guard let latitude = userInfo.double(forKey: "latitude"),
|
||||||
|
let longitude = userInfo.double(forKey: "longitude"),
|
||||||
|
let peak = userInfo.double(forKey: "peak") else {
|
||||||
|
print("[NotificationService] Unable to get base info for intensity calculation")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let magnitude = userInfo.double(forKey: "mag") ?? 0
|
||||||
|
let location = CLLocation(latitude: latitude, longitude: longitude)
|
||||||
|
guard let distance = EQNUserData.shared.lastLocation?.distance(from: location) else {
|
||||||
|
print("[NotificationService] Unable to calculate distance or get last location")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let distanceKm = distance / 1_000
|
||||||
|
|
||||||
|
// If the shake is mild, user can disale sound and use default notification sound
|
||||||
|
// This logic is done here and not with the rest because distance and other informations are needed
|
||||||
|
let mildQuakeSoundDisabled = UserDefaults.appGroup?.bool(forKey: UserDefaults.AllertaSismicaSuonoDisabilitatoSismaDebole) ?? true
|
||||||
|
let isMildQuake = isMildQuake(magnitude: magnitude, distance: distanceKm)
|
||||||
|
if isMildQuake && mildQuakeSoundDisabled {
|
||||||
|
bestAttemptContent.sound = UNNotificationSound.default
|
||||||
|
}
|
||||||
|
|
||||||
|
let intensita = peak * exp(-distanceKm/peak/250)
|
||||||
|
let stringSuffix = if intensita < 0.004 {
|
||||||
|
"no_shaking"
|
||||||
|
} else if intensita < 0.30 {
|
||||||
|
"mild"
|
||||||
|
} else if intensita < 0.70 {
|
||||||
|
"moderate"
|
||||||
|
} else {
|
||||||
|
"strong"
|
||||||
|
}
|
||||||
|
bestAttemptContent.body = "alert_intensity_\(stringSuffix)".localized
|
||||||
|
|
||||||
let intensity = userInfo.integer(forKey: "intensity")
|
let intensity = userInfo.integer(forKey: "intensity")
|
||||||
switch intensity {
|
switch intensity {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -63,35 +100,6 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluate intensity and get proper string to display
|
|
||||||
guard let latitude = userInfo.double(forKey: "latitude"),
|
|
||||||
let longitude = userInfo.double(forKey: "longitude"),
|
|
||||||
let peak = userInfo.double(forKey: "peak") else {
|
|
||||||
print("[NotificationService] Unable to get base info for intensity calculation")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let location = CLLocation(latitude: latitude, longitude: longitude)
|
|
||||||
guard let distance = EQNUserData.shared.lastLocation?.distance(from: location) else {
|
|
||||||
print("[NotificationService] Unable to calculate distance or get last location")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let distanceKm = distance / 1_000
|
|
||||||
let intensita = peak * exp(-distanceKm/peak/250)
|
|
||||||
let stringSuffix: String
|
|
||||||
|
|
||||||
if intensita < 0.004 {
|
|
||||||
stringSuffix = "no_shaking"
|
|
||||||
} else if intensita < 0.30 {
|
|
||||||
stringSuffix = "mild"
|
|
||||||
} else if intensita < 0.70 {
|
|
||||||
stringSuffix = "moderate"
|
|
||||||
} else {
|
|
||||||
stringSuffix = "strong"
|
|
||||||
}
|
|
||||||
bestAttemptContent.body = "alert_intensity_\(stringSuffix)".localized
|
|
||||||
|
|
||||||
case "manual":
|
case "manual":
|
||||||
// there are 12 levels, so a customized icon doesn't make sense
|
// there are 12 levels, so a customized icon doesn't make sense
|
||||||
// use a generic warning icon instead
|
// use a generic warning icon instead
|
||||||
@@ -159,7 +167,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
notificationCenter.removeDeliveredNotifications(withIdentifiers: identifiers)
|
notificationCenter.removeDeliveredNotifications(withIdentifiers: identifiers)
|
||||||
|
|
||||||
// !! Note: this is a known issue/bug
|
// !! Note: this is a known issue/bug
|
||||||
// we need to add a delay before invoking the completion, otherwise the notification will not be remved
|
// we need to add a delay before invoking the completion, otherwise the notification will not be removed
|
||||||
// ref: https://stackoverflow.com/questions/53697279/why-are-notifications-not-removed-with-removedeliverednotifications
|
// ref: https://stackoverflow.com/questions/53697279/why-are-notifications-not-removed-with-removedeliverednotifications
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
completion()
|
completion()
|
||||||
@@ -167,6 +175,20 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func isMildQuake(
|
||||||
|
magnitude: Double,
|
||||||
|
distance: Double
|
||||||
|
) -> Bool {
|
||||||
|
var intensity_at_location: Double = 0
|
||||||
|
if distance > 0 {
|
||||||
|
let R: Double = 6371
|
||||||
|
let eq_depth: Double = 10.0
|
||||||
|
let hyp_distance = sqrt(pow(eq_depth, 2) + 4 * R * (R - eq_depth) * pow(sin(distance / (2 * R)), 2))
|
||||||
|
intensity_at_location = -2.15 * log10(hyp_distance) + 1.0 * magnitude + 2.31
|
||||||
|
}
|
||||||
|
return intensity_at_location < 3
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
private func manualIconName(for provider: String, color: String) -> String {
|
private func manualIconName(for provider: String, color: String) -> String {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
652A3C6B2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652A3C6A2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift */; };
|
652A3C6B2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652A3C6A2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift */; };
|
||||||
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */; };
|
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */; };
|
||||||
653604E9262348FA00B2B651 /* EQNBaseMapFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */; };
|
653604E9262348FA00B2B651 /* EQNBaseMapFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */; };
|
||||||
|
653C5C2C2E295C5A00E25528 /* SeismicNetworkFilterRecapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C5C2B2E295C5A00E25528 /* SeismicNetworkFilterRecapView.swift */; };
|
||||||
653C67E225F3CC2E00FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
653C67E225F3CC2E00FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
||||||
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
||||||
653C67FC25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67FB25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift */; };
|
653C67FC25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67FB25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift */; };
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
65583A05261B83BE00ECA9F9 /* UIKit+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */; };
|
65583A05261B83BE00ECA9F9 /* UIKit+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */; };
|
||||||
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */; };
|
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */; };
|
||||||
6563DAA42AAF515F0072D309 /* BackgroundTaskIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6563DAA32AAF515F0072D309 /* BackgroundTaskIdentifiable.swift */; };
|
6563DAA42AAF515F0072D309 /* BackgroundTaskIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6563DAA32AAF515F0072D309 /* BackgroundTaskIdentifiable.swift */; };
|
||||||
|
6568C2D42E2A930500402F16 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
||||||
656D138F2C2225560094F597 /* SubscriptionDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656D138E2C2225560094F597 /* SubscriptionDetailsViewController.swift */; };
|
656D138F2C2225560094F597 /* SubscriptionDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656D138E2C2225560094F597 /* SubscriptionDetailsViewController.swift */; };
|
||||||
656D13912C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656D13902C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift */; };
|
656D13912C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656D13902C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift */; };
|
||||||
656E02162C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656E02152C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift */; };
|
656E02162C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656E02152C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift */; };
|
||||||
@@ -49,6 +51,11 @@
|
|||||||
657415E02D70B6F800F54890 /* EQNMapAnnotationShakemap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657415DE2D70B6F700F54890 /* EQNMapAnnotationShakemap.swift */; };
|
657415E02D70B6F800F54890 /* EQNMapAnnotationShakemap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657415DE2D70B6F700F54890 /* EQNMapAnnotationShakemap.swift */; };
|
||||||
657747FD2D4D12A200213830 /* SeismicNetworkData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FC2D4D12A200213830 /* SeismicNetworkData.swift */; };
|
657747FD2D4D12A200213830 /* SeismicNetworkData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FC2D4D12A200213830 /* SeismicNetworkData.swift */; };
|
||||||
657747FF2D4D2BA200213830 /* SeismicNetworkScrollIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */; };
|
657747FF2D4D2BA200213830 /* SeismicNetworkScrollIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */; };
|
||||||
|
657CCF082E323AF700E91715 /* NotificationContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657CCF072E323AF700E91715 /* NotificationContentViewController.swift */; };
|
||||||
|
657CCF092E323BE500E91715 /* EQNRealtimePushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65EA58812A60360D0038EE9D /* EQNRealtimePushNotification.swift */; };
|
||||||
|
657CCF0A2E323DC600E91715 /* Foundation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650247142A618D7F001AC512 /* Foundation+Extensions.swift */; };
|
||||||
|
657CCF0C2E32711D00E91715 /* MapSeismicWaveAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657CCF0B2E32711D00E91715 /* MapSeismicWaveAnimator.swift */; };
|
||||||
|
657CCF0D2E32711D00E91715 /* MapSeismicWaveAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657CCF0B2E32711D00E91715 /* MapSeismicWaveAnimator.swift */; };
|
||||||
6586971125F44C26009C0182 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
6586971125F44C26009C0182 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
||||||
658BAB7B25FE67930015C454 /* EQNBaseMapRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */; };
|
658BAB7B25FE67930015C454 /* EQNBaseMapRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */; };
|
||||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */; };
|
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */; };
|
||||||
@@ -224,7 +231,6 @@
|
|||||||
8CF05B57218C93BA0055012B /* EQNUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF05B56218C93BA0055012B /* EQNUtility.m */; };
|
8CF05B57218C93BA0055012B /* EQNUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF05B56218C93BA0055012B /* EQNUtility.m */; };
|
||||||
8CF12CD321DE49B600613AC5 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CF12CD221DE49B600613AC5 /* UserNotifications.framework */; };
|
8CF12CD321DE49B600613AC5 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CF12CD221DE49B600613AC5 /* UserNotifications.framework */; };
|
||||||
8CF12CD521DE49B600613AC5 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CF12CD421DE49B600613AC5 /* UserNotificationsUI.framework */; };
|
8CF12CD521DE49B600613AC5 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CF12CD421DE49B600613AC5 /* UserNotificationsUI.framework */; };
|
||||||
8CF12CD921DE49B600613AC5 /* NotificationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF12CD821DE49B600613AC5 /* NotificationViewController.m */; };
|
|
||||||
8CF12CDC21DE49B600613AC5 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8CF12CDA21DE49B600613AC5 /* MainInterface.storyboard */; };
|
8CF12CDC21DE49B600613AC5 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8CF12CDA21DE49B600613AC5 /* MainInterface.storyboard */; };
|
||||||
8CF12CE021DE49B600613AC5 /* EQNNotificationContent.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 8CF12CD121DE49B600613AC5 /* EQNNotificationContent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
8CF12CE021DE49B600613AC5 /* EQNNotificationContent.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 8CF12CD121DE49B600613AC5 /* EQNNotificationContent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
8CF4F4D8216D3A110057110B /* EQNAreaCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF4F4D7216D3A110057110B /* EQNAreaCheck.m */; };
|
8CF4F4D8216D3A110057110B /* EQNAreaCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF4F4D7216D3A110057110B /* EQNAreaCheck.m */; };
|
||||||
@@ -329,6 +335,7 @@
|
|||||||
65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniMapViewController.swift; sourceTree = "<group>"; };
|
65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniMapViewController.swift; sourceTree = "<group>"; };
|
||||||
653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapFilter.swift; sourceTree = "<group>"; };
|
653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapFilter.swift; sourceTree = "<group>"; };
|
||||||
653B791F2934B6DA00E8FFFB /* EQNNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EQNNotificationService.entitlements; sourceTree = "<group>"; };
|
653B791F2934B6DA00E8FFFB /* EQNNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EQNNotificationService.entitlements; sourceTree = "<group>"; };
|
||||||
|
653C5C2B2E295C5A00E25528 /* SeismicNetworkFilterRecapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkFilterRecapView.swift; sourceTree = "<group>"; };
|
||||||
653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNCustomAnnotationView.swift; sourceTree = "<group>"; };
|
653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNCustomAnnotationView.swift; sourceTree = "<group>"; };
|
||||||
653C67FB25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationUserReport.swift; sourceTree = "<group>"; };
|
653C67FB25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationUserReport.swift; sourceTree = "<group>"; };
|
||||||
653C680325F3DF8A00FE52AC /* EQNBaseMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapViewController.swift; sourceTree = "<group>"; };
|
653C680325F3DF8A00FE52AC /* EQNBaseMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapViewController.swift; sourceTree = "<group>"; };
|
||||||
@@ -356,6 +363,8 @@
|
|||||||
657415DE2D70B6F700F54890 /* EQNMapAnnotationShakemap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationShakemap.swift; sourceTree = "<group>"; };
|
657415DE2D70B6F700F54890 /* EQNMapAnnotationShakemap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationShakemap.swift; sourceTree = "<group>"; };
|
||||||
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkData.swift; sourceTree = "<group>"; };
|
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkData.swift; sourceTree = "<group>"; };
|
||||||
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkScrollIndicatorView.swift; sourceTree = "<group>"; };
|
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkScrollIndicatorView.swift; sourceTree = "<group>"; };
|
||||||
|
657CCF072E323AF700E91715 /* NotificationContentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentViewController.swift; sourceTree = "<group>"; };
|
||||||
|
657CCF0B2E32711D00E91715 /* MapSeismicWaveAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSeismicWaveAnimator.swift; sourceTree = "<group>"; };
|
||||||
6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBlurredCloseButton.swift; sourceTree = "<group>"; };
|
6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBlurredCloseButton.swift; sourceTree = "<group>"; };
|
||||||
658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapRepresentable.swift; sourceTree = "<group>"; };
|
658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapRepresentable.swift; sourceTree = "<group>"; };
|
||||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertViewController.swift; sourceTree = "<group>"; };
|
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertViewController.swift; sourceTree = "<group>"; };
|
||||||
@@ -554,8 +563,6 @@
|
|||||||
8CF12CD121DE49B600613AC5 /* EQNNotificationContent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = EQNNotificationContent.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
8CF12CD121DE49B600613AC5 /* EQNNotificationContent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = EQNNotificationContent.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
8CF12CD221DE49B600613AC5 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
|
8CF12CD221DE49B600613AC5 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
|
||||||
8CF12CD421DE49B600613AC5 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
|
8CF12CD421DE49B600613AC5 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
|
||||||
8CF12CD721DE49B600613AC5 /* NotificationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationViewController.h; sourceTree = "<group>"; };
|
|
||||||
8CF12CD821DE49B600613AC5 /* NotificationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationViewController.m; sourceTree = "<group>"; };
|
|
||||||
8CF12CDB21DE49B600613AC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
8CF12CDB21DE49B600613AC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
||||||
8CF12CDD21DE49B600613AC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
8CF12CDD21DE49B600613AC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
8CF4F4D6216D3A110057110B /* EQNAreaCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EQNAreaCheck.h; sourceTree = "<group>"; };
|
8CF4F4D6216D3A110057110B /* EQNAreaCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EQNAreaCheck.h; sourceTree = "<group>"; };
|
||||||
@@ -678,6 +685,7 @@
|
|||||||
children = (
|
children = (
|
||||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */,
|
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */,
|
||||||
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */,
|
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */,
|
||||||
|
657CCF0B2E32711D00E91715 /* MapSeismicWaveAnimator.swift */,
|
||||||
);
|
);
|
||||||
path = "Realtime Alert";
|
path = "Realtime Alert";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -913,8 +921,7 @@
|
|||||||
children = (
|
children = (
|
||||||
6557CBBC26078A1700962757 /* EQNNotificationContent.entitlements */,
|
6557CBBC26078A1700962757 /* EQNNotificationContent.entitlements */,
|
||||||
8C483CB621FDACD100259FD2 /* EQNNotificationContent-Bridging-Header.h */,
|
8C483CB621FDACD100259FD2 /* EQNNotificationContent-Bridging-Header.h */,
|
||||||
8CF12CD721DE49B600613AC5 /* NotificationViewController.h */,
|
657CCF072E323AF700E91715 /* NotificationContentViewController.swift */,
|
||||||
8CF12CD821DE49B600613AC5 /* NotificationViewController.m */,
|
|
||||||
8CF12CDA21DE49B600613AC5 /* MainInterface.storyboard */,
|
8CF12CDA21DE49B600613AC5 /* MainInterface.storyboard */,
|
||||||
8CF12CDD21DE49B600613AC5 /* Info.plist */,
|
8CF12CDD21DE49B600613AC5 /* Info.plist */,
|
||||||
);
|
);
|
||||||
@@ -941,6 +948,7 @@
|
|||||||
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */,
|
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */,
|
||||||
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */,
|
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */,
|
||||||
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */,
|
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */,
|
||||||
|
653C5C2B2E295C5A00E25528 /* SeismicNetworkFilterRecapView.swift */,
|
||||||
DC2814372519C56100C1AFF7 /* SeismicNetworksViewController.swift */,
|
DC2814372519C56100C1AFF7 /* SeismicNetworksViewController.swift */,
|
||||||
DCC76BD7251F56050005C4DC /* SeismicCardSettingsViewController.swift */,
|
DCC76BD7251F56050005C4DC /* SeismicCardSettingsViewController.swift */,
|
||||||
65DBFB4A25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift */,
|
65DBFB4A25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift */,
|
||||||
@@ -1656,6 +1664,7 @@
|
|||||||
65F9B4A02A8CC58200F13260 /* UpdateUserLocationTask.swift in Sources */,
|
65F9B4A02A8CC58200F13260 /* UpdateUserLocationTask.swift in Sources */,
|
||||||
8C4E34422152B5E8008B0D2A /* EQNRilevamento.m in Sources */,
|
8C4E34422152B5E8008B0D2A /* EQNRilevamento.m in Sources */,
|
||||||
8C7A3B66225A5EA40045B266 /* NSDictionary+EQNExtensions.m in Sources */,
|
8C7A3B66225A5EA40045B266 /* NSDictionary+EQNExtensions.m in Sources */,
|
||||||
|
653C5C2C2E295C5A00E25528 /* SeismicNetworkFilterRecapView.swift in Sources */,
|
||||||
65AB4A992C11DFC200950DF7 /* EQNSettingSeismicNetworkNotification.swift in Sources */,
|
65AB4A992C11DFC200950DF7 /* EQNSettingSeismicNetworkNotification.swift in Sources */,
|
||||||
8CF66053214C12DC009F4314 /* EQNMath.m in Sources */,
|
8CF66053214C12DC009F4314 /* EQNMath.m in Sources */,
|
||||||
DCF4A54524F8DB8300B17326 /* SettingDateTableViewCell.swift in Sources */,
|
DCF4A54524F8DB8300B17326 /* SettingDateTableViewCell.swift in Sources */,
|
||||||
@@ -1673,6 +1682,7 @@
|
|||||||
653C67E225F3CC2E00FE52AC /* EQNCustomAnnotationView.swift in Sources */,
|
653C67E225F3CC2E00FE52AC /* EQNCustomAnnotationView.swift in Sources */,
|
||||||
8CF4F4D8216D3A110057110B /* EQNAreaCheck.m in Sources */,
|
8CF4F4D8216D3A110057110B /* EQNAreaCheck.m in Sources */,
|
||||||
8C4E34452152B707008B0D2A /* EQNAccelerometroManager.m in Sources */,
|
8C4E34452152B707008B0D2A /* EQNAccelerometroManager.m in Sources */,
|
||||||
|
657CCF0C2E32711D00E91715 /* MapSeismicWaveAnimator.swift in Sources */,
|
||||||
65D409942619BA34008CF356 /* SegnalazioniSendReportCell.swift in Sources */,
|
65D409942619BA34008CF356 /* SegnalazioniSendReportCell.swift in Sources */,
|
||||||
65F9B49C2A8CA22800F13260 /* BackgroundTaskManager.swift in Sources */,
|
65F9B49C2A8CA22800F13260 /* BackgroundTaskManager.swift in Sources */,
|
||||||
656D13912C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift in Sources */,
|
656D13912C22371F0094F597 /* SubscriptionDetailsTableViewCell.swift in Sources */,
|
||||||
@@ -1704,17 +1714,21 @@
|
|||||||
8C465D9F21F7BE0600F04673 /* Assets.xcassets in Sources */,
|
8C465D9F21F7BE0600F04673 /* Assets.xcassets in Sources */,
|
||||||
65D9938C2922647800F2B0EB /* AppTheme.swift in Sources */,
|
65D9938C2922647800F2B0EB /* AppTheme.swift in Sources */,
|
||||||
DC0AE1B92538204100111307 /* EQNSegnalazione.m in Sources */,
|
DC0AE1B92538204100111307 /* EQNSegnalazione.m in Sources */,
|
||||||
|
657CCF092E323BE500E91715 /* EQNRealtimePushNotification.swift in Sources */,
|
||||||
|
657CCF082E323AF700E91715 /* NotificationContentViewController.swift in Sources */,
|
||||||
654D18DE25F943E200BB6DB0 /* EQNMapAnnotationUserReport.swift in Sources */,
|
654D18DE25F943E200BB6DB0 /* EQNMapAnnotationUserReport.swift in Sources */,
|
||||||
654D18D625F9420500BB6DB0 /* EQNMapAnnotationPastquake.swift in Sources */,
|
654D18D625F9420500BB6DB0 /* EQNMapAnnotationPastquake.swift in Sources */,
|
||||||
65D507DB2A852274005BDC57 /* EQNUserData.swift in Sources */,
|
65D507DB2A852274005BDC57 /* EQNUserData.swift in Sources */,
|
||||||
|
657CCF0A2E323DC600E91715 /* Foundation+Extensions.swift in Sources */,
|
||||||
DC0AE1B52538202300111307 /* EQNUtility.m in Sources */,
|
DC0AE1B52538202300111307 /* EQNUtility.m in Sources */,
|
||||||
65D507DC2A85227F005BDC57 /* Constants.swift in Sources */,
|
65D507DC2A85227F005BDC57 /* Constants.swift in Sources */,
|
||||||
|
657CCF0D2E32711D00E91715 /* MapSeismicWaveAnimator.swift in Sources */,
|
||||||
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */,
|
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */,
|
||||||
654D18DA25F9424700BB6DB0 /* EQNUtility+Extensions.swift in Sources */,
|
654D18DA25F9424700BB6DB0 /* EQNUtility+Extensions.swift in Sources */,
|
||||||
DC0AE1BA2538204100111307 /* EQNPastquakes.m in Sources */,
|
DC0AE1BA2538204100111307 /* EQNPastquakes.m in Sources */,
|
||||||
|
6568C2D42E2A930500402F16 /* EQNBlurredCloseButton.swift in Sources */,
|
||||||
65D9938A29219DEC00F2B0EB /* UIKit+Extensions.swift in Sources */,
|
65D9938A29219DEC00F2B0EB /* UIKit+Extensions.swift in Sources */,
|
||||||
6514FF6C2D720CBE000A7BD0 /* MapPinStyle.swift in Sources */,
|
6514FF6C2D720CBE000A7BD0 /* MapPinStyle.swift in Sources */,
|
||||||
8CF12CD921DE49B600613AC5 /* NotificationViewController.m in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -1818,7 +1832,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
@@ -1829,13 +1843,12 @@
|
|||||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = EQNNotificationService;
|
INFOPLIST_KEY_CFBundleDisplayName = EQNNotificationService;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Earthquake Network. All rights reserved.";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Earthquake Network. All rights reserved.";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||||
@@ -1847,7 +1860,6 @@
|
|||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -1860,20 +1872,19 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = EQNNotificationService;
|
INFOPLIST_KEY_CFBundleDisplayName = EQNNotificationService;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Earthquake Network. All rights reserved.";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Earthquake Network. All rights reserved.";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -1883,7 +1894,6 @@
|
|||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -1923,6 +1933,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 159;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@@ -1942,7 +1953,8 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MARKETING_VERSION = 5.11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -1985,6 +1997,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 159;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
@@ -1998,7 +2011,8 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MARKETING_VERSION = 5.11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
@@ -2014,19 +2028,18 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
ENABLE_MODULE_VERIFIER = YES;
|
ENABLE_MODULE_VERIFIER = YES;
|
||||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -2090,7 +2103,6 @@
|
|||||||
SWIFT_OBJC_BRIDGING_HEADER = "Earthquake Network/Earthquake Network-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Earthquake Network/Earthquake Network-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -2102,18 +2114,17 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
ENABLE_MODULE_VERIFIER = YES;
|
ENABLE_MODULE_VERIFIER = YES;
|
||||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -2176,7 +2187,6 @@
|
|||||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork - AppStore";
|
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork - AppStore";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Earthquake Network/Earthquake Network-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Earthquake Network/Earthquake Network-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -2187,7 +2197,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
@@ -2196,13 +2206,12 @@
|
|||||||
"NOTIFICATION_CONTENT=1",
|
"NOTIFICATION_CONTENT=1",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
|
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
|
||||||
@@ -2210,7 +2219,6 @@
|
|||||||
SWIFT_OBJC_BRIDGING_HEADER = "EQNNotificationContent/EQNNotificationContent-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "EQNNotificationContent/EQNNotificationContent-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -2221,27 +2229,25 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 150;
|
CURRENT_PROJECT_VERSION = "$(inherited)";
|
||||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"ADS_ENABLED=0",
|
"ADS_ENABLED=0",
|
||||||
"NOTIFICATION_CONTENT=1",
|
"NOTIFICATION_CONTENT=1",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.9.0;
|
MARKETING_VERSION = "$(inherited)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
|
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "EQNNotificationContent/EQNNotificationContent-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "EQNNotificationContent/EQNNotificationContent-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -2292,7 +2298,7 @@
|
|||||||
repositoryURL = "https://github.com/andreabusi-it/Shogun.git";
|
repositoryURL = "https://github.com/andreabusi-it/Shogun.git";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = 1.0.0;
|
minimumVersion = 2.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
65B16E1C2BDFA88D0020527E /* XCRemoteSwiftPackageReference "Solar" */ = {
|
65B16E1C2BDFA88D0020527E /* XCRemoteSwiftPackageReference "Solar" */ = {
|
||||||
|
|||||||
+24
-15
@@ -6,8 +6,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "194a6706acbd25e4ef639bcaddea16e8758a3e27",
|
"revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
|
||||||
"version" : "1.2024011602.0"
|
"version" : "1.2024072200.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -42,8 +42,17 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/firebase/firebase-ios-sdk.git",
|
"location" : "https://github.com/firebase/firebase-ios-sdk.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "075679d6b25b28f4cb167f1d7769b58fb556fb30",
|
"revision" : "fdc352fabaf5916e7faa1f96ad02b1957e93e5a5",
|
||||||
"version" : "11.8.0"
|
"version" : "11.15.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "google-ads-on-device-conversion-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "428d8bb138e00f9a3f4f61cc6cd8863607524f65",
|
||||||
|
"version" : "2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -51,8 +60,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "be0881ff728eca210ccb628092af400c086abda3",
|
"revision" : "45ce435e9406d3c674dd249a042b932bee006f60",
|
||||||
"version" : "11.7.0"
|
"version" : "11.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -69,8 +78,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/google/GoogleUtilities.git",
|
"location" : "https://github.com/google/GoogleUtilities.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb",
|
"revision" : "60da361632d0de02786f709bdc0c4df340f7613e",
|
||||||
"version" : "8.0.2"
|
"version" : "8.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -78,8 +87,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/google/grpc-binary.git",
|
"location" : "https://github.com/google/grpc-binary.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "f56d8fc3162de9a498377c7b6cea43431f4f5083",
|
"revision" : "cc0001a0cf963aa40501d9c2b181e7fc9fd8ec71",
|
||||||
"version" : "1.65.1"
|
"version" : "1.69.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -96,8 +105,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
|
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "2d12673670417654f08f5f90fdd62926dc3a2648",
|
"revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
|
||||||
"version" : "100.0.0"
|
"version" : "101.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -130,10 +139,10 @@
|
|||||||
{
|
{
|
||||||
"identity" : "shogun",
|
"identity" : "shogun",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/andreabusi-it/Shogun",
|
"location" : "https://github.com/andreabusi-it/Shogun.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "ad890190d6be90f7712c2e56a38ef0937d9f8c1a",
|
"revision" : "809b56a43fadac72db9963a21c74688af7ef51b7",
|
||||||
"version" : "1.8.0"
|
"version" : "2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -207,20 +207,16 @@
|
|||||||
|
|
||||||
- (void)configureAppTracking
|
- (void)configureAppTracking
|
||||||
{
|
{
|
||||||
if (@available(iOS 14, *)) {
|
// add a delay otherwise the alert will not be displayed
|
||||||
// add a delay otherwise the alert will not be displayed
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
|
||||||
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
|
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
|
||||||
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
|
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
|
||||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
|
} else {
|
||||||
} else {
|
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = NO;
|
||||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = NO;
|
}
|
||||||
}
|
}];
|
||||||
}];
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configureFirebase
|
- (void)configureFirebase
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ extension UserDefaults {
|
|||||||
|
|
||||||
// Impostazioni della sezione `Allerta in tempo reale`
|
// Impostazioni della sezione `Allerta in tempo reale`
|
||||||
static let AllertaSismicaAbilitato = "NOTIFICHE_ALLERA_SISMICA_ABILITATO"
|
static let AllertaSismicaAbilitato = "NOTIFICHE_ALLERA_SISMICA_ABILITATO"
|
||||||
|
static let AllertaSismicaSuonoDisabilitatoSismaDebole = "NOTIFICHE_ALLERA_SISMICA_SUONO_DISABILITATO_SISMA_DEBOLE"
|
||||||
static let AllertaSismicaCriticalAlerts = "NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
|
static let AllertaSismicaCriticalAlerts = "NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
|
||||||
static let AllertaSismicaSismiDaNotificare = "NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE"
|
static let AllertaSismicaSismiDaNotificare = "NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE"
|
||||||
static let AllertaSismicaRaggioSismiLievi = "NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI"
|
static let AllertaSismicaRaggioSismiLievi = "NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI"
|
||||||
@@ -69,6 +70,7 @@ extension UserDefaults {
|
|||||||
static let AppMigrationV5_8 = "EQNUserDefaultMigrationV5_8"
|
static let AppMigrationV5_8 = "EQNUserDefaultMigrationV5_8"
|
||||||
static let AppMigrationV5_8_2 = "EQNUserDefaultMigrationV5_8_2"
|
static let AppMigrationV5_8_2 = "EQNUserDefaultMigrationV5_8_2"
|
||||||
static let AppMigrationV5_9 = "EQNUserDefaultMigrationV5_9"
|
static let AppMigrationV5_9 = "EQNUserDefaultMigrationV5_9"
|
||||||
|
static let AppMigrationV5_10 = "EQNUserDefaultMigrationV5_10"
|
||||||
|
|
||||||
static let SettingsSeismicNetworkNotificationMigrationV5_8 = "EQNUserDefaultSettingsSeismicNetworkNotificationMigrationV5_8"
|
static let SettingsSeismicNetworkNotificationMigrationV5_8 = "EQNUserDefaultSettingsSeismicNetworkNotificationMigrationV5_8"
|
||||||
static let SettingsUserReportNotificationMigrationV5_8 = "EQNUserDefaultSettingsUserReportNotificationMigrationV5_8"
|
static let SettingsUserReportNotificationMigrationV5_8 = "EQNUserDefaultSettingsUserReportNotificationMigrationV5_8"
|
||||||
|
|||||||
@@ -92,10 +92,8 @@ class SubscriptionsViewController: UITableViewController {
|
|||||||
tableView.separatorStyle = .none
|
tableView.separatorStyle = .none
|
||||||
tableView.backgroundColor = .systemGroupedBackground
|
tableView.backgroundColor = .systemGroupedBackground
|
||||||
tableView.contentInset = EQNBaseContainerTableViewCell.EdgeInsets
|
tableView.contentInset = EQNBaseContainerTableViewCell.EdgeInsets
|
||||||
if #available(iOS 15.0, *) {
|
// remove extra padding on top of each section header
|
||||||
// remove extra padding on top of each section header
|
tableView.sectionHeaderTopPadding = 0.0
|
||||||
tableView.sectionHeaderTopPadding = 0.0
|
|
||||||
}
|
|
||||||
tableView.registerCell(for: SubscriptionsActiveTableViewCell.self)
|
tableView.registerCell(for: SubscriptionsActiveTableViewCell.self)
|
||||||
tableView.registerCell(for: SubscriptionsDescriptionTableViewCell.self)
|
tableView.registerCell(for: SubscriptionsDescriptionTableViewCell.self)
|
||||||
tableView.registerCell(for: SubscriptionProductTableViewCell.self)
|
tableView.registerCell(for: SubscriptionProductTableViewCell.self)
|
||||||
@@ -119,14 +117,21 @@ class SubscriptionsViewController: UITableViewController {
|
|||||||
let isSubscription = product.isSubscription
|
let isSubscription = product.isSubscription
|
||||||
return isPurchased && isSubscription
|
return isPurchased && isSubscription
|
||||||
}.sorted { lProduct, rProduct in
|
}.sorted { lProduct, rProduct in
|
||||||
// if user has more than one subscriptions,
|
// If user has more than one subscriptions,
|
||||||
// show first the Top10k
|
// show first the Top10k.
|
||||||
let lIs10k = lProduct.isTop100k
|
let lIs10k = lProduct.isTop10k
|
||||||
let rIs10k = rProduct.isTop100k
|
let rIs10k = rProduct.isTop10k
|
||||||
if lIs10k {
|
|
||||||
return lIs10k
|
// If left item is Top10k, order first
|
||||||
|
if lIs10k && !rIs10k {
|
||||||
|
return true
|
||||||
|
} else if !lProduct.isTop10k && rProduct.isTop10k {
|
||||||
|
// right product is Top10k, left no
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// both products Top10k or Top100k, keep existing order
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return rIs10k
|
|
||||||
}
|
}
|
||||||
self.productSubscribed = purchased.first
|
self.productSubscribed = purchased.first
|
||||||
self.products = products.sorted(by: { $0.productIdentifier > $1.productIdentifier })
|
self.products = products.sorted(by: { $0.productIdentifier > $1.productIdentifier })
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
//
|
||||||
|
// MapSeismicWaveAnimator.swift
|
||||||
|
// Earthquake Network
|
||||||
|
//
|
||||||
|
// Created by Andrea Busi on 24/07/25.
|
||||||
|
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MapKit
|
||||||
|
|
||||||
|
|
||||||
|
class MapSeismicWaveAnimator {
|
||||||
|
|
||||||
|
private weak var mapView: MKMapView?
|
||||||
|
private weak var waveTimeLabel: UILabel?
|
||||||
|
|
||||||
|
private let OverlayCircleId = "wave_animation"
|
||||||
|
|
||||||
|
/// Alert to display
|
||||||
|
private let realtimeAlert: EQNRealtimePushNotification
|
||||||
|
/// Timer to constantly update countdown label
|
||||||
|
private var countdownTimer: Timer?
|
||||||
|
/// Timer to simulate animation for the wave
|
||||||
|
private var waveAnimationTimer: Timer?
|
||||||
|
/// Refresh time for wave animation
|
||||||
|
private let waveAnimationRefreshRate = 0.1
|
||||||
|
/// Current radius of the wave animation on the map
|
||||||
|
private var waveAnimationCurrentRadius: CLLocationDistance = 0
|
||||||
|
private var waveAnimationVelocity: Double = 1_000
|
||||||
|
|
||||||
|
// MARK: - Init
|
||||||
|
|
||||||
|
init(
|
||||||
|
realtimeAlert: EQNRealtimePushNotification,
|
||||||
|
mapView: MKMapView,
|
||||||
|
waveTimeLabel: UILabel
|
||||||
|
) {
|
||||||
|
self.realtimeAlert = realtimeAlert
|
||||||
|
self.mapView = mapView
|
||||||
|
self.waveTimeLabel = waveTimeLabel
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setup() {
|
||||||
|
self.waveAnimationCurrentRadius = currentWavePosition()
|
||||||
|
self.waveAnimationVelocity = evaluateWaveAnimationVelocity()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
startCountdown()
|
||||||
|
startWaveAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stop() {
|
||||||
|
stopCountdown()
|
||||||
|
stopWaveAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Wave
|
||||||
|
|
||||||
|
private func startCountdown() {
|
||||||
|
// show countdown only if time is less than 300 seconds
|
||||||
|
if realtimeAlert.currentCountdown() < 300 {
|
||||||
|
// start a timer for the countdown label
|
||||||
|
waveTimeLabel?.isHidden = false
|
||||||
|
countdownTimer = Timer.scheduledTimer(
|
||||||
|
timeInterval: 1.0,
|
||||||
|
target: self,
|
||||||
|
selector: #selector(countdownTimerFired(_:)),
|
||||||
|
userInfo: nil,
|
||||||
|
repeats: true
|
||||||
|
)
|
||||||
|
countdownTimer?.fire()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startWaveAnimation() {
|
||||||
|
waveAnimationTimer = Timer.scheduledTimer(
|
||||||
|
timeInterval: waveAnimationRefreshRate,
|
||||||
|
target: self,
|
||||||
|
selector: #selector(mapWaveAnimationFired(_:)),
|
||||||
|
userInfo: nil,
|
||||||
|
repeats: true
|
||||||
|
)
|
||||||
|
waveAnimationTimer?.fire()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopCountdown() {
|
||||||
|
countdownTimer?.invalidate()
|
||||||
|
countdownTimer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopWaveAnimation() {
|
||||||
|
waveAnimationTimer?.invalidate()
|
||||||
|
waveAnimationTimer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Timer
|
||||||
|
|
||||||
|
@objc private func countdownTimerFired(_ sender: Timer) {
|
||||||
|
let countdown = realtimeAlert.currentCountdown()
|
||||||
|
waveTimeLabel?.text = String.localizedStringWithFormat(NSLocalizedString("alert_wave", comment: ""), countdown)
|
||||||
|
waveTimeLabel?.textColor = waveTimeTextColor(for: countdown)
|
||||||
|
|
||||||
|
if countdown <= 0 {
|
||||||
|
// stop the countdown
|
||||||
|
stopCountdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func mapWaveAnimationFired(_ sender: Timer) {
|
||||||
|
waveAnimationCurrentRadius += waveAnimationVelocity
|
||||||
|
addMapCircle(center: realtimeAlert.coordinate.coordinate, radius: waveAnimationCurrentRadius)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
/// Evaluate current position for the wave
|
||||||
|
/// Used to define initial position for the wave circle
|
||||||
|
/// - Returns: Distance of the wave from the original earthquake point
|
||||||
|
private func currentWavePosition() -> Double {
|
||||||
|
// distanza tra utente e terremoto
|
||||||
|
let distance = realtimeAlert.distanceFromUser()
|
||||||
|
|
||||||
|
// calcoliamo la distanza rimanente da mostrare, perchè la schermata potrebbe anche essere aperta in ritardo
|
||||||
|
let remainingDistance = realtimeAlert.waveSpeed * Double(realtimeAlert.currentCountdown())
|
||||||
|
return distance - remainingDistance
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluate wave velocity based on push notification data
|
||||||
|
/// - Returns: Wave velocity, used for animation
|
||||||
|
private func evaluateWaveAnimationVelocity() -> Double {
|
||||||
|
let velocity = realtimeAlert.waveSpeed
|
||||||
|
return velocity * waveAnimationRefreshRate
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the text color based on impact countdown
|
||||||
|
private func waveTimeTextColor(for countdown: Int) -> UIColor {
|
||||||
|
switch countdown {
|
||||||
|
case _ where countdown > 15:
|
||||||
|
return UIColor(red: 255.0/255.0, green: 140.0/255.0, blue: 0.0, alpha: 1.0)
|
||||||
|
case _ where countdown > 5:
|
||||||
|
return UIColor(red: 255.0/255.0, green: 100.0/255.0, blue: 0.0, alpha: 1.0)
|
||||||
|
default:
|
||||||
|
return UIColor(red: 255.0/255.0, green: 0.0/255.0, blue: 0.0, alpha: 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Map management
|
||||||
|
|
||||||
|
func addMapCircle(
|
||||||
|
center: CLLocationCoordinate2D,
|
||||||
|
radius: CLLocationDistance
|
||||||
|
) {
|
||||||
|
guard let mapView else { return }
|
||||||
|
|
||||||
|
// remove any other existing overlays
|
||||||
|
let overlays = mapView.overlays.filter { $0.title == OverlayCircleId }
|
||||||
|
mapView.removeOverlays(overlays)
|
||||||
|
|
||||||
|
// add new overlay
|
||||||
|
let circle = MKCircle(center: center, radius: radius)
|
||||||
|
circle.title = OverlayCircleId
|
||||||
|
mapView.addOverlay(circle)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOverlayRenderer(for overlay: MKOverlay) -> MKOverlayRenderer? {
|
||||||
|
switch overlay {
|
||||||
|
case let circle as MKCircle where overlay.title == OverlayCircleId:
|
||||||
|
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 nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -102,7 +102,6 @@ class RealtimeAlertView: UIView {
|
|||||||
lazy var mapView: MKMapView = {
|
lazy var mapView: MKMapView = {
|
||||||
let map = MKMapView()
|
let map = MKMapView()
|
||||||
map.translatesAutoresizingMaskIntoConstraints = false
|
map.translatesAutoresizingMaskIntoConstraints = false
|
||||||
map.delegate = self
|
|
||||||
map.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
map.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
||||||
map.showsUserLocation = true
|
map.showsUserLocation = true
|
||||||
return map
|
return map
|
||||||
@@ -160,28 +159,13 @@ class RealtimeAlertView: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func addMapCircle(
|
func addMapLine(
|
||||||
center: CLLocationCoordinate2D,
|
coordinates: [CLLocationCoordinate2D]
|
||||||
radius: CLLocationDistance,
|
|
||||||
overlayId: String
|
|
||||||
) {
|
) {
|
||||||
// remove any other existing overlays
|
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
|
||||||
let overlays = mapView.overlays.filter { $0.title == overlayId }
|
mapView.addOverlay(polyline)
|
||||||
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(
|
func addMapAnnotation(
|
||||||
title: String = "",
|
title: String = "",
|
||||||
@@ -192,35 +176,3 @@ class RealtimeAlertView: UIView {
|
|||||||
mapView.addAnnotation(annotation)
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+27
-85
@@ -10,7 +10,7 @@ import UIKit
|
|||||||
import MapKit
|
import MapKit
|
||||||
|
|
||||||
|
|
||||||
class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
class RealtimeAlertViewController: UIViewController {
|
||||||
|
|
||||||
@objc var onClose: () -> Void = {}
|
@objc var onClose: () -> Void = {}
|
||||||
|
|
||||||
@@ -20,17 +20,17 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
|||||||
private var notificationView: RealtimeAlertView {
|
private var notificationView: RealtimeAlertView {
|
||||||
containerView.alertView
|
containerView.alertView
|
||||||
}
|
}
|
||||||
|
/// Manage the wave animation on the map and the countdown label
|
||||||
|
private lazy var animator: MapSeismicWaveAnimator = {
|
||||||
|
let animator = MapSeismicWaveAnimator(
|
||||||
|
realtimeAlert: realtimeAlert,
|
||||||
|
mapView: notificationView.mapView,
|
||||||
|
waveTimeLabel: notificationView.waveTimeLabel
|
||||||
|
)
|
||||||
|
return animator
|
||||||
|
}()
|
||||||
/// Alert to display
|
/// Alert to display
|
||||||
private let realtimeAlert: EQNRealtimePushNotification
|
private let realtimeAlert: EQNRealtimePushNotification
|
||||||
/// Timer to constantly update countdown label
|
|
||||||
private var countdownTimer: Timer?
|
|
||||||
/// Refresh time for wave animation
|
|
||||||
private let waveAnimationRefreshRate = 0.1
|
|
||||||
/// Current radius of the wave animation on the map
|
|
||||||
private var waveAnimationCurrentRadius: CLLocationDistance = 0
|
|
||||||
private var waveAnimationVelocity: Double = 1_000
|
|
||||||
/// Timer to simulate animation for the wave
|
|
||||||
private var waveAnimationTimer: Timer?
|
|
||||||
|
|
||||||
// MARK: - Init
|
// MARK: - Init
|
||||||
|
|
||||||
@@ -38,9 +38,6 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
|||||||
init(notification: EQNRealtimePushNotification) {
|
init(notification: EQNRealtimePushNotification) {
|
||||||
self.realtimeAlert = notification
|
self.realtimeAlert = notification
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
self.waveAnimationCurrentRadius = currentWavePosition()
|
|
||||||
self.waveAnimationVelocity = evaluateWaveAnimationVelocity()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@@ -64,8 +61,7 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
|||||||
configureUI()
|
configureUI()
|
||||||
updateUI()
|
updateUI()
|
||||||
|
|
||||||
startCountdown()
|
animator.start()
|
||||||
startWaveAnimation()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
@@ -77,6 +73,8 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func configureUI() {
|
private func configureUI() {
|
||||||
|
notificationView.mapView.delegate = self
|
||||||
|
|
||||||
notificationView.closeButton.addTarget(self, action: #selector(onTapClose(_:)), for: .touchUpInside)
|
notificationView.closeButton.addTarget(self, action: #selector(onTapClose(_:)), for: .touchUpInside)
|
||||||
|
|
||||||
// configure color for animation
|
// configure color for animation
|
||||||
@@ -104,93 +102,37 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
|||||||
// aggiungiamo annotation con epicentro sisma
|
// aggiungiamo annotation con epicentro sisma
|
||||||
notificationView.addMapAnnotation(center: realtimeAlert.coordinate.coordinate, intensity: realtimeAlert.intensity)
|
notificationView.addMapAnnotation(center: realtimeAlert.coordinate.coordinate, intensity: realtimeAlert.intensity)
|
||||||
|
|
||||||
// simuliamo animazione dell'onda sismica
|
|
||||||
notificationView.addMapCircle(center: realtimeAlert.coordinate.coordinate, radius: waveAnimationCurrentRadius, overlayId: "wave_animation")
|
|
||||||
|
|
||||||
// aggiungiamo un segmento tra la posizione del sisma e quella dell'utente
|
// aggiungiamo un segmento tra la posizione del sisma e quella dell'utente
|
||||||
if let lastPosition = EQNUser.default().lastPosition {
|
if let lastPosition = EQNUser.default().lastPosition {
|
||||||
notificationView.addMapLine(coordinates: [realtimeAlert.coordinate.coordinate, lastPosition.coordinate])
|
notificationView.addMapLine(coordinates: [realtimeAlert.coordinate.coordinate, lastPosition.coordinate])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startCountdown() {
|
|
||||||
// show countdown only if time is less than 300 seconds
|
|
||||||
if realtimeAlert.currentCountdown() < 300 {
|
|
||||||
// start a timer for the countdown label
|
|
||||||
notificationView.waveTimeLabel.isHidden = false
|
|
||||||
countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdownTimerFired(_:)), userInfo: nil, repeats: true)
|
|
||||||
countdownTimer?.fire()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func startWaveAnimation() {
|
|
||||||
waveAnimationTimer = Timer.scheduledTimer(timeInterval: waveAnimationRefreshRate, target: self, selector: #selector(mapWaveAnimationFired(_:)), userInfo: nil, repeats: true)
|
|
||||||
waveAnimationTimer?.fire()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Action
|
// MARK: - Action
|
||||||
|
|
||||||
@objc private func onTapClose(_ sender: UIButton) {
|
@objc private func onTapClose(_ sender: UIButton) {
|
||||||
// invalidiamo i timer, altri
|
// stoppiamo animazione e countdown
|
||||||
countdownTimer?.invalidate()
|
animator.stop()
|
||||||
countdownTimer = nil
|
|
||||||
waveAnimationTimer?.invalidate()
|
|
||||||
waveAnimationTimer = nil
|
|
||||||
|
|
||||||
onClose()
|
onClose()
|
||||||
dismiss(animated: true)
|
dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RealtimeAlertViewController: MKMapViewDelegate {
|
||||||
|
|
||||||
// MARK: - Timer
|
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||||
|
animator.getOverlayRenderer(for: overlay) ?? MKOverlayRenderer(overlay: overlay)
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func countdownTimerFired(_ sender: Timer) {
|
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||||
let countdown = realtimeAlert.currentCountdown()
|
guard let annotation = annotation as? EQNMapAnnotationPastquake else {
|
||||||
notificationView.waveTimeLabel.text = String.localizedStringWithFormat(NSLocalizedString("alert_wave", comment: ""), countdown)
|
return nil
|
||||||
notificationView.waveTimeLabel.textColor = waveTimeTextColor(for: countdown)
|
|
||||||
|
|
||||||
if countdown <= 0 {
|
|
||||||
// stop the countdown
|
|
||||||
countdownTimer?.invalidate()
|
|
||||||
countdownTimer = nil
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func mapWaveAnimationFired(_ sender: Timer) {
|
|
||||||
waveAnimationCurrentRadius += waveAnimationVelocity
|
|
||||||
notificationView.addMapCircle(center: realtimeAlert.coordinate.coordinate, radius: waveAnimationCurrentRadius, overlayId: "wave_animation")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Helpers
|
|
||||||
|
|
||||||
/// Evaluate current position for the wave
|
|
||||||
/// Used to define initial position for the wave circle
|
|
||||||
/// - Returns: Distance of the wave from the original earthquake point
|
|
||||||
private func currentWavePosition() -> Double {
|
|
||||||
// distanza tra utente e terremoto
|
|
||||||
let distance = realtimeAlert.distanceFromUser()
|
|
||||||
|
|
||||||
// calcoliamo la distanza rimanente da mostrare, perchè la schermata potrebbe anche essere aperta in ritardo
|
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
|
||||||
let remainingDistance = realtimeAlert.waveSpeed * Double(realtimeAlert.currentCountdown())
|
annotationView.image = annotation.image
|
||||||
return distance - remainingDistance
|
annotationView.title = annotation.title
|
||||||
}
|
return annotationView
|
||||||
|
|
||||||
/// Evaluate wave velocity based on push notification data
|
|
||||||
/// - Returns: Wave velocity, used for animation
|
|
||||||
private func evaluateWaveAnimationVelocity() -> Double {
|
|
||||||
let velocity = realtimeAlert.waveSpeed
|
|
||||||
return velocity * waveAnimationRefreshRate
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the text color based on impact countdown
|
|
||||||
private func waveTimeTextColor(for countdown: Int) -> UIColor {
|
|
||||||
switch countdown {
|
|
||||||
case _ where countdown > 15:
|
|
||||||
return UIColor(red: 255.0/255.0, green: 140.0/255.0, blue: 0.0, alpha: 1.0)
|
|
||||||
case _ where countdown > 5:
|
|
||||||
return UIColor(red: 255.0/255.0, green: 100.0/255.0, blue: 0.0, alpha: 1.0)
|
|
||||||
default:
|
|
||||||
return UIColor(red: 255.0/255.0, green: 0.0/255.0, blue: 0.0, alpha: 1.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -206,6 +206,7 @@ class SeismicNetworkMinimalTableViewCell: SeismicNetworkBaseTableViewCell {
|
|||||||
) {
|
) {
|
||||||
self.seismic = seismic
|
self.seismic = seismic
|
||||||
self.isPushSelected = isPushSelected
|
self.isPushSelected = isPushSelected
|
||||||
|
self.informationTypes.removeAll()
|
||||||
|
|
||||||
if seismic.preliminary.intValue > 0 {
|
if seismic.preliminary.intValue > 0 {
|
||||||
informationTypes.insert(.preliminary)
|
informationTypes.insert(.preliminary)
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
|||||||
]
|
]
|
||||||
|
|
||||||
private let initialFilterType = EQNSeismic.shared.filterOption
|
private let initialFilterType = EQNSeismic.shared.filterOption
|
||||||
private var currentFilterType = EQNSeismic.FilterType.inRadius
|
private(set) var currentFilterType = EQNSeismic.FilterType.inRadius
|
||||||
private var currentMaximumDistance = EQNData.DefaultFilterRadius
|
private var currentMaximumDistance = EQNData.DefaultFilterRadius
|
||||||
private var currentMinimumMagnitude = EQNData.DefaultFilterMagnitude
|
private var currentMinimumMagnitude = EQNData.DefaultFilterMagnitude
|
||||||
|
|
||||||
|
|||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// SeismicNetworkFilterRecapView.swift
|
||||||
|
// Earthquake Network
|
||||||
|
//
|
||||||
|
// Created by Andrea Busi on 17/07/25.
|
||||||
|
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Shogun
|
||||||
|
|
||||||
|
|
||||||
|
struct SeismicNetworkFilterRecapView: View {
|
||||||
|
class Model: ObservableObject {
|
||||||
|
@Published var filter = EQNSeismic.shared.filterOption
|
||||||
|
@Published var sort = EQNSeismic.shared.sort
|
||||||
|
}
|
||||||
|
|
||||||
|
@ObservedObject private var model: Model
|
||||||
|
private let onSort: (_ sort: EQNSeismic.Sort) -> Void
|
||||||
|
private let onMainFilter: () -> Void
|
||||||
|
private let onMap: () -> Void
|
||||||
|
|
||||||
|
// MARK: - Init
|
||||||
|
|
||||||
|
init(
|
||||||
|
model: Model,
|
||||||
|
onSort: @escaping (_ sort: EQNSeismic.Sort) -> Void,
|
||||||
|
onMainFilter: @escaping () -> Void,
|
||||||
|
onMap: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
self.model = model
|
||||||
|
self.onSort = onSort
|
||||||
|
self.onMainFilter = onMainFilter
|
||||||
|
self.onMap = onMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - View
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
RoundedButton(
|
||||||
|
systemName: sortIcon,
|
||||||
|
tintColor: tintColor,
|
||||||
|
action: {
|
||||||
|
model.sort.advance()
|
||||||
|
onSort(model.sort)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button {
|
||||||
|
onMainFilter()
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "magnifyingglass")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(height: 12)
|
||||||
|
|
||||||
|
Text(filterTitle)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.overlay {
|
||||||
|
Capsule().stroke(AppTheme.Colors.gray.color, lineWidth: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.font(.caption)
|
||||||
|
.tint(tintColor)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
RoundedButton(
|
||||||
|
systemName: "globe",
|
||||||
|
tintColor: tintColor,
|
||||||
|
action: onMap
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.background(Color.clear)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var tintColor: Color {
|
||||||
|
Color.blue
|
||||||
|
//AppTheme.Colors.lightBlue.color
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filterTitle: String {
|
||||||
|
switch model.filter {
|
||||||
|
case .inRadius: "filter_area".localized
|
||||||
|
case .positionRelevant: "filter_relevant".localized
|
||||||
|
case .worldWide: "filter_all".localized
|
||||||
|
case .userFelt: "filter_felt".localized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var sortIcon: String {
|
||||||
|
switch model.sort {
|
||||||
|
case .time: "clock"
|
||||||
|
case .position:
|
||||||
|
if #available(iOS 16, *) {
|
||||||
|
"compass.drawing"
|
||||||
|
} else {
|
||||||
|
"ruler"
|
||||||
|
}
|
||||||
|
case .magnitude: "thermometer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct RoundedButton: View {
|
||||||
|
let systemName: String
|
||||||
|
let tintColor: Color
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button {
|
||||||
|
action()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: systemName)
|
||||||
|
.resizable()
|
||||||
|
.tint(tintColor)
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxHeight: .infinity)
|
||||||
|
.frame(width: 40.0)
|
||||||
|
.padding(8)
|
||||||
|
.overlay {
|
||||||
|
Capsule().stroke(AppTheme.Colors.gray.color, lineWidth: 1)
|
||||||
|
}
|
||||||
|
.animation(nil, value: systemName) // previene animazioni implicite nel bottone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
SeismicNetworkFilterRecapView(
|
||||||
|
model: .init(),
|
||||||
|
onSort: { _ in },
|
||||||
|
onMainFilter: {},
|
||||||
|
onMap: {}
|
||||||
|
)
|
||||||
|
.frame(height: 34.0)
|
||||||
|
}
|
||||||
+22
-2
@@ -140,7 +140,7 @@ class SeismicNetworksIntensityMapViewController: EQNBaseMapViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func nextPinStyle() {
|
private func nextPinStyle() {
|
||||||
pinStyle.next()
|
pinStyle.advance()
|
||||||
reloadMap()
|
reloadMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ extension EQNMapAnnotationShakemap {
|
|||||||
case .full, .light:
|
case .full, .light:
|
||||||
let identifier = EQNSeismicAnnotationView.identifier(for: style)
|
let identifier = EQNSeismicAnnotationView.identifier(for: style)
|
||||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: self) as! EQNSeismicAnnotationView
|
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: self) as! EQNSeismicAnnotationView
|
||||||
annotationView.magnitude = String(format: "%.1f", shakemap.intensity)
|
annotationView.magnitude = intensityString(from: shakemap.intensity)
|
||||||
annotationView.magnitudeTextColor = intensityTextColor ?? .black
|
annotationView.magnitudeTextColor = intensityTextColor ?? .black
|
||||||
annotationView.magnitudeBackgroundColor = intensityColor
|
annotationView.magnitudeBackgroundColor = intensityColor
|
||||||
annotationView.canShowCallout = true
|
annotationView.canShowCallout = true
|
||||||
@@ -242,6 +242,26 @@ extension EQNMapAnnotationShakemap {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func intensityString(from intensity: Float) -> String {
|
||||||
|
let intensityRounded = (intensity * 10).rounded() / 10
|
||||||
|
let intensityFloor = floor(intensityRounded)
|
||||||
|
|
||||||
|
let romanNumerals: [Int: String] = [
|
||||||
|
1: "I", 2: "II", 3: "III", 4: "IV",
|
||||||
|
5: "V", 6: "VI", 7: "VII", 8: "VIII",
|
||||||
|
9: "IX", 10: "X", 11: "XI", 12: "XII"
|
||||||
|
]
|
||||||
|
|
||||||
|
var result = romanNumerals[Int(intensityFloor)] ?? ""
|
||||||
|
|
||||||
|
if intensityRounded != intensityFloor {
|
||||||
|
let reminder = Int(((intensityRounded - intensityFloor) * 10).rounded())
|
||||||
|
result += ".\(reminder)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate class ShakemapPolyline: MKPolyline {
|
fileprivate class ShakemapPolyline: MKPolyline {
|
||||||
|
|||||||
+11
-4
@@ -63,14 +63,17 @@ class SeismicNetworksMapDetailViewController: EQNBaseMapViewController {
|
|||||||
|
|
||||||
// MARK: - Internal
|
// MARK: - Internal
|
||||||
|
|
||||||
private let seismic: EQNSisma
|
private let seismic: EQNSisma?
|
||||||
private var allSeismics: [EQNSisma]
|
private var allSeismics: [EQNSisma]
|
||||||
/// Contains circles drawed on the map
|
/// Contains circles drawed on the map
|
||||||
private var mapCircles = [MKCircle]()
|
private var mapCircles = [MKCircle]()
|
||||||
|
|
||||||
// MARK: - Init
|
// MARK: - Init
|
||||||
|
|
||||||
init(seismic: EQNSisma, allSeismics: [EQNSisma]) {
|
init(
|
||||||
|
seismic: EQNSisma?,
|
||||||
|
allSeismics: [EQNSisma]
|
||||||
|
) {
|
||||||
self.seismic = seismic
|
self.seismic = seismic
|
||||||
self.allSeismics = allSeismics
|
self.allSeismics = allSeismics
|
||||||
super.init()
|
super.init()
|
||||||
@@ -128,7 +131,11 @@ class SeismicNetworksMapDetailViewController: EQNBaseMapViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func elaborateMapCenter() {
|
override func elaborateMapCenter() {
|
||||||
setMapCenter(for: seismic.coordinate)
|
if let seismic {
|
||||||
|
setMapCenter(for: seismic.coordinate)
|
||||||
|
} else if let location = CLLocationManager().location {
|
||||||
|
setMapCenter(for: location)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
||||||
@@ -178,7 +185,7 @@ class SeismicNetworksMapDetailViewController: EQNBaseMapViewController {
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func nextPinStyle() {
|
private func nextPinStyle() {
|
||||||
pinStyle.next()
|
pinStyle.advance()
|
||||||
reloadMap()
|
reloadMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+80
-32
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import SwiftUI
|
||||||
import EventKitUI
|
import EventKitUI
|
||||||
import DZNEmptyDataSet
|
import DZNEmptyDataSet
|
||||||
import Shogun
|
import Shogun
|
||||||
@@ -68,7 +69,6 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
// MARK: - UI
|
// MARK: - UI
|
||||||
|
|
||||||
@IBOutlet private weak var displayModeButton: UIBarButtonItem!
|
@IBOutlet private weak var displayModeButton: UIBarButtonItem!
|
||||||
@IBOutlet private weak var sortButton: UIBarButtonItem!
|
|
||||||
private var tableViewTopConstraint: NSLayoutConstraint?
|
private var tableViewTopConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
private lazy var tableView: UITableView = {
|
private lazy var tableView: UITableView = {
|
||||||
@@ -111,6 +111,32 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
view.layer.borderColor = AppTheme.Colors.gray.cgColor
|
view.layer.borderColor = AppTheme.Colors.gray.cgColor
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// model is needed in order to send data to SwiftUI view
|
||||||
|
private let model = SeismicNetworkFilterRecapView.Model()
|
||||||
|
|
||||||
|
private lazy var filterRecapView: UIView = {
|
||||||
|
let hosting = UIHostingController(
|
||||||
|
rootView: SeismicNetworkFilterRecapView(
|
||||||
|
model: model,
|
||||||
|
onSort: { [weak self] sort in
|
||||||
|
self?.changeSort(to: sort)
|
||||||
|
},
|
||||||
|
onMainFilter: { [weak self] in
|
||||||
|
self?.openFilter()
|
||||||
|
},
|
||||||
|
onMap: { [weak self] in
|
||||||
|
self?.showMapDetail(for: nil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
addChild(hosting)
|
||||||
|
let filterRecapView = hosting.view!
|
||||||
|
hosting.view.isOpaque = false
|
||||||
|
hosting.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
hosting.didMove(toParent: self)
|
||||||
|
return hosting.view
|
||||||
|
}()
|
||||||
|
|
||||||
// MARK: - View Lifecycle
|
// MARK: - View Lifecycle
|
||||||
|
|
||||||
@@ -147,19 +173,44 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func setupUI() {
|
private func setupUI() {
|
||||||
|
view.backgroundColor = tableView.backgroundColor
|
||||||
view.addSubview(scrollIndicatorView)
|
view.addSubview(scrollIndicatorView)
|
||||||
view.addSubview(tableView)
|
view.addSubview(tableView)
|
||||||
|
view.addSubview(filterRecapView)
|
||||||
|
|
||||||
scrollIndicatorView.topAnchor.constraint(equalTo: tableView.topAnchor).isActive = true
|
scrollIndicatorView.topAnchor.constraint(equalTo: tableView.topAnchor).isActive = true
|
||||||
scrollIndicatorView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
scrollIndicatorView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||||
scrollIndicatorView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
|
scrollIndicatorView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
|
||||||
scrollIndicatorView.widthAnchor.constraint(equalToConstant: 10.0).isActive = true
|
scrollIndicatorView.widthAnchor.constraint(equalToConstant: 10.0).isActive = true
|
||||||
|
|
||||||
tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor)
|
tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor)
|
||||||
tableViewTopConstraint?.isActive = true
|
tableViewTopConstraint?.isActive = true
|
||||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||||
tableView.trailingAnchor.constraint(equalTo: scrollIndicatorView.leadingAnchor).isActive = true
|
tableView.trailingAnchor.constraint(equalTo: scrollIndicatorView.leadingAnchor).isActive = true
|
||||||
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
|
tableView.bottomAnchor
|
||||||
|
.constraint(
|
||||||
|
equalTo: filterRecapView.topAnchor,
|
||||||
|
constant: -8
|
||||||
|
).isActive = true
|
||||||
|
|
||||||
|
filterRecapView.heightAnchor.constraint(equalToConstant: 34.0).isActive = true
|
||||||
|
filterRecapView.leadingAnchor
|
||||||
|
.constraint(
|
||||||
|
equalTo: view.leadingAnchor,
|
||||||
|
constant: 10.0
|
||||||
|
).isActive = true
|
||||||
|
filterRecapView.trailingAnchor
|
||||||
|
.constraint(
|
||||||
|
equalTo: view.trailingAnchor,
|
||||||
|
constant: -10.0
|
||||||
|
).isActive = true
|
||||||
|
filterRecapView.topAnchor
|
||||||
|
.constraint(equalTo: tableView.bottomAnchor).isActive = true
|
||||||
|
filterRecapView.bottomAnchor
|
||||||
|
.constraint(
|
||||||
|
equalTo: view.safeAreaLayoutGuide.bottomAnchor,
|
||||||
|
constant: -8
|
||||||
|
).isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupFilterView(isVisible: Bool) {
|
private func setupFilterView(isVisible: Bool) {
|
||||||
@@ -201,31 +252,13 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
tableView.emptyDataSetSource = self
|
tableView.emptyDataSetSource = self
|
||||||
tableView.separatorStyle = .none
|
tableView.separatorStyle = .none
|
||||||
tableView.contentInset = EQNBaseContainerTableViewCell.EdgeInsets
|
tableView.contentInset = EQNBaseContainerTableViewCell.EdgeInsets
|
||||||
|
|
||||||
setupSortMenu()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func setupSortMenu() {
|
|
||||||
let currentSort = EQNSeismic.shared.sort
|
|
||||||
sortButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: [
|
|
||||||
UIAction(title: NSLocalizedString("sort_date", comment: ""), image: UIImage(systemName: "calendar"), state: currentSort == .time ? .on : .off) { [weak self ] _ in
|
|
||||||
self?.changeSort(to: .time)
|
|
||||||
},
|
|
||||||
UIAction(title: NSLocalizedString("sort_position", comment: ""), image: UIImage(systemName: "ruler"), state: currentSort == .position ? .on : .off) { [weak self] _ in
|
|
||||||
self?.changeSort(to: .position)
|
|
||||||
},
|
|
||||||
UIAction(title: NSLocalizedString("sort_magnitude", comment: ""), image: UIImage(systemName: "thermometer"), state: currentSort == .magnitude ? .on : .off) { [weak self] _ in
|
|
||||||
self?.changeSort(to: .magnitude)
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkForLocation() {
|
private func checkForLocation() {
|
||||||
// check if a valid location is available,
|
// check if a valid location is available,
|
||||||
// otherwise change the filter settings
|
// otherwise change the filter settings
|
||||||
if !isLocationAvailable() {
|
if !isLocationAvailable() {
|
||||||
EQNSeismic.shared.filterOption = .worldWide
|
updateFilter(type: .worldWide)
|
||||||
EQNSeismic.shared.saveFilters()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +277,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func showMapDetail(for seismic: EQNSisma) {
|
private func showMapDetail(for seismic: EQNSisma?) {
|
||||||
let seismics = getSeismics()
|
let seismics = getSeismics()
|
||||||
let controller = SeismicNetworksMapDetailViewController(seismic: seismic, allSeismics: seismics)
|
let controller = SeismicNetworksMapDetailViewController(seismic: seismic, allSeismics: seismics)
|
||||||
controller.delegate = self
|
controller.delegate = self
|
||||||
@@ -335,10 +368,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func changeSort(to sort: EQNSeismic.Sort) {
|
private func changeSort(to sort: EQNSeismic.Sort) {
|
||||||
EQNSeismic.shared.sort = sort
|
updateFilter(sort: sort)
|
||||||
EQNSeismic.shared.saveFilters()
|
|
||||||
|
|
||||||
setupSortMenu()
|
|
||||||
refreshUI()
|
refreshUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,11 +598,22 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
|
|
||||||
private func updateFilter(
|
private func updateFilter(
|
||||||
type: EQNSeismic.FilterType? = nil,
|
type: EQNSeismic.FilterType? = nil,
|
||||||
|
sort: EQNSeismic.Sort? = nil,
|
||||||
radius: Double? = nil,
|
radius: Double? = nil,
|
||||||
magnitude: Double? = nil
|
magnitude: Double? = nil
|
||||||
) {
|
) {
|
||||||
if let type {
|
if let type {
|
||||||
|
let previous = EQNSeismic.shared.filterOption
|
||||||
|
if previous == .userFelt && previous != type {
|
||||||
|
loadData(forced: true)
|
||||||
|
}
|
||||||
|
|
||||||
EQNSeismic.shared.filterOption = type
|
EQNSeismic.shared.filterOption = type
|
||||||
|
model.filter = type
|
||||||
|
}
|
||||||
|
if let sort {
|
||||||
|
EQNSeismic.shared.sort = sort
|
||||||
|
model.sort = sort
|
||||||
}
|
}
|
||||||
if let radius {
|
if let radius {
|
||||||
EQNSeismic.shared.maximumDistance = String(format: "%.0f", radius)
|
EQNSeismic.shared.maximumDistance = String(format: "%.0f", radius)
|
||||||
@@ -628,9 +669,15 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
if let centerIndexPath = getCenterCellIndexPath(), centerIndexPath != currentCenteredIndexPath {
|
if let centerIndexPath = getCenterCellIndexPath(), centerIndexPath != currentCenteredIndexPath {
|
||||||
currentCenteredIndexPath = centerIndexPath
|
currentCenteredIndexPath = centerIndexPath
|
||||||
|
|
||||||
let row = rows[centerIndexPath.row]
|
if rows.count > centerIndexPath.row {
|
||||||
if case .seismic = row, seismicViewModels.count > centerIndexPath.row {
|
let row = rows[centerIndexPath.row]
|
||||||
scrollIndicatorView.highlighted = seismicViewModels[centerIndexPath.row]
|
if case .seismic = row, seismicViewModels.count > centerIndexPath.row {
|
||||||
|
scrollIndicatorView.highlighted = seismicViewModels[centerIndexPath.row]
|
||||||
|
} else {
|
||||||
|
scrollIndicatorView.highlighted = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scrollIndicatorView.highlighted = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,12 +688,12 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
|||||||
loadData(forced: true)
|
loadData(forced: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func openFilterTapped(_ sender: Any) {
|
private func openFilter() {
|
||||||
performSegue(withIdentifier: Self.SegueIdentifierFilters, sender: nil)
|
performSegue(withIdentifier: Self.SegueIdentifierFilters, sender: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func collapseExpandTapped(_ sender: Any) {
|
@IBAction func collapseExpandTapped(_ sender: Any) {
|
||||||
cardDisplayType.next()
|
cardDisplayType.advance()
|
||||||
|
|
||||||
switch cardDisplayType {
|
switch cardDisplayType {
|
||||||
case .small:
|
case .small:
|
||||||
@@ -851,6 +898,7 @@ extension SeismicNetworksViewController: EKEventEditViewDelegate {
|
|||||||
|
|
||||||
extension SeismicNetworksViewController: SeismicFiltersViewControllerDelegate {
|
extension SeismicNetworksViewController: SeismicFiltersViewControllerDelegate {
|
||||||
func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController) {
|
func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController) {
|
||||||
|
model.filter = controller.currentFilterType
|
||||||
loadData(forced: controller.needsDataUpdate)
|
loadData(forced: controller.needsDataUpdate)
|
||||||
refreshUI()
|
refreshUI()
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -13,14 +13,17 @@ class SettingsRealTimeAlertsViewController: SettingsBaseTableViewController {
|
|||||||
|
|
||||||
private enum RowIdentifier: Int {
|
private enum RowIdentifier: Int {
|
||||||
case abilitaNotifiche
|
case abilitaNotifiche
|
||||||
|
case disabilitaSuonoAllerta
|
||||||
case abilitaCriticalAlerts
|
case abilitaCriticalAlerts
|
||||||
}
|
}
|
||||||
|
|
||||||
private var isNotificationEnabled = false
|
private var isNotificationEnabled = false
|
||||||
|
private var isMildQuakeSoundDisabled = false
|
||||||
private var isCriticalAlertsEnabled = false
|
private var isCriticalAlertsEnabled = false
|
||||||
|
|
||||||
private let settings: [SettingItem] = [
|
private let settings: [SettingItem] = [
|
||||||
.init(type: .enable, title: NSLocalizedString("options_notification_enable_alarm", comment: "")),
|
.init(type: .enable, title: NSLocalizedString("options_notification_enable_alarm", comment: "")),
|
||||||
|
.init(type: .enable, title: NSLocalizedString("options_notification_disable_sound", comment: "")),
|
||||||
.init(type: .enable, title: NSLocalizedString("critical_alerts_setting", comment: ""))
|
.init(type: .enable, title: NSLocalizedString("critical_alerts_setting", comment: ""))
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ class SettingsRealTimeAlertsViewController: SettingsBaseTableViewController {
|
|||||||
let saved = EQNSettingRealTimeAlert.shared
|
let saved = EQNSettingRealTimeAlert.shared
|
||||||
|
|
||||||
isNotificationEnabled = saved.isAbilitato
|
isNotificationEnabled = saved.isAbilitato
|
||||||
|
isMildQuakeSoundDisabled = saved.isMildQuakeSoundDisabled
|
||||||
isCriticalAlertsEnabled = saved.isCriticalAlertsEnabled
|
isCriticalAlertsEnabled = saved.isCriticalAlertsEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +97,11 @@ class SettingsRealTimeAlertsViewController: SettingsBaseTableViewController {
|
|||||||
cell.valueChanged = { [weak self] enabled in
|
cell.valueChanged = { [weak self] enabled in
|
||||||
self?.onChangeNotificationEnabled(enabled)
|
self?.onChangeNotificationEnabled(enabled)
|
||||||
}
|
}
|
||||||
|
case .disabilitaSuonoAllerta:
|
||||||
|
cell.toggleSwitch.isOn = isMildQuakeSoundDisabled
|
||||||
|
cell.valueChanged = { [weak self] enabled in
|
||||||
|
self?.onChangeDisableSoundEnabled(enabled)
|
||||||
|
}
|
||||||
case .abilitaCriticalAlerts:
|
case .abilitaCriticalAlerts:
|
||||||
cell.toggleSwitch.isOn = isCriticalAlertsEnabled
|
cell.toggleSwitch.isOn = isCriticalAlertsEnabled
|
||||||
cell.valueChanged = { [weak self] enabled in
|
cell.valueChanged = { [weak self] enabled in
|
||||||
@@ -116,6 +125,14 @@ class SettingsRealTimeAlertsViewController: SettingsBaseTableViewController {
|
|||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func onChangeDisableSoundEnabled(_ enabled: Bool) {
|
||||||
|
isMildQuakeSoundDisabled = enabled
|
||||||
|
EQNSettingRealTimeAlert.shared.isMildQuakeSoundDisabled = isMildQuakeSoundDisabled
|
||||||
|
EQNSettingRealTimeAlert.shared.saveUserInfo()
|
||||||
|
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
private func onChangeCriticalAlertsEnabled(_ enabled: Bool) {
|
private func onChangeCriticalAlertsEnabled(_ enabled: Bool) {
|
||||||
if enabled {
|
if enabled {
|
||||||
askForCriticalAlertsPermission()
|
askForCriticalAlertsPermission()
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ static NSString * const EQNServerUrlCalibration = @"https://srv.earthquakenetwor
|
|||||||
// download rete smartphone
|
// download rete smartphone
|
||||||
static NSString * const EQNServerUrlDownloadSmartphoneNetwork = @"https://cache.earthquakenetwork.it/distquake_count_redis3.php";
|
static NSString * const EQNServerUrlDownloadSmartphoneNetwork = @"https://cache.earthquakenetwork.it/distquake_count_redis3.php";
|
||||||
// download area check
|
// download area check
|
||||||
static NSString * const EQNServerUrlDownloadAreaCheck = @"https://srv.earthquakenetwork.it/distquake_download_areacheck.php";
|
static NSString * const EQNServerUrlDownloadAreaCheck = @"https://cache.earthquakenetwork.it/distquake_download_areacheck.php";
|
||||||
// download pastquakes
|
// download pastquakes
|
||||||
static NSString * const EQNServerUrlDownloadPastQuakes = @"https://srv.earthquakenetwork.it/distquake_download_pastquakes.php";
|
static NSString * const EQNServerUrlDownloadPastQuakes = @"https://srv.earthquakenetwork.it/distquake_download_pastquakes.php";
|
||||||
// download segnalazioni
|
// download segnalazioni
|
||||||
|
|||||||
@@ -37,13 +37,3 @@ extension CGFloat {
|
|||||||
self*2.0
|
self*2.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CaseIterable where Self: Equatable {
|
|
||||||
mutating func next() {
|
|
||||||
let all = Self.allCases
|
|
||||||
let idx = all.firstIndex(of: self)!
|
|
||||||
let next = all.index(after: idx)
|
|
||||||
let newValue = all[next == all.endIndex ? all.startIndex : next]
|
|
||||||
self = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ public class Log {
|
|||||||
shared.log(level: .debug, tag: tag ?? "nil", message: message ?? "nil", functionName: functionName)
|
shared.log(level: .debug, tag: tag ?? "nil", message: message ?? "nil", functionName: functionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
|
||||||
public func dumpLog() async -> String {
|
public func dumpLog() async -> String {
|
||||||
return (try? await getLogEntries()) ?? ""
|
return (try? await getLogEntries()) ?? ""
|
||||||
}
|
}
|
||||||
@@ -104,7 +103,6 @@ public class Log {
|
|||||||
|
|
||||||
/// Retrieve log entries from a specified time.
|
/// Retrieve log entries from a specified time.
|
||||||
/// - Returns: String of log entries, newlines separated
|
/// - Returns: String of log entries, newlines separated
|
||||||
@available(iOS 15.0, *)
|
|
||||||
private func getLogEntries() async throws -> String {
|
private func getLogEntries() async throws -> String {
|
||||||
let logTask = Task.init(priority: .utility) { () -> String in
|
let logTask = Task.init(priority: .utility) { () -> String in
|
||||||
let logs = try retrieveLogEntries()
|
let logs = try retrieveLogEntries()
|
||||||
@@ -116,7 +114,6 @@ public class Log {
|
|||||||
return try await logTask.value
|
return try await logTask.value
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
|
||||||
private func retrieveLogEntries() throws -> [OSLogEntryLog] {
|
private func retrieveLogEntries() throws -> [OSLogEntryLog] {
|
||||||
// Open the log store.
|
// Open the log store.
|
||||||
let logStore = try OSLogStore(scope: .currentProcessIdentifier)
|
let logStore = try OSLogStore(scope: .currentProcessIdentifier)
|
||||||
@@ -134,7 +131,6 @@ public class Log {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
|
||||||
extension OSLogEntryLog.Level: @retroactive CustomStringConvertible {
|
extension OSLogEntryLog.Level: @retroactive CustomStringConvertible {
|
||||||
public var description: String {
|
public var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
|||||||
migrationFirstAppStat()
|
migrationFirstAppStat()
|
||||||
migrationCriticalAlerts()
|
migrationCriticalAlerts()
|
||||||
migrationV5_9()
|
migrationV5_9()
|
||||||
|
migrationV5_10()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
@@ -119,4 +120,19 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
|||||||
|
|
||||||
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_9)
|
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_9)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func migrationV5_10() {
|
||||||
|
let userDefaults = UserDefaults.standard
|
||||||
|
let migrationPerformed = userDefaults.bool(forKey: UserDefaults.AppMigrationV5_10)
|
||||||
|
if migrationPerformed {
|
||||||
|
print("[EQNUserDefaultsCommand] Migration v5.10 already performed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
print("[EQNUserDefaultsCommand] Save default value for mildQuakeSoundDisabled")
|
||||||
|
EQNSettingRealTimeAlert.shared.isMildQuakeSoundDisabled = true
|
||||||
|
EQNSettingRealTimeAlert.shared.saveUserInfo()
|
||||||
|
|
||||||
|
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_10)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,14 @@
|
|||||||
- (void)scaricaDatiReteSmartphone
|
- (void)scaricaDatiReteSmartphone
|
||||||
{
|
{
|
||||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:EQNServerUrlDownloadSmartphoneNetwork] richiesta:EQNTipoChiamataDownloadDati success:^(id result) {
|
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:EQNServerUrlDownloadSmartphoneNetwork] richiesta:EQNTipoChiamataDownloadDati success:^(id result) {
|
||||||
|
|
||||||
self.rete_smartphone = [[EQNReteSmartphone alloc] initWithInfo:result];
|
// Parsiamo la risposta (assicurandoci che non contenga valori nulli)
|
||||||
|
EQNReteSmartphone *rete = [EQNReteSmartphone fromResponse:result];
|
||||||
|
if (rete != nil) {
|
||||||
|
self.rete_smartphone = rete;
|
||||||
|
} else {
|
||||||
|
NSLog(@"[EQNManager] Impossibile parsare la risposta di DownloadSmartphoneNetwork");
|
||||||
|
}
|
||||||
|
|
||||||
[self performSelectorOnMainThread:@selector(scaricaAreaCheck) withObject:nil waitUntilDone:YES];
|
[self performSelectorOnMainThread:@selector(scaricaAreaCheck) withObject:nil waitUntilDone:YES];
|
||||||
} failure:^(NSError * error) {
|
} failure:^(NSError * error) {
|
||||||
@@ -72,7 +78,12 @@
|
|||||||
|
|
||||||
- (void)scaricaAreaCheck
|
- (void)scaricaAreaCheck
|
||||||
{
|
{
|
||||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?lat=%f&lon=%f", EQNServerUrlDownloadAreaCheck, [EQNUser defaultUser].lastPosition.coordinate.latitude, [EQNUser defaultUser].lastPosition.coordinate.longitude]] richiesta:EQNTipoChiamataAreaCheck success:^(id result) {
|
// Quantizziamo le coordinate, in modo che venga sfruttata la cache lato server
|
||||||
|
CLLocation *lastPosition = [EQNUser defaultUser].lastPosition;
|
||||||
|
double latitude = round(lastPosition.coordinate.latitude * 5.0) / 5.0;
|
||||||
|
double longitude = round(lastPosition.coordinate.longitude * 5.0) / 5.0;
|
||||||
|
|
||||||
|
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?lat=%f&lon=%f", EQNServerUrlDownloadAreaCheck, latitude, longitude]] richiesta:EQNTipoChiamataAreaCheck success:^(id result) {
|
||||||
|
|
||||||
self.area_check = [[EQNAreaCheck alloc] initWithInfo:result];
|
self.area_check = [[EQNAreaCheck alloc] initWithInfo:result];
|
||||||
|
|
||||||
@@ -123,11 +134,13 @@
|
|||||||
// L'endpoint per lo scaricamento dei dati prende due parametri:
|
// L'endpoint per lo scaricamento dei dati prende due parametri:
|
||||||
// - `pro` per il provider selezionato,
|
// - `pro` per il provider selezionato,
|
||||||
// - `mag` per la magnitudo minima.
|
// - `mag` per la magnitudo minima.
|
||||||
// Dalla v5.8 non esiste più la selezione delle reti, quindi passiamo sempre "ALL".
|
// Dalla v5.8 non esiste più la selezione delle reti, quindi il provider da passare diventa:
|
||||||
|
// - `FELT` se filtro selezionato è sismi percepiti
|
||||||
|
// - `ALL` in tutti gli altri casi
|
||||||
// Per la magnitudo minima, invece, passiamo 0 per i filtri "raggio" e "rilevanti,
|
// Per la magnitudo minima, invece, passiamo 0 per i filtri "raggio" e "rilevanti,
|
||||||
// altrimenti passiamo 2 per il filtro "mondo"
|
// altrimenti passiamo 2 per il filtro "mondo"
|
||||||
|
|
||||||
NSString *filterProvider = @"ALL";
|
NSString *filterProvider = [EQNSeismic shared].filterOption == FilterTypeUserFelt ? @"FELT" : @"ALL";
|
||||||
NSString *filterMagnitude = [EQNSeismic shared].filterOption == FilterTypeWorldWide ? @"2.0" : @"0.0";
|
NSString *filterMagnitude = [EQNSeismic shared].filterOption == FilterTypeWorldWide ? @"2.0" : @"0.0";
|
||||||
|
|
||||||
NSString *queryString = [NSString stringWithFormat:@"?pro=%@&mag=%@", filterProvider, filterMagnitude];
|
NSString *queryString = [NSString stringWithFormat:@"?pro=%@&mag=%@", filterProvider, filterMagnitude];
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
case intensity
|
case intensity
|
||||||
|
case magnitude
|
||||||
case latitude
|
case latitude
|
||||||
case longitude
|
case longitude
|
||||||
case counter
|
case counter
|
||||||
@@ -36,6 +37,7 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
let type: String
|
let type: String
|
||||||
/// Earthquake intensity
|
/// Earthquake intensity
|
||||||
let intensity: Int
|
let intensity: Int
|
||||||
|
let magnitude: Int
|
||||||
/// Earthquake coordinate
|
/// Earthquake coordinate
|
||||||
let latitude: Double
|
let latitude: Double
|
||||||
let longitude: Double
|
let longitude: Double
|
||||||
@@ -63,6 +65,7 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
init(
|
init(
|
||||||
type: String,
|
type: String,
|
||||||
intensity: Int,
|
intensity: Int,
|
||||||
|
magnitude: Int,
|
||||||
latitude: Double,
|
latitude: Double,
|
||||||
longitude: Double,
|
longitude: Double,
|
||||||
counter: Int,
|
counter: Int,
|
||||||
@@ -76,6 +79,7 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
) {
|
) {
|
||||||
self.type = type
|
self.type = type
|
||||||
self.intensity = intensity
|
self.intensity = intensity
|
||||||
|
self.magnitude = magnitude
|
||||||
self.latitude = latitude
|
self.latitude = latitude
|
||||||
self.longitude = longitude
|
self.longitude = longitude
|
||||||
self.counter = counter
|
self.counter = counter
|
||||||
@@ -201,6 +205,27 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var title: String = ""
|
||||||
|
if let titleKey = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
|
||||||
|
title = String(format: NSLocalizedString(titleKey, comment: ""), arg)
|
||||||
|
}
|
||||||
|
let displayTitle = payload.string(forKey: "title", orDefault: "")
|
||||||
|
let displayBody = payload.string(forKey: "body", orDefault: "")
|
||||||
|
|
||||||
|
return from(
|
||||||
|
userInfo: userInfo,
|
||||||
|
title: title,
|
||||||
|
displayTitle: displayTitle,
|
||||||
|
displayBody: displayBody
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(
|
||||||
|
userInfo: [AnyHashable: Any],
|
||||||
|
title: String,
|
||||||
|
displayTitle: String,
|
||||||
|
displayBody: String
|
||||||
|
) -> EQNRealtimePushNotification? {
|
||||||
guard let latitude = userInfo.double(forKey: "latitude"),
|
guard let latitude = userInfo.double(forKey: "latitude"),
|
||||||
let longitude = userInfo.double(forKey: "longitude") else {
|
let longitude = userInfo.double(forKey: "longitude") else {
|
||||||
print("[EQNRealtimePushNotification] Unable to get coordinate from push notification")
|
print("[EQNRealtimePushNotification] Unable to get coordinate from push notification")
|
||||||
@@ -209,6 +234,7 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
|
|
||||||
let type = userInfo.string(forKey: "type", orDefault: "")
|
let type = userInfo.string(forKey: "type", orDefault: "")
|
||||||
let intensity = userInfo.integer(forKey: "intensity", orDefault: 0)
|
let intensity = userInfo.integer(forKey: "intensity", orDefault: 0)
|
||||||
|
let magnitude = userInfo.integer(forKey: "magnitude", orDefault: 0)
|
||||||
|
|
||||||
let counter = userInfo.integer(forKey: "counter", orDefault: 0)
|
let counter = userInfo.integer(forKey: "counter", orDefault: 0)
|
||||||
var dateTime: Date?
|
var dateTime: Date?
|
||||||
@@ -222,16 +248,10 @@ class EQNRealtimePushNotification: NSObject, Codable {
|
|||||||
}
|
}
|
||||||
let peak = userInfo.double(forKey: "peak")
|
let peak = userInfo.double(forKey: "peak")
|
||||||
|
|
||||||
var title: String = ""
|
|
||||||
if let titleKey = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
|
|
||||||
title = String(format: NSLocalizedString(titleKey, comment: ""), arg)
|
|
||||||
}
|
|
||||||
let displayTitle = payload.string(forKey: "title", orDefault: "")
|
|
||||||
let displayBody = payload.string(forKey: "body", orDefault: "")
|
|
||||||
|
|
||||||
return .init(
|
return .init(
|
||||||
type: type,
|
type: type,
|
||||||
intensity: intensity,
|
intensity: intensity,
|
||||||
|
magnitude: magnitude,
|
||||||
latitude: latitude,
|
latitude: latitude,
|
||||||
longitude: longitude,
|
longitude: longitude,
|
||||||
counter: counter,
|
counter: counter,
|
||||||
|
|||||||
@@ -21,13 +21,27 @@ class EQNReteSmartphone: NSObject {
|
|||||||
let top10kAvailable: Int
|
let top10kAvailable: Int
|
||||||
let top100kAvailable: Int
|
let top100kAvailable: Int
|
||||||
|
|
||||||
|
// MARK: - Class
|
||||||
|
|
||||||
|
// Sometimes the response returns a broken response, with all values to null.
|
||||||
|
// In order to avoid crashes due to ObjC-Swift bridging, we need to take a generic nullable object,
|
||||||
|
// and then cast to the expected type (a dictionary).
|
||||||
|
@objc static func from(response: Any?) -> EQNReteSmartphone? {
|
||||||
|
if let info = response as? [[String: Any]?] {
|
||||||
|
return .init(info: info)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Init
|
// MARK: - Init
|
||||||
|
|
||||||
@objc init(info: [[String: Any]]) {
|
private init(info: [[String: Any]?]) {
|
||||||
// merge array in a single dictionary
|
// merge array in a single dictionary
|
||||||
let allValues = info.reduce([:]) { (result, dictionary) -> [String: Any] in
|
let allValues = info
|
||||||
return result.merging(dictionary, uniquingKeysWith: { (_, new) in new })
|
.compactMap { $0 }
|
||||||
}
|
.reduce([:]) { (result, dictionary) -> [String: Any] in
|
||||||
|
return result.merging(dictionary, uniquingKeysWith: { (_, new) in new })
|
||||||
|
}
|
||||||
|
|
||||||
self.counterLastDayAlerts = allValues.integer(forKey: "eq", orDefault: 0)
|
self.counterLastDayAlerts = allValues.integer(forKey: "eq", orDefault: 0)
|
||||||
self.counterTotalAlerts = allValues.integer(forKey: "eq_p", orDefault: 0)
|
self.counterTotalAlerts = allValues.integer(forKey: "eq_p", orDefault: 0)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import Foundation
|
|||||||
case userFelt
|
case userFelt
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Sort: Int {
|
enum Sort: Int, CaseIterable {
|
||||||
case time
|
case time
|
||||||
case position
|
case position
|
||||||
case magnitude
|
case magnitude
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ class EQNSettingRealTimeAlert: NSObject {
|
|||||||
static let shared = EQNSettingRealTimeAlert()
|
static let shared = EQNSettingRealTimeAlert()
|
||||||
|
|
||||||
@objc var isAbilitato: Bool
|
@objc var isAbilitato: Bool
|
||||||
@objc var isCriticalAlertsEnabled: Bool
|
var isMildQuakeSoundDisabled: Bool
|
||||||
|
var isCriticalAlertsEnabled: Bool
|
||||||
|
|
||||||
@objc var sismiDaNotificare: String
|
var sismiDaNotificare: String
|
||||||
@objc var raggioSismiLievi: String
|
@objc var raggioSismiLievi: String
|
||||||
@objc var raggioSismiForti: String
|
var raggioSismiForti: String
|
||||||
|
|
||||||
private static let DefaultSismiDaNotificare = "0"
|
private static let DefaultSismiDaNotificare = "0"
|
||||||
private static let DefaultRaggioSismiLievi = "250"
|
private static let DefaultRaggioSismiLievi = "250"
|
||||||
@@ -38,6 +39,7 @@ class EQNSettingRealTimeAlert: NSObject {
|
|||||||
|
|
||||||
let sharedDefaults = UserDefaults.appGroup
|
let sharedDefaults = UserDefaults.appGroup
|
||||||
isCriticalAlertsEnabled = sharedDefaults?.bool(forKey: UserDefaults.AllertaSismicaCriticalAlerts) ?? false
|
isCriticalAlertsEnabled = sharedDefaults?.bool(forKey: UserDefaults.AllertaSismicaCriticalAlerts) ?? false
|
||||||
|
isMildQuakeSoundDisabled = sharedDefaults?.bool(forKey: UserDefaults.AllertaSismicaSuonoDisabilitatoSismaDebole) ?? true
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
@@ -50,12 +52,14 @@ class EQNSettingRealTimeAlert: NSObject {
|
|||||||
defaults.set(raggioSismiForti, forKey: UserDefaults.AllertaSismicaRaggioSismiForti)
|
defaults.set(raggioSismiForti, forKey: UserDefaults.AllertaSismicaRaggioSismiForti)
|
||||||
if let sharedDefaults = UserDefaults.appGroup {
|
if let sharedDefaults = UserDefaults.appGroup {
|
||||||
sharedDefaults.set(isCriticalAlertsEnabled, forKey: UserDefaults.AllertaSismicaCriticalAlerts)
|
sharedDefaults.set(isCriticalAlertsEnabled, forKey: UserDefaults.AllertaSismicaCriticalAlerts)
|
||||||
|
sharedDefaults.set(isMildQuakeSoundDisabled, forKey: UserDefaults.AllertaSismicaSuonoDisabilitatoSismaDebole)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc class func saveDefaultValues() {
|
@objc class func saveDefaultValues() {
|
||||||
shared.isAbilitato = true
|
shared.isAbilitato = true
|
||||||
shared.isCriticalAlertsEnabled = false
|
shared.isCriticalAlertsEnabled = false
|
||||||
|
shared.isMildQuakeSoundDisabled = true
|
||||||
shared.sismiDaNotificare = Self.DefaultSismiDaNotificare
|
shared.sismiDaNotificare = Self.DefaultSismiDaNotificare
|
||||||
shared.raggioSismiLievi = Self.DefaultRaggioSismiLievi
|
shared.raggioSismiLievi = Self.DefaultRaggioSismiLievi
|
||||||
shared.raggioSismiForti = Self.DefaultRaggioSismiForti
|
shared.raggioSismiForti = Self.DefaultRaggioSismiForti
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CWo-PE-Dqp">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CWo-PE-Dqp">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
@@ -26,12 +26,6 @@
|
|||||||
<action selector="collapseExpandTapped:" destination="tVM-DH-fmv" id="EnD-92-5ZX"/>
|
<action selector="collapseExpandTapped:" destination="tVM-DH-fmv" id="EnD-92-5ZX"/>
|
||||||
</connections>
|
</connections>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
<barButtonItem image="navbar-icon-filters" id="vOM-Np-CIk">
|
|
||||||
<connections>
|
|
||||||
<action selector="openFilterTapped:" destination="tVM-DH-fmv" id="76a-Bl-bCj"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
<barButtonItem image="navbar-icon-sort" id="LyU-KI-3Mb"/>
|
|
||||||
<barButtonItem image="navbar-icon-refresh" id="ZJh-jF-ILm">
|
<barButtonItem image="navbar-icon-refresh" id="ZJh-jF-ILm">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="refreshDataTapped:" destination="tVM-DH-fmv" id="qs5-jS-0Op"/>
|
<action selector="refreshDataTapped:" destination="tVM-DH-fmv" id="qs5-jS-0Op"/>
|
||||||
@@ -41,7 +35,6 @@
|
|||||||
</navigationItem>
|
</navigationItem>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="displayModeButton" destination="HTN-07-s5p" id="Lhc-Od-MvL"/>
|
<outlet property="displayModeButton" destination="HTN-07-s5p" id="Lhc-Od-MvL"/>
|
||||||
<outlet property="sortButton" destination="LyU-KI-3Mb" id="969-Zg-YBB"/>
|
|
||||||
<segue destination="6LP-zk-O1z" kind="presentation" identifier="ShowFilters" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="Nzu-iH-UgB"/>
|
<segue destination="6LP-zk-O1z" kind="presentation" identifier="ShowFilters" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="Nzu-iH-UgB"/>
|
||||||
<segue destination="Rfp-kt-2Kx" kind="presentation" identifier="ShowCardSettings" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="VWw-16-xGw"/>
|
<segue destination="Rfp-kt-2Kx" kind="presentation" identifier="ShowCardSettings" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="VWw-16-xGw"/>
|
||||||
</connections>
|
</connections>
|
||||||
@@ -59,7 +52,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="jl5-sK-UaA">
|
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="jl5-sK-UaA">
|
||||||
<rect key="frame" x="0.0" y="144" width="414" height="614"/>
|
<rect key="frame" x="0.0" y="192" width="414" height="532"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="fbo-Ug-IiE" id="meg-jS-D2z"/>
|
<outlet property="dataSource" destination="fbo-Ug-IiE" id="meg-jS-D2z"/>
|
||||||
@@ -67,7 +60,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4mK-no-RDk">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4mK-no-RDk">
|
||||||
<rect key="frame" x="0.0" y="758" width="414" height="55"/>
|
<rect key="frame" x="0.0" y="724" width="414" height="55"/>
|
||||||
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
|
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="55" id="1Dm-ex-6od"/>
|
<constraint firstAttribute="height" constant="55" id="1Dm-ex-6od"/>
|
||||||
@@ -276,17 +269,17 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<viewController storyboardIdentifier="EQNLogViewController" id="noK-2F-IZE" customClass="EQNLogViewController" sceneMemberID="viewController">
|
<viewController storyboardIdentifier="EQNLogViewController" id="noK-2F-IZE" customClass="EQNLogViewController" sceneMemberID="viewController">
|
||||||
<view key="view" contentMode="scaleToFill" id="6P7-SV-yrd">
|
<view key="view" contentMode="scaleToFill" id="6P7-SV-yrd">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="886"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="838"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="ija-iK-2hE">
|
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="ija-iK-2hE">
|
||||||
<rect key="frame" x="0.0" y="20" width="414" height="808"/>
|
<rect key="frame" x="0.0" y="20" width="414" height="760"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
</textView>
|
</textView>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g5C-Wg-DEu">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g5C-Wg-DEu">
|
||||||
<rect key="frame" x="16" y="836" width="382" height="30"/>
|
<rect key="frame" x="16" y="788" width="382" height="30"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="30" id="CFr-4Z-X1A"/>
|
<constraint firstAttribute="height" constant="30" id="CFr-4Z-X1A"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -404,7 +397,7 @@
|
|||||||
<tabBarItem key="tabBarItem" title="Settings" image="tabbar-icon-settings" id="5VO-yI-kw5"/>
|
<tabBarItem key="tabBarItem" title="Settings" image="tabbar-icon-settings" id="5VO-yI-kw5"/>
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="B9g-HM-VPb">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="B9g-HM-VPb">
|
||||||
<rect key="frame" x="0.0" y="48" width="414" height="96"/>
|
<rect key="frame" x="0.0" y="96" width="414" height="96"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -506,7 +499,7 @@
|
|||||||
<tabBarItem key="tabBarItem" title="Reports" image="tabbar-icon-reports" id="oaL-SG-Zpq"/>
|
<tabBarItem key="tabBarItem" title="Reports" image="tabbar-icon-reports" id="oaL-SG-Zpq"/>
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="xbw-SF-Eq7">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="xbw-SF-Eq7">
|
||||||
<rect key="frame" x="0.0" y="48" width="414" height="96"/>
|
<rect key="frame" x="0.0" y="96" width="414" height="96"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -525,7 +518,7 @@
|
|||||||
<tabBarItem key="tabBarItem" title="Alerts" image="tabbar-icon-alerts" id="aeo-GH-qCD"/>
|
<tabBarItem key="tabBarItem" title="Alerts" image="tabbar-icon-alerts" id="aeo-GH-qCD"/>
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="bk1-MS-moG">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="bk1-MS-moG">
|
||||||
<rect key="frame" x="0.0" y="48" width="414" height="96"/>
|
<rect key="frame" x="0.0" y="96" width="414" height="96"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -544,7 +537,7 @@
|
|||||||
<tabBarItem key="tabBarItem" title="Seismic Networks" image="tabbar-icon-networks" id="eed-sY-0Ua"/>
|
<tabBarItem key="tabBarItem" title="Seismic Networks" image="tabbar-icon-networks" id="eed-sY-0Ua"/>
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="LRX-7t-Fk4">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="LRX-7t-Fk4">
|
||||||
<rect key="frame" x="0.0" y="48" width="414" height="96"/>
|
<rect key="frame" x="0.0" y="96" width="414" height="96"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -565,7 +558,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="200" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="a35-sg-TCr">
|
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="200" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="a35-sg-TCr">
|
||||||
<rect key="frame" x="0.0" y="144" width="414" height="614"/>
|
<rect key="frame" x="0.0" y="192" width="414" height="532"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="syj-UE-OWc" id="Vah-TU-YfT"/>
|
<outlet property="dataSource" destination="syj-UE-OWc" id="Vah-TU-YfT"/>
|
||||||
@@ -573,7 +566,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PyX-yA-DXv">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PyX-yA-DXv">
|
||||||
<rect key="frame" x="0.0" y="758" width="414" height="55"/>
|
<rect key="frame" x="0.0" y="724" width="414" height="55"/>
|
||||||
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
|
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="55" id="kmt-E8-s2w"/>
|
<constraint firstAttribute="height" constant="55" id="kmt-E8-s2w"/>
|
||||||
@@ -623,9 +616,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<image name="1.square" catalog="system" width="128" height="114"/>
|
<image name="1.square" catalog="system" width="128" height="114"/>
|
||||||
<image name="navbar-icon-arrow-collapse" width="24" height="24"/>
|
<image name="navbar-icon-arrow-collapse" width="24" height="24"/>
|
||||||
<image name="navbar-icon-filters" width="24" height="24"/>
|
|
||||||
<image name="navbar-icon-refresh" width="24" height="24"/>
|
<image name="navbar-icon-refresh" width="24" height="24"/>
|
||||||
<image name="navbar-icon-sort" width="24" height="24"/>
|
|
||||||
<image name="tabbar-icon-alerts" width="25" height="25"/>
|
<image name="tabbar-icon-alerts" width="25" height="25"/>
|
||||||
<image name="tabbar-icon-networks" width="25" height="25"/>
|
<image name="tabbar-icon-networks" width="25" height="25"/>
|
||||||
<image name="tabbar-icon-reports" width="25" height="25"/>
|
<image name="tabbar-icon-reports" width="25" height="25"/>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
class EQNBlurredCloseButton: UIButton {
|
class EQNBlurredCloseButton: UIButton {
|
||||||
@@ -18,6 +19,12 @@ class EQNBlurredCloseButton: UIButton {
|
|||||||
setupUI()
|
setupUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func setupUI() {
|
private func setupUI() {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class EQNSeismicAnnotationView: MKAnnotationView {
|
|||||||
private static let FullViewHeight: CGFloat = MagnitudeHeight + 2*LabelHeight
|
private static let FullViewHeight: CGFloat = MagnitudeHeight + 2*LabelHeight
|
||||||
private static let FullViewWidth: CGFloat = 100.0
|
private static let FullViewWidth: CGFloat = 100.0
|
||||||
private static let SmallViewHeight: CGFloat = MagnitudeHeight
|
private static let SmallViewHeight: CGFloat = MagnitudeHeight
|
||||||
private static let SmallViewWidth: CGFloat = 100.0
|
private static let SmallViewWidth: CGFloat = 80.0
|
||||||
static let CircleViewHeight: CGFloat = 20.0
|
static let CircleViewHeight: CGFloat = 20.0
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
@@ -80,7 +80,7 @@ class EQNSeismicAnnotationView: MKAnnotationView {
|
|||||||
|
|
||||||
private lazy var magnitudeLabel: UILabel = {
|
private lazy var magnitudeLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = UIFont.systemFont(ofSize: 12, weight: .bold)
|
label.font = UIFont.systemFont(ofSize: 11, weight: .bold)
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
label.textColor = AppTheme.Colors.lightBlue
|
label.textColor = AppTheme.Colors.lightBlue
|
||||||
return label
|
return label
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "ألغي";
|
"status_cancel" = "ألغي";
|
||||||
"options_alarms" = "تنبيه بوقت فعلي";
|
"options_alarms" = "تنبيه بوقت فعلي";
|
||||||
"options_notification_enable_alarm" = "قم بتفعيل الإنذار عند اكتشاف زلزال في الوقت الفعلي بواسطة شبكة الهواتف الذكية";
|
"options_notification_enable_alarm" = "قم بتفعيل الإنذار عند اكتشاف زلزال في الوقت الفعلي بواسطة شبكة الهواتف الذكية";
|
||||||
|
"options_notification_disable_sound" = "قم بتعطيل صوت المنبه إذا كان الاهتزاز في موقعك خفيفًا";
|
||||||
"options_notification_official" = "إخطارات الشبكة الزلزالية";
|
"options_notification_official" = "إخطارات الشبكة الزلزالية";
|
||||||
"options_notification_enable_official" = "تلقي إشعارات بشأن الزلازل التي اكتشفتها شبكات الزلازل الوطنية والدولية";
|
"options_notification_enable_official" = "تلقي إشعارات بشأن الزلازل التي اكتشفتها شبكات الزلازل الوطنية والدولية";
|
||||||
"options_official_type" = "مرشح الإشعارات";
|
"options_official_type" = "مرشح الإشعارات";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "حل المشكلة";
|
"permission_location_no_background_solve" = "حل المشكلة";
|
||||||
"main_share_app" = "شارك التطبيق";
|
"main_share_app" = "شارك التطبيق";
|
||||||
"main_vote" = "قيّم التطبيق";
|
"main_vote" = "قيّم التطبيق";
|
||||||
"main_twitter_see" = "التبيين في تويتر";
|
"main_twitter_see" = "عرض على X";
|
||||||
"map_smartphone_magnitude" = "سيتم تقدير قوة الزلزال بواسطة الشبكة الزلزالية الوطنية وسيظهر في علامة تبويب الشبكات الزلزالية في التطبيق";
|
"map_smartphone_magnitude" = "سيتم تقدير قوة الزلزال بواسطة الشبكة الزلزالية الوطنية وسيظهر في علامة تبويب الشبكات الزلزالية في التطبيق";
|
||||||
"main_alerttest" = "تنبيه اختياري";
|
"main_alerttest" = "تنبيه اختياري";
|
||||||
"main_simulator" = "محاكي";
|
"main_simulator" = "محاكي";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "شهريا";
|
"subscription_plan_monthly" = "شهريا";
|
||||||
"subscription_plan_yearly" = "سنوي";
|
"subscription_plan_yearly" = "سنوي";
|
||||||
"subscription_plan_perpetual" = "حياة";
|
"subscription_plan_perpetual" = "حياة";
|
||||||
|
"tap_to_open" = "انقر للتكبير";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Διαγραφή";
|
"status_cancel" = "Διαγραφή";
|
||||||
"options_alarms" = "Ειδοποίηση σε πραγματικό χρόνο";
|
"options_alarms" = "Ειδοποίηση σε πραγματικό χρόνο";
|
||||||
"options_notification_enable_alarm" = "Να ακούγεται συναγερμός όταν ανιχνεύεται σεισμός σε πραγματικό χρόνο από το δίκτυο smartphone";
|
"options_notification_enable_alarm" = "Να ακούγεται συναγερμός όταν ανιχνεύεται σεισμός σε πραγματικό χρόνο από το δίκτυο smartphone";
|
||||||
|
"options_notification_disable_sound" = "Απενεργοποιήστε τον ήχο συναγερμού εάν το κούνημα στην τοποθεσία σας είναι ήπιο";
|
||||||
"options_notification_official" = "Κοινοποιήσεις σεισμικών δικτύων";
|
"options_notification_official" = "Κοινοποιήσεις σεισμικών δικτύων";
|
||||||
"options_notification_enable_official" = "Λήψη ειδοποιήσεων για τους σεισμούς που εντοπίζονται από τα εθνικά και διεθνή σεισμικά δίκτυα";
|
"options_notification_enable_official" = "Λήψη ειδοποιήσεων για τους σεισμούς που εντοπίζονται από τα εθνικά και διεθνή σεισμικά δίκτυα";
|
||||||
"options_official_type" = "Φίλτρο ειδοποιήσεων";
|
"options_official_type" = "Φίλτρο ειδοποιήσεων";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Διόρθωση";
|
"permission_location_no_background_solve" = "Διόρθωση";
|
||||||
"main_share_app" = "Μοιράσου";
|
"main_share_app" = "Μοιράσου";
|
||||||
"main_vote" = "Ψήφισε την Εφαρμογή";
|
"main_vote" = "Ψήφισε την Εφαρμογή";
|
||||||
"main_twitter_see" = "Twitter";
|
"main_twitter_see" = "X";
|
||||||
"map_smartphone_magnitude" = "Το μέγεθος θα εκτιμηθεί από το εθνικό σεισμικό δίκτυο και θα εμφανιστεί στην οθόνη Σεισμικών Δικτύων της εφαρμογής";
|
"map_smartphone_magnitude" = "Το μέγεθος θα εκτιμηθεί από το εθνικό σεισμικό δίκτυο και θα εμφανιστεί στην οθόνη Σεισμικών Δικτύων της εφαρμογής";
|
||||||
"main_alerttest" = "Τεστ ειδοποίησης";
|
"main_alerttest" = "Τεστ ειδοποίησης";
|
||||||
"main_simulator" = "Προσομοιωτής";
|
"main_simulator" = "Προσομοιωτής";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Μηνιαίο";
|
"subscription_plan_monthly" = "Μηνιαίο";
|
||||||
"subscription_plan_yearly" = "Ετήσιο";
|
"subscription_plan_yearly" = "Ετήσιο";
|
||||||
"subscription_plan_perpetual" = "Διάρκεια Ζωής";
|
"subscription_plan_perpetual" = "Διάρκεια Ζωής";
|
||||||
|
"tap_to_open" = "Πατήστε για μεγέθυνση";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Cancel";
|
"status_cancel" = "Cancel";
|
||||||
"options_alarms" = "Real time alert";
|
"options_alarms" = "Real time alert";
|
||||||
"options_notification_enable_alarm" = "Activate an alarm when a quake is detected in real time by the network of smartphones";
|
"options_notification_enable_alarm" = "Activate an alarm when a quake is detected in real time by the network of smartphones";
|
||||||
|
"options_notification_disable_sound" = "Disable the alarm sound if the shaking at your location is mild";
|
||||||
"options_notification_official" = "Seismic network notifications";
|
"options_notification_official" = "Seismic network notifications";
|
||||||
"options_notification_enable_official" = "Receive notifications for the earthquakes detected by the national and international seismic networks";
|
"options_notification_enable_official" = "Receive notifications for the earthquakes detected by the national and international seismic networks";
|
||||||
"options_official_type" = "Notification filter";
|
"options_official_type" = "Notification filter";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Solve";
|
"permission_location_no_background_solve" = "Solve";
|
||||||
"main_share_app" = "Share App";
|
"main_share_app" = "Share App";
|
||||||
"main_vote" = "Rate the App";
|
"main_vote" = "Rate the App";
|
||||||
"main_twitter_see" = "View on Twitter";
|
"main_twitter_see" = "View on X";
|
||||||
"map_smartphone_magnitude" = "The magnitude will be estimated by the national seismic network and it will appear in the Seismic Networks tab of the app";
|
"map_smartphone_magnitude" = "The magnitude will be estimated by the national seismic network and it will appear in the Seismic Networks tab of the app";
|
||||||
"main_alerttest" = "Test alert";
|
"main_alerttest" = "Test alert";
|
||||||
"main_simulator" = "Simulator";
|
"main_simulator" = "Simulator";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Monthly";
|
"subscription_plan_monthly" = "Monthly";
|
||||||
"subscription_plan_yearly" = "Annual";
|
"subscription_plan_yearly" = "Annual";
|
||||||
"subscription_plan_perpetual" = "Lifetime";
|
"subscription_plan_perpetual" = "Lifetime";
|
||||||
|
"tap_to_open" = "Tap to open";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Clara";
|
"status_cancel" = "Clara";
|
||||||
"options_alarms" = "Alerta en tiempo real";
|
"options_alarms" = "Alerta en tiempo real";
|
||||||
"options_notification_enable_alarm" = "Suena una alarma cuando se detecta un sismo en tiempo real por la red de los teléfonos inteligentes";
|
"options_notification_enable_alarm" = "Suena una alarma cuando se detecta un sismo en tiempo real por la red de los teléfonos inteligentes";
|
||||||
|
"options_notification_disable_sound" = "Desactive el sonido de la alarma si el sismo en tu ubicación es leve";
|
||||||
"options_notification_official" = "Notificaciones redes sísmicas";
|
"options_notification_official" = "Notificaciones redes sísmicas";
|
||||||
"options_notification_enable_official" = "Recibe las notificaciones de los sismos detectados por las redes sísmicas nacionales e internacionales";
|
"options_notification_enable_official" = "Recibe las notificaciones de los sismos detectados por las redes sísmicas nacionales e internacionales";
|
||||||
"options_official_type" = "Filtro de notificaciones";
|
"options_official_type" = "Filtro de notificaciones";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Corregir";
|
"permission_location_no_background_solve" = "Corregir";
|
||||||
"main_share_app" = "Comparte App";
|
"main_share_app" = "Comparte App";
|
||||||
"main_vote" = "Vota la app";
|
"main_vote" = "Vota la app";
|
||||||
"main_twitter_see" = "Ver en Twitter";
|
"main_twitter_see" = "Ver en X";
|
||||||
"map_smartphone_magnitude" = "La magnitud será comunicada por la red sísmica nacional y aparecerá en la sección de Redes Sísmicas de la app";
|
"map_smartphone_magnitude" = "La magnitud será comunicada por la red sísmica nacional y aparecerá en la sección de Redes Sísmicas de la app";
|
||||||
"main_alerttest" = "Prueba alerta";
|
"main_alerttest" = "Prueba alerta";
|
||||||
"main_simulator" = "Simulador";
|
"main_simulator" = "Simulador";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Mensual";
|
"subscription_plan_monthly" = "Mensual";
|
||||||
"subscription_plan_yearly" = "Anual";
|
"subscription_plan_yearly" = "Anual";
|
||||||
"subscription_plan_perpetual" = "Para siempre";
|
"subscription_plan_perpetual" = "Para siempre";
|
||||||
|
"tap_to_open" = "Toque para ampliar";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Supprimer";
|
"status_cancel" = "Supprimer";
|
||||||
"options_alarms" = "Alerte en temps réel";
|
"options_alarms" = "Alerte en temps réel";
|
||||||
"options_notification_enable_alarm" = "Une alarme retentit lorsqu'un séisme est détecté par le réseau des smartphones";
|
"options_notification_enable_alarm" = "Une alarme retentit lorsqu'un séisme est détecté par le réseau des smartphones";
|
||||||
|
"options_notification_disable_sound" = "Désactivez le son de l'alarme si les secousses à votre emplacement sont légères";
|
||||||
"options_notification_official" = "Notifications de réseaux sismiquex";
|
"options_notification_official" = "Notifications de réseaux sismiquex";
|
||||||
"options_notification_enable_official" = "Recevez les notifications des séismes détectés par les réseaux sismiques nationaux et internationaux";
|
"options_notification_enable_official" = "Recevez les notifications des séismes détectés par les réseaux sismiques nationaux et internationaux";
|
||||||
"options_official_type" = "Filtre de notificatio";
|
"options_official_type" = "Filtre de notificatio";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Corriger";
|
"permission_location_no_background_solve" = "Corriger";
|
||||||
"main_share_app" = "Partager l'App";
|
"main_share_app" = "Partager l'App";
|
||||||
"main_vote" = "Voter l'App";
|
"main_vote" = "Voter l'App";
|
||||||
"main_twitter_see" = "Voir sur Twitter";
|
"main_twitter_see" = "Voir sur X";
|
||||||
"map_smartphone_magnitude" = "La magnitude sera estimée par le réseau sismique national et s'affichera dans la page d'écran Réseaux Sismiques de l'app";
|
"map_smartphone_magnitude" = "La magnitude sera estimée par le réseau sismique national et s'affichera dans la page d'écran Réseaux Sismiques de l'app";
|
||||||
"main_alerttest" = "Test alerte";
|
"main_alerttest" = "Test alerte";
|
||||||
"main_simulator" = "Simulateur";
|
"main_simulator" = "Simulateur";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Mensuel";
|
"subscription_plan_monthly" = "Mensuel";
|
||||||
"subscription_plan_yearly" = "Annuel";
|
"subscription_plan_yearly" = "Annuel";
|
||||||
"subscription_plan_perpetual" = "Pour toujours";
|
"subscription_plan_perpetual" = "Pour toujours";
|
||||||
|
"tap_to_open" = "Appuyez pour agrandir";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Poništi";
|
"status_cancel" = "Poništi";
|
||||||
"options_alarms" = "Upozorenje u stvarnom vremenu";
|
"options_alarms" = "Upozorenje u stvarnom vremenu";
|
||||||
"options_notification_enable_alarm" = "Aktiviraj alarm kada mreža pametnih telefona u stvarnom vremenu otkrije potres";
|
"options_notification_enable_alarm" = "Aktiviraj alarm kada mreža pametnih telefona u stvarnom vremenu otkrije potres";
|
||||||
|
"options_notification_disable_sound" = "Onemogućite zvuk alarma ako je podrhtavanje na vašoj lokaciji blago";
|
||||||
"options_notification_official" = "Obavijesti o seizmološkim mrežama";
|
"options_notification_official" = "Obavijesti o seizmološkim mrežama";
|
||||||
"options_notification_enable_official" = "Primajte obavijesti o potresima koje su otkrile nacionalne i međunarodne seizmičke mreže";
|
"options_notification_enable_official" = "Primajte obavijesti o potresima koje su otkrile nacionalne i međunarodne seizmičke mreže";
|
||||||
"options_official_type" = "Filter obavijesti";
|
"options_official_type" = "Filter obavijesti";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Mjesečno";
|
"subscription_plan_monthly" = "Mjesečno";
|
||||||
"subscription_plan_yearly" = "Godišnji";
|
"subscription_plan_yearly" = "Godišnji";
|
||||||
"subscription_plan_perpetual" = "Zauvijek";
|
"subscription_plan_perpetual" = "Zauvijek";
|
||||||
|
"tap_to_open" = "Dodirnite za uvećanje";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Batal";
|
"status_cancel" = "Batal";
|
||||||
"options_alarms" = "Peringatan real time";
|
"options_alarms" = "Peringatan real time";
|
||||||
"options_notification_enable_alarm" = "Nyalakan alarm saat gempa terdeteksi secara real time oleh jaringan smartphone";
|
"options_notification_enable_alarm" = "Nyalakan alarm saat gempa terdeteksi secara real time oleh jaringan smartphone";
|
||||||
|
"options_notification_disable_sound" = "Nonaktifkan suara alarm jika guncangan di lokasi Anda ringan";
|
||||||
"options_notification_official" = "Pemberitahuan jaringan seismik";
|
"options_notification_official" = "Pemberitahuan jaringan seismik";
|
||||||
"options_notification_enable_official" = "Terima pemberitahuan untuk gempa bumi yang terdeteksi oleh jaringan seismik nasional dan internasional";
|
"options_notification_enable_official" = "Terima pemberitahuan untuk gempa bumi yang terdeteksi oleh jaringan seismik nasional dan internasional";
|
||||||
"options_official_type" = "Filter notifikasi";
|
"options_official_type" = "Filter notifikasi";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Atasi";
|
"permission_location_no_background_solve" = "Atasi";
|
||||||
"main_share_app" = "Bagikan Aplikasi";
|
"main_share_app" = "Bagikan Aplikasi";
|
||||||
"main_vote" = "Beri Rating untuk Aplikasi";
|
"main_vote" = "Beri Rating untuk Aplikasi";
|
||||||
"main_twitter_see" = "Lihat di Twitter";
|
"main_twitter_see" = "Lihat di X";
|
||||||
"map_smartphone_magnitude" = "Magnitudo akan diperkirakan oleh jaringan seismik nasional dan akan muncul di tab Jaringan Seismik pada aplikasi";
|
"map_smartphone_magnitude" = "Magnitudo akan diperkirakan oleh jaringan seismik nasional dan akan muncul di tab Jaringan Seismik pada aplikasi";
|
||||||
"main_alerttest" = "Tes peringatan";
|
"main_alerttest" = "Tes peringatan";
|
||||||
"main_simulator" = "Simulator";
|
"main_simulator" = "Simulator";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Bulanan";
|
"subscription_plan_monthly" = "Bulanan";
|
||||||
"subscription_plan_yearly" = "Tahunan";
|
"subscription_plan_yearly" = "Tahunan";
|
||||||
"subscription_plan_perpetual" = "Selamanya";
|
"subscription_plan_perpetual" = "Selamanya";
|
||||||
|
"tap_to_open" = "Ketuk untuk memperbesar";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "Cancella";
|
"status_cancel" = "Cancella";
|
||||||
"options_alarms" = "Allerta in tempo reale";
|
"options_alarms" = "Allerta in tempo reale";
|
||||||
"options_notification_enable_alarm" = "Attiva un allarme quando un sisma è rilevato dalla rete smartphone";
|
"options_notification_enable_alarm" = "Attiva un allarme quando un sisma è rilevato dalla rete smartphone";
|
||||||
|
"options_notification_disable_sound" = "Disabilita il suono di allerta se l'intensità del sisma nella tua zona è debole";
|
||||||
"options_notification_official" = "Notifiche da reti sismiche";
|
"options_notification_official" = "Notifiche da reti sismiche";
|
||||||
"options_notification_enable_official" = "Ricevi notifiche per i sismi rilevati dalle reti sismiche nazionali e internazionali";
|
"options_notification_enable_official" = "Ricevi notifiche per i sismi rilevati dalle reti sismiche nazionali e internazionali";
|
||||||
"options_official_type" = "Filtro notifiche";
|
"options_official_type" = "Filtro notifiche";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Correggi";
|
"permission_location_no_background_solve" = "Correggi";
|
||||||
"main_share_app" = "Condividi App";
|
"main_share_app" = "Condividi App";
|
||||||
"main_vote" = "Vota l'App";
|
"main_vote" = "Vota l'App";
|
||||||
"main_twitter_see" = "Vedi in Twitter";
|
"main_twitter_see" = "Vedi in X";
|
||||||
"map_smartphone_magnitude" = "La magnitudo sarà comunicata dalla rete sismica nazionale e comparirà nella sezione Reti Sismiche dell'app";
|
"map_smartphone_magnitude" = "La magnitudo sarà comunicata dalla rete sismica nazionale e comparirà nella sezione Reti Sismiche dell'app";
|
||||||
"main_alerttest" = "Test Allerta";
|
"main_alerttest" = "Test Allerta";
|
||||||
"main_simulator" = "Simulatore";
|
"main_simulator" = "Simulatore";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Mensile";
|
"subscription_plan_monthly" = "Mensile";
|
||||||
"subscription_plan_yearly" = "Annuale";
|
"subscription_plan_yearly" = "Annuale";
|
||||||
"subscription_plan_perpetual" = "A vita";
|
"subscription_plan_perpetual" = "A vita";
|
||||||
|
"tap_to_open" = "Tocca per aprire";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"status_cancel" = "İptal et";
|
"status_cancel" = "İptal et";
|
||||||
"options_alarms" = "Gerçek zamanlı uyarı";
|
"options_alarms" = "Gerçek zamanlı uyarı";
|
||||||
"options_notification_enable_alarm" = "Bir deprem akıllı telefon ağı tarafından gerçek zamanlı olarak tespit edildiğinde bir alarm çal";
|
"options_notification_enable_alarm" = "Bir deprem akıllı telefon ağı tarafından gerçek zamanlı olarak tespit edildiğinde bir alarm çal";
|
||||||
|
"options_notification_disable_sound" = "Bulunduğunuz yerdeki sarsıntı hafifse alarm sesini devre dışı bırakın";
|
||||||
"options_notification_official" = "Sismik ağ bildirimleri";
|
"options_notification_official" = "Sismik ağ bildirimleri";
|
||||||
"options_notification_enable_official" = "Ulusal ve uluslararası sismik ağlar tarafından tespit edilen depremler için bildirim alın";
|
"options_notification_enable_official" = "Ulusal ve uluslararası sismik ağlar tarafından tespit edilen depremler için bildirim alın";
|
||||||
"options_official_type" = "Bildirim filtresi";
|
"options_official_type" = "Bildirim filtresi";
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
"permission_location_no_background_solve" = "Çözün";
|
"permission_location_no_background_solve" = "Çözün";
|
||||||
"main_share_app" = "Uygul. Paylaş";
|
"main_share_app" = "Uygul. Paylaş";
|
||||||
"main_vote" = "Uygulamayı oyla";
|
"main_vote" = "Uygulamayı oyla";
|
||||||
"main_twitter_see" = "Twitter";
|
"main_twitter_see" = "X";
|
||||||
"map_smartphone_magnitude" = "Büyüklük ulusal sismik ağ tarafından tahmin edilecek ve uygulamanın Sismik Ağlar sekmesinde görünecektir.";
|
"map_smartphone_magnitude" = "Büyüklük ulusal sismik ağ tarafından tahmin edilecek ve uygulamanın Sismik Ağlar sekmesinde görünecektir.";
|
||||||
"main_alerttest" = "Test uyarısı";
|
"main_alerttest" = "Test uyarısı";
|
||||||
"main_simulator" = "Simülatör";
|
"main_simulator" = "Simülatör";
|
||||||
@@ -235,3 +236,4 @@
|
|||||||
"subscription_plan_monthly" = "Aylık";
|
"subscription_plan_monthly" = "Aylık";
|
||||||
"subscription_plan_yearly" = "Yıllık";
|
"subscription_plan_yearly" = "Yıllık";
|
||||||
"subscription_plan_perpetual" = "Sonsuza kadar";
|
"subscription_plan_perpetual" = "Sonsuza kadar";
|
||||||
|
"tap_to_open" = "Büyütmek için dokunun";
|
||||||
|
|||||||
Reference in New Issue
Block a user