Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95a214403b | |||
| a7db3c6fa1 | |||
| 4805c79ed6 | |||
| c6ec20e180 | |||
| f6dfd4a761 | |||
| 0212d0a15f | |||
| 3176bde5ed | |||
| dfdbbd0ed4 | |||
| e9986e0fe1 | |||
| beb264f95e | |||
| 217b5edbcf | |||
| e13f95aa5d | |||
| fc5bdbcc92 | |||
| d0ee637449 | |||
| 66e9d7035e | |||
| 7db48e381f | |||
| f9bdb84ad9 | |||
| bee18f6407 | |||
| 96f3a44db4 | |||
| e394259f24 | |||
| 3b53350969 | |||
| f3c3c19e39 | |||
| 8404d72d8f | |||
| a3b0499ed3 | |||
| d923b37fbd | |||
| 282803cf98 | |||
| 039e7b82a1 | |||
| b098caf2ef | |||
| 73caf9647c | |||
| 8700e200f9 | |||
| e99845ff1b | |||
| a0161e8f4c | |||
| 1b9944a7ca | |||
| 4c00e4ef6a | |||
| 63592e6cfb | |||
| 2877dff23c | |||
| f2386a1abb | |||
| 5e4a500f03 | |||
| 2b8f2db7c5 | |||
| 11d994696d | |||
| cd6e20c1b2 | |||
| af5371571c | |||
| 6291b22df0 | |||
| 2a7cfd3079 | |||
| cae5fee992 | |||
| 53b8c0fab4 | |||
| 8751d3c8f2 | |||
| 2d333f993b | |||
| 22d421f1cc | |||
| cec8b39fc7 | |||
| 5ceaa4a8be | |||
| 94bdb9dbe1 | |||
| ee1b762032 |
@@ -1,5 +1,36 @@
|
||||
# Changelog
|
||||
|
||||
## Versione 5.3
|
||||
|
||||
- Rivista gestione registrazione utente
|
||||
- Modifica in segnalazioni utente
|
||||
- Allineata mappa segnalazioni utente ad Android
|
||||
|
||||
## Versione 5.2.1
|
||||
|
||||
- Disattivata schermata di debug
|
||||
|
||||
## Versione 5.2
|
||||
|
||||
- Nuova schermata per allerta in tempo reale
|
||||
|
||||
## Versione 5.1
|
||||
|
||||
### Build (91)
|
||||
- Corretto problema con selezioni reti EMSC
|
||||
|
||||
### Build (90)
|
||||
- Rimozione notifiche dello stesso tipo
|
||||
|
||||
## Versione 5.0.3
|
||||
|
||||
### Build (89)
|
||||
- Corretto problema con ultima posizione non salvata in app
|
||||
- Forzato aggiornamento Firebase
|
||||
- Corretti metodi deprecati in salvataggio dati
|
||||
- Corretti comportamento filtri con iOS 15
|
||||
- Slider con valori a step
|
||||
|
||||
## Versione 5.0.2
|
||||
|
||||
### Build (88)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"magnitude_range" : "0",
|
||||
"provider" : "SGC",
|
||||
"google.c.a.e" : "1",
|
||||
"google.c.fid" : "d3PS1dEvrUA-tmLLpl5E5f",
|
||||
"preliminary" : "0",
|
||||
"longitude" : "-75.5157",
|
||||
"gcm.message_id" : "1668682445010677",
|
||||
"latitude" : "4.35306",
|
||||
"type" : "official",
|
||||
"google.c.sender.id" : "899482329945",
|
||||
"difference" : "6",
|
||||
"data" : "2022-11-17 11:48:00",
|
||||
"depth" : "26",
|
||||
"aps" : {
|
||||
"content-available" : 1,
|
||||
"alert" : {
|
||||
"loc-key" : "Sisma rilevato a",
|
||||
"title-loc-key" : "Segnalazione da rete sismica",
|
||||
"loc-args" : [
|
||||
"Cajamarca - Tolima, Colombia - M2.2"
|
||||
]
|
||||
},
|
||||
"mutable-content" : 1,
|
||||
"sound" : "default"
|
||||
},
|
||||
"magnitude" : "2.2",
|
||||
"magnitude_type" : "M",
|
||||
"place" : "Cajamarca - Tolima, Colombia",
|
||||
"pop100" : "6622"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"Simulator Target Bundle": "com.finazzi.distquake",
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"2 km da Foligno"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
},
|
||||
"category": "notifica_con_mappa",
|
||||
"content-available": 1,
|
||||
"mutable-content": 1,
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2022-06-22 19:12:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "45.64664",
|
||||
"detection_longitude": "9.188540",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"magnitude": 20,
|
||||
"latitude": "42.958",
|
||||
"location": "2 km da Foligno",
|
||||
"longitude": "12.702",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "manual",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"15 χλμ από το Αίγιο"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,20 +14,21 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:34:50",
|
||||
"datetime": "2022-06-23 10:10:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "37.983810",
|
||||
"detection_longitude": "23.727539",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "37.683810",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "23.327539",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "38.19",
|
||||
"location": "15 χλμ από το Αίγιο",
|
||||
"longitude": "22.26",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"14 km from California City"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-16 12:41:20",
|
||||
"datetime": "2022-06-23 07:55:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "37.3229978",
|
||||
"detection_longitude": "-122.0321823",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "37.9229978",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-121.0321823",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "35.15",
|
||||
"location": "14 km from California City",
|
||||
"longitude": "-117.78",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"5 km de Las Cujas"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 20:39:00",
|
||||
"datetime": "2022-06-23 10:19:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "-34.603722",
|
||||
"detection_longitude": "-58.381592",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "-34.103722",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-58.781592",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "-32.57",
|
||||
"location": "5 km de Las Cujas",
|
||||
"longitude": "-71.46",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"15 km de Dieppe"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:37:40",
|
||||
"datetime": "2022-06-23 10:07:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "48.856614",
|
||||
"detection_longitude": "2.8522219",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "48.456614",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "2.3522219",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "49.77",
|
||||
"location": "15 km de Dieppe",
|
||||
"longitude": "1.05",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"5 km od Novog"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:39:50",
|
||||
"datetime": "2022-06-23 10:02:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "45.813177",
|
||||
"detection_longitude": "15.977048",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "45.413177",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "15.677048",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "45.09",
|
||||
"location": "5 km od Novog",
|
||||
"longitude": "14.87",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"35 km dari Sindanbarang"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:42:40",
|
||||
"datetime": "2022-06-23 10:13:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "-2.548926",
|
||||
"detection_longitude": "118.0148634",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "-2.948926",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "118.6148634",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "-7.38",
|
||||
"location": "35 km dari Sindanbarang",
|
||||
"longitude": "106.83",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"2 km da Foligno"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 20:32:20",
|
||||
"datetime": "2022-06-22 19:12:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "45.64664",
|
||||
"detection_longitude": "9.188540",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "45.164664",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "9.788540",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "42.958",
|
||||
"location": "2 km da Foligno",
|
||||
"longitude": "12.702",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"45 km de Puebla"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,19 +14,20 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-16 12:39:40",
|
||||
"datetime": "2022-06-23 10:16:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "19.432608",
|
||||
"detection_longitude": "-99.133209",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "19.932608",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-98.033209",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "18.72",
|
||||
"location": "45 km de Puebla",
|
||||
"longitude": "-97.90",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"aps": {
|
||||
"alert": {
|
||||
"loc-args": [
|
||||
"150 km (Test)"
|
||||
"Bandırma'ya 25 km"
|
||||
],
|
||||
"loc-key": "Rilevato sisma forte a",
|
||||
"title-loc-key": "Allerta sismica in tempo reale"
|
||||
@@ -14,20 +14,21 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:44:30",
|
||||
"datetime": "2022-06-23 10:22:00",
|
||||
"delay": 4,
|
||||
"detection_latitude": "41.008238",
|
||||
"detection_longitude": "28.978359",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "41.608238",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "28.678359",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
"latitude": "40.33",
|
||||
"location": "Bandırma'ya 25 km",
|
||||
"longitude": "27.66",
|
||||
"peak": "0.4",
|
||||
"randcode": 100,
|
||||
"test": 0,
|
||||
"type": "eqn",
|
||||
"wave_speed": "4.7",
|
||||
"critical": true
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.mapView registerClass:[EQNCustomAnnotationView class] forAnnotationViewWithReuseIdentifier:EQNCustomAnnotationView.SingleLineIdentifier];
|
||||
[self.mapView registerClass:[EQNCustomAnnotationView class] forAnnotationViewWithReuseIdentifier:EQNCustomAnnotationView.SmallIdentifier];
|
||||
}
|
||||
|
||||
- (void)didReceiveNotification:(UNNotification *)notification
|
||||
@@ -67,9 +68,8 @@
|
||||
[self.mapView addAnnotation:annotation];
|
||||
|
||||
} else if ([userInfo[@"type"] isEqualToString:@"manual"]){
|
||||
EQNMapAnnotationUserReport *annotation = [[EQNMapAnnotationUserReport alloc] initWithTitle:@""
|
||||
coordinate:coordinate.coordinate
|
||||
magnitude:[userInfo[@"magnitudo"] intValue]];
|
||||
EQNMapAnnotationUserReport *annotation = [[EQNMapAnnotationUserReport alloc] initWithMagnitude:[userInfo[@"magnitude"] intValue]
|
||||
coordinate:coordinate.coordinate];
|
||||
[self.mapView addAnnotation:annotation];
|
||||
}
|
||||
|
||||
@@ -118,9 +118,9 @@
|
||||
} else if ([annotation isKindOfClass:[EQNMapAnnotationUserReport class]]) {
|
||||
EQNMapAnnotationUserReport *report = (EQNMapAnnotationUserReport *)annotation;
|
||||
|
||||
EQNCustomAnnotationView *annotationView = (EQNCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:EQNCustomAnnotationView.SingleLineIdentifier];
|
||||
EQNCustomAnnotationView *annotationView = (EQNCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:EQNCustomAnnotationView.SmallIdentifier];
|
||||
annotationView.image = report.image;
|
||||
annotationView.title = report.title;
|
||||
annotationView.title = report.timeDifference;
|
||||
return annotationView;
|
||||
}
|
||||
return nil;
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "NotificationService.h"
|
||||
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// NotificationService+Extension.swift
|
||||
// EQNNotificationService
|
||||
//
|
||||
// Created by Andrea Busi on 28/05/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
|
||||
extension NotificationService {
|
||||
|
||||
@objc(removeNotificationsForType:completion:)
|
||||
func removeNotifications(
|
||||
for type: String?,
|
||||
completion: @escaping() -> Void
|
||||
) {
|
||||
guard let type = type else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
let notificationCenter = UNUserNotificationCenter.current()
|
||||
|
||||
notificationCenter.getDeliveredNotifications { notifications in
|
||||
let sameTypeNotifications = notifications.filter { notification in
|
||||
let payload = notification.request.content.userInfo
|
||||
if let notificationType = payload["type"] as? String {
|
||||
return notificationType == type
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
let identifiers = sameTypeNotifications.map { $0.request.identifier }
|
||||
notificationCenter.removeDeliveredNotifications(withIdentifiers: identifiers)
|
||||
|
||||
// !! Note: this is a known issue/bug
|
||||
// we need to add a delay before invoking the completion, otherwise the notification will not be remved
|
||||
// ref: https://stackoverflow.com/questions/53697279/why-are-notifications-not-removed-with-removedeliverednotifications
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
#import "NotificationService.h"
|
||||
#import "EQNAllertaSismica.h"
|
||||
#import "Costanti.h"
|
||||
#import "EQNNotificationService-Swift.h"
|
||||
|
||||
|
||||
@interface NotificationService ()
|
||||
|
||||
@@ -73,20 +75,9 @@ static NSString * const EQNSoundNotificationEQN = @"alert_sound.wav";
|
||||
break;
|
||||
}
|
||||
} else if ([notificationType isEqualToString:@"manual"]) {
|
||||
NSString *intensity = [userInfo objectForKey:@"magnitude"];
|
||||
switch ([intensity intValue]) {
|
||||
case 0:
|
||||
iconName = @"star_green.png";
|
||||
break;
|
||||
case 1:
|
||||
iconName = @"star_yellow.png";
|
||||
break;
|
||||
case 2:
|
||||
iconName = @"star_red.png";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// there are 12 levels, so a customized icon doesn't make sense
|
||||
// use a generic warning icon instead
|
||||
iconName = @"warning_yellow.png";
|
||||
} else if ([notificationType isEqualToString:@"official"]) {
|
||||
NSString *provaider = [userInfo objectForKey:@"provider"];
|
||||
double intensity = [[userInfo objectForKey:@"magnitude"] doubleValue];
|
||||
@@ -158,7 +149,10 @@ static NSString * const EQNSoundNotificationEQN = @"alert_sound.wav";
|
||||
}
|
||||
}
|
||||
|
||||
[self contentComplete];
|
||||
// remove same type posted notification
|
||||
[self removeNotificationsForType:notificationType completion:^{
|
||||
[self contentComplete];
|
||||
}];;
|
||||
}
|
||||
|
||||
- (void)serviceExtensionTimeWillExpire
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -11,8 +11,8 @@
|
||||
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 651901B825F5358700CAFF20 /* EQNMapAnnotationSeismic.swift */; };
|
||||
6525A82625E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */; };
|
||||
652C37BD26092B3C0068EC3B /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652C37BC26092B3C0068EC3B /* FiltersViewModel.swift */; };
|
||||
6531185928425B89006CBC29 /* NotificationService+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6531185828425B89006CBC29 /* NotificationService+Extension.swift */; };
|
||||
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */; };
|
||||
6535600425F398CD00BB57D2 /* Costanti+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6535600325F398CD00BB57D2 /* Costanti+Extensions.swift */; };
|
||||
653604E9262348FA00B2B651 /* EQNBaseMapFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */; };
|
||||
653C67E225F3CC2E00FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
||||
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */; };
|
||||
@@ -24,6 +24,9 @@
|
||||
654D18D625F9420500BB6DB0 /* EQNMapAnnotationPastquake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 654D18C825F93CD700BB6DB0 /* EQNMapAnnotationPastquake.swift */; };
|
||||
654D18DA25F9424700BB6DB0 /* EQNUtility+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0188E252F09C500C783F0 /* EQNUtility+Extensions.swift */; };
|
||||
654D18DE25F943E200BB6DB0 /* EQNMapAnnotationUserReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653C67FB25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift */; };
|
||||
6552C13829262119008E723C /* Shogun in Frameworks */ = {isa = PBXBuildFile; productRef = 6552C13729262119008E723C /* Shogun */; };
|
||||
6552C13A2926261D008E723C /* Shogun in Frameworks */ = {isa = PBXBuildFile; productRef = 6552C1392926261D008E723C /* Shogun */; };
|
||||
6552C140292678BD008E723C /* warning_yellow.png in Resources */ = {isa = PBXBuildFile; fileRef = 6552C13F292678BD008E723C /* warning_yellow.png */; };
|
||||
6557CB2A2607676B00962757 /* triangle2_yellow.png in Resources */ = {isa = PBXBuildFile; fileRef = 6557CAC52607676200962757 /* triangle2_yellow.png */; };
|
||||
6557CB2B2607676B00962757 /* star_purple.png in Resources */ = {isa = PBXBuildFile; fileRef = 6557CAC62607676200962757 /* star_purple.png */; };
|
||||
6557CB2C2607676B00962757 /* oct_white.png in Resources */ = {isa = PBXBuildFile; fileRef = 6557CAC72607676200962757 /* oct_white.png */; };
|
||||
@@ -130,14 +133,19 @@
|
||||
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */; };
|
||||
6586971125F44C26009C0182 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
||||
658BAB7B25FE67930015C454 /* EQNBaseMapRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */; };
|
||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */; };
|
||||
658BC02B2859A4D3009EECAA /* RealtimeAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */; };
|
||||
65AD23CE261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AD23CD261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift */; };
|
||||
65BBB22C26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65BBB22B26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift */; };
|
||||
65CB83432915720400EE1E35 /* EQNUserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65CB83422915720400EE1E35 /* EQNUserData.swift */; };
|
||||
65D409942619BA34008CF356 /* SegnalazioniSendReportCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65D409932619BA34008CF356 /* SegnalazioniSendReportCell.swift */; };
|
||||
65D9938A29219DEC00F2B0EB /* UIKit+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */; };
|
||||
65D9938C2922647800F2B0EB /* AppTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC52B8A424FCCD6900ABEBA6 /* AppTheme.swift */; };
|
||||
65DBFB4B25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65DBFB4A25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift */; };
|
||||
65DBFB7425E2BBF20041CBA6 /* GADTMediumTemplateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65DBFB6F25E2BBF20041CBA6 /* GADTMediumTemplateView.xib */; };
|
||||
65DBFB7525E2BBF20041CBA6 /* GADTMediumTemplateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65DBFB7125E2BBF20041CBA6 /* GADTMediumTemplateView.m */; };
|
||||
65DBFB7625E2BBF20041CBA6 /* GADTTemplateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65DBFB7225E2BBF20041CBA6 /* GADTTemplateView.m */; };
|
||||
65E1B19B260F980600A0ACBA /* Dictionary+EQNExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */; };
|
||||
65E1226C285C92AA000E294A /* EQNRealtimeAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */; };
|
||||
8C10B0B92281FE7F00125C9F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
|
||||
8C10B0BA2281FE7F00125C9F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
|
||||
8C10B0BB2281FE7F00125C9F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
|
||||
@@ -150,7 +158,7 @@
|
||||
8C483CB821FDACD300259FD2 /* IAPHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C483CB721FDACD300259FD2 /* IAPHelper.swift */; };
|
||||
8C483CBC21FDACE500259FD2 /* VersioneProProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C483CBB21FDACE500259FD2 /* VersioneProProducts.swift */; };
|
||||
8C4B0B7E21CACE3F00AED489 /* NotificationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4B0B7D21CACE3F00AED489 /* NotificationService.m */; };
|
||||
8C4B0B8221CACE3F00AED489 /* EQNNotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 8C4B0B7A21CACE3F00AED489 /* EQNNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
8C4B0B8221CACE3F00AED489 /* EQNNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 8C4B0B7A21CACE3F00AED489 /* EQNNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
8C4DD4F9228237E000AE77ED /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C4DD4FB228237E000AE77ED /* InfoPlist.strings */; };
|
||||
8C4E343F215012FA008B0D2A /* EQNManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4E343E215012FA008B0D2A /* EQNManager.m */; };
|
||||
8C4E34422152B5E8008B0D2A /* EQNRilevamento.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4E34412152B5E8008B0D2A /* EQNRilevamento.m */; };
|
||||
@@ -180,7 +188,7 @@
|
||||
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 */; };
|
||||
8CF12CE021DE49B600613AC5 /* EQNNotificationContent.appex in Embed App 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 */; };
|
||||
8CF4F4DB216D44930057110B /* EQNPastquakes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF4F4DA216D44930057110B /* EQNPastquakes.m */; };
|
||||
8CF6604F214C0E58009F4314 /* EQNCalibrazione.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF6604E214C0E58009F4314 /* EQNCalibrazione.m */; };
|
||||
@@ -195,7 +203,6 @@
|
||||
DC0AE1B92538204100111307 /* EQNSegnalazione.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C593E89217BA2470008B260 /* EQNSegnalazione.m */; };
|
||||
DC0AE1BA2538204100111307 /* EQNPastquakes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF4F4DA216D44930057110B /* EQNPastquakes.m */; };
|
||||
DC0E551324F8063300D54270 /* SettingSegmentedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0E551224F8063300D54270 /* SettingSegmentedTableViewCell.swift */; };
|
||||
DC105641251E7ECE002579BB /* UIFont+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC105640251E7ECE002579BB /* UIFont+Extensions.swift */; };
|
||||
DC27EB2F24F6EBE000ACBFE0 /* SettingsSeismicNetworksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC27EB2E24F6EBE000ACBFE0 /* SettingsSeismicNetworksViewController.swift */; };
|
||||
DC2814302519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC28142F2519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift */; };
|
||||
DC2814382519C56100C1AFF7 /* SeismicNetworksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2814372519C56100C1AFF7 /* SeismicNetworksViewController.swift */; };
|
||||
@@ -206,7 +213,6 @@
|
||||
DC4B67612517833F00634277 /* EQNSeismic.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4B67602517833F00634277 /* EQNSeismic.swift */; };
|
||||
DC52B8A224FC145500ABEBA6 /* SettingsBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC52B8A124FC145500ABEBA6 /* SettingsBaseViewController.m */; };
|
||||
DC52B8A524FCCD6900ABEBA6 /* AppTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC52B8A424FCCD6900ABEBA6 /* AppTheme.swift */; };
|
||||
DC553AF625692E37000B521B /* StoryboardInitializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC553AF525692E37000B521B /* StoryboardInitializable.swift */; };
|
||||
DC646F27252B694A000AA5FD /* AlertsSeismicNotificationExpandedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC646F26252B694A000AA5FD /* AlertsSeismicNotificationExpandedTableViewCell.swift */; };
|
||||
DC646F32252B698B000AA5FD /* AlertsSeismicNotificationCompactTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC646F31252B698B000AA5FD /* AlertsSeismicNotificationCompactTableViewCell.swift */; };
|
||||
DC65B391250F243E00251693 /* SeismicSettingsNetworksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC65B390250F243E00251693 /* SeismicSettingsNetworksViewController.swift */; };
|
||||
@@ -224,7 +230,6 @@
|
||||
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB28CED24FB8400001F557E /* SettingsViewController.swift */; };
|
||||
DCB45BC8250E86E100DB2D0C /* SeismicSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB45BC7250E86E100DB2D0C /* SeismicSettingsViewController.swift */; };
|
||||
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */; };
|
||||
DCB6FBEC24D0B40600ED23B8 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */; };
|
||||
DCBB267A24D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */; };
|
||||
DCBB267E24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267D24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift */; };
|
||||
DCBB268024D1ECE200F04559 /* SubscriptionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267F24D1ECE200F04559 /* SubscriptionDetailViewController.swift */; };
|
||||
@@ -267,16 +272,16 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8CADAAA521B98C550044E256 /* Embed App Extensions */ = {
|
||||
8CADAAA521B98C550044E256 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
8CF12CE021DE49B600613AC5 /* EQNNotificationContent.appex in Embed App Extensions */,
|
||||
8C4B0B8221CACE3F00AED489 /* EQNNotificationService.appex in Embed App Extensions */,
|
||||
8CF12CE021DE49B600613AC5 /* EQNNotificationContent.appex in Embed Foundation Extensions */,
|
||||
8C4B0B8221CACE3F00AED489 /* EQNNotificationService.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
@@ -288,8 +293,8 @@
|
||||
651901B825F5358700CAFF20 /* EQNMapAnnotationSeismic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationSeismic.swift; sourceTree = "<group>"; };
|
||||
6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkAdvertiseTableViewCell.swift; sourceTree = "<group>"; };
|
||||
652C37BC26092B3C0068EC3B /* FiltersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewModel.swift; sourceTree = "<group>"; };
|
||||
6531185828425B89006CBC29 /* NotificationService+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationService+Extension.swift"; sourceTree = "<group>"; };
|
||||
65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniMapViewController.swift; sourceTree = "<group>"; };
|
||||
6535600325F398CD00BB57D2 /* Costanti+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Costanti+Extensions.swift"; sourceTree = "<group>"; };
|
||||
653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapFilter.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>"; };
|
||||
@@ -297,6 +302,7 @@
|
||||
6544416A25E9599000C41714 /* EQNDebugViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNDebugViewController.swift; sourceTree = "<group>"; };
|
||||
654D18C325F93C0600BB6DB0 /* PasquakesMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasquakesMapViewController.swift; sourceTree = "<group>"; };
|
||||
654D18C825F93CD700BB6DB0 /* EQNMapAnnotationPastquake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationPastquake.swift; sourceTree = "<group>"; };
|
||||
6552C13F292678BD008E723C /* warning_yellow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = warning_yellow.png; sourceTree = "<group>"; };
|
||||
6557CAC52607676200962757 /* triangle2_yellow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = triangle2_yellow.png; sourceTree = "<group>"; };
|
||||
6557CAC62607676200962757 /* star_purple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = star_purple.png; sourceTree = "<group>"; };
|
||||
6557CAC72607676200962757 /* oct_white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oct_white.png; sourceTree = "<group>"; };
|
||||
@@ -405,6 +411,8 @@
|
||||
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkViewModel.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>"; };
|
||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertViewController.swift; sourceTree = "<group>"; };
|
||||
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertView.swift; sourceTree = "<group>"; };
|
||||
65A4D5AA26280A24003918E0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
65A4D5AB26280A24003918E0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
65A4D5AC26280A56003918E0 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "el-GR"; path = "el-GR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
@@ -417,6 +425,7 @@
|
||||
65A4D5B626281126003918E0 /* id-ID */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "id-ID"; path = "id-ID.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
65AD23CD261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsDescriptionTableViewCell.swift; sourceTree = "<group>"; };
|
||||
65BBB22B26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniLast24HoursCell.swift; sourceTree = "<group>"; };
|
||||
65CB83422915720400EE1E35 /* EQNUserData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNUserData.swift; sourceTree = "<group>"; };
|
||||
65D409932619BA34008CF356 /* SegnalazioniSendReportCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniSendReportCell.swift; sourceTree = "<group>"; };
|
||||
65DBFB4A25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworksMapDetailViewController.swift; sourceTree = "<group>"; };
|
||||
65DBFB6F25E2BBF20041CBA6 /* GADTMediumTemplateView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GADTMediumTemplateView.xib; sourceTree = "<group>"; };
|
||||
@@ -424,7 +433,7 @@
|
||||
65DBFB7125E2BBF20041CBA6 /* GADTMediumTemplateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GADTMediumTemplateView.m; sourceTree = "<group>"; };
|
||||
65DBFB7225E2BBF20041CBA6 /* GADTTemplateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GADTTemplateView.m; sourceTree = "<group>"; };
|
||||
65DBFB7325E2BBF20041CBA6 /* GADTMediumTemplateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GADTMediumTemplateView.h; sourceTree = "<group>"; };
|
||||
65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+EQNExtensions.swift"; sourceTree = "<group>"; };
|
||||
65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNRealtimeAlert.swift; sourceTree = "<group>"; };
|
||||
8C10B0BC2281FE7F00125C9F /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8C10B0BE2281FE9E00125C9F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8C10B0BF2281FEA000125C9F /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -515,7 +524,6 @@
|
||||
DC08803E24F5A89000186D97 /* SettingEnableTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingEnableTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC08804024F5B41400186D97 /* SettingSliderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingSliderTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC0E551224F8063300D54270 /* SettingSegmentedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingSegmentedTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC105640251E7ECE002579BB /* UIFont+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Extensions.swift"; sourceTree = "<group>"; };
|
||||
DC27EB2E24F6EBE000ACBFE0 /* SettingsSeismicNetworksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSeismicNetworksViewController.swift; sourceTree = "<group>"; };
|
||||
DC28142F2519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC2814372519C56100C1AFF7 /* SeismicNetworksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworksViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -528,7 +536,6 @@
|
||||
DC52B8A024FC145500ABEBA6 /* SettingsBaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SettingsBaseViewController.h; sourceTree = "<group>"; };
|
||||
DC52B8A124FC145500ABEBA6 /* SettingsBaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsBaseViewController.m; sourceTree = "<group>"; };
|
||||
DC52B8A424FCCD6900ABEBA6 /* AppTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTheme.swift; sourceTree = "<group>"; };
|
||||
DC553AF525692E37000B521B /* StoryboardInitializable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardInitializable.swift; sourceTree = "<group>"; };
|
||||
DC646F26252B694A000AA5FD /* AlertsSeismicNotificationExpandedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsSeismicNotificationExpandedTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC646F31252B698B000AA5FD /* AlertsSeismicNotificationCompactTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsSeismicNotificationCompactTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC65B390250F243E00251693 /* SeismicSettingsNetworksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicSettingsNetworksViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -546,7 +553,6 @@
|
||||
DCB28CED24FB8400001F557E /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||
DCB45BC7250E86E100DB2D0C /* SeismicSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicSettingsViewController.swift; sourceTree = "<group>"; };
|
||||
DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertSimulatorViewController.swift; sourceTree = "<group>"; };
|
||||
DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
|
||||
DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsHeaderTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCBB267D24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionProductTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCBB267F24D1ECE200F04559 /* SubscriptionDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionDetailViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -585,6 +591,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6552C13829262119008E723C /* Shogun in Frameworks */,
|
||||
8C5EA22D21763103002DC156 /* MapKit.framework in Frameworks */,
|
||||
8CC2B44F214AC7F8002ED1B2 /* CoreMotion.framework in Frameworks */,
|
||||
8C483CAE21FDA53B00259FD2 /* StoreKit.framework in Frameworks */,
|
||||
@@ -598,6 +605,7 @@
|
||||
files = (
|
||||
8C465D9A21F653AB00F04673 /* Assets.xcassets in Frameworks */,
|
||||
8CF12CD521DE49B600613AC5 /* UserNotificationsUI.framework in Frameworks */,
|
||||
6552C13A2926261D008E723C /* Shogun in Frameworks */,
|
||||
8CF12CD321DE49B600613AC5 /* UserNotifications.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -615,6 +623,15 @@
|
||||
path = Debug;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
658BC0272859A43C009EECAA /* Realtime Alert */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */,
|
||||
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */,
|
||||
);
|
||||
path = "Realtime Alert";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
65DBFB5225E2A2580041CBA6 /* Map annotation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -660,6 +677,7 @@
|
||||
8C483CB521FDACD100259FD2 /* EQNNotificationService-Bridging-Header.h */,
|
||||
8C4B0B7C21CACE3F00AED489 /* NotificationService.h */,
|
||||
8C4B0B7D21CACE3F00AED489 /* NotificationService.m */,
|
||||
6531185828425B89006CBC29 /* NotificationService+Extension.swift */,
|
||||
DC30BC862534DBB30041B23B /* Icons */,
|
||||
8C4B0B7F21CACE3F00AED489 /* Info.plist */,
|
||||
);
|
||||
@@ -693,7 +711,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8CF66050214C0F7F009F4314 /* Costanti.h */,
|
||||
6535600325F398CD00BB57D2 /* Costanti+Extensions.swift */,
|
||||
8CBD3DC52149B9AD0070C963 /* AppDelegate.h */,
|
||||
8CBD3DC62149B9AD0070C963 /* AppDelegate.m */,
|
||||
DCB6FBEA24D0B11300ED23B8 /* Controllers */,
|
||||
@@ -747,10 +764,8 @@
|
||||
DC10563F251E7EC0002579BB /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC105640251E7ECE002579BB /* UIFont+Extensions.swift */,
|
||||
8C7A3B65225A5EA40045B266 /* NSDictionary+EQNExtensions.h */,
|
||||
8C7A3B64225A5EA30045B266 /* NSDictionary+EQNExtensions.m */,
|
||||
65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */,
|
||||
65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */,
|
||||
650B23AA2632CCD3007AE752 /* UIView+EQNExtensions.swift */,
|
||||
);
|
||||
@@ -785,6 +800,7 @@
|
||||
DC30BC862534DBB30041B23B /* Icons */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6552C13F292678BD008E723C /* warning_yellow.png */,
|
||||
6557CACE2607676300962757 /* circle_green.png */,
|
||||
6557CAFF2607676700962757 /* circle_purple.png */,
|
||||
6557CB1D2607676900962757 /* circle_red.png */,
|
||||
@@ -925,7 +941,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8CBD3DD12149B9AD0070C963 /* Assets.xcassets */,
|
||||
DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */,
|
||||
DC3ADD2E24CB1EBA00737919 /* Sound */,
|
||||
);
|
||||
path = Resources;
|
||||
@@ -942,7 +957,6 @@
|
||||
DC3ADD2F24CB1EFB00737919 /* Libs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC553AF525692E37000B521B /* StoryboardInitializable.swift */,
|
||||
DC10563F251E7EC0002579BB /* Extensions */,
|
||||
8CF66054214C566A009F4314 /* Reachability.h */,
|
||||
8CF66056214C566A009F4314 /* Reachability.m */,
|
||||
@@ -1061,6 +1075,7 @@
|
||||
DCF0188E252F09C500C783F0 /* EQNUtility+Extensions.swift */,
|
||||
8C8EBBA521540039002784BA /* EQNUser.h */,
|
||||
8C8EBBA621540039002784BA /* EQNUser.m */,
|
||||
65CB83422915720400EE1E35 /* EQNUserData.swift */,
|
||||
DC3B5428257FCBCA00C0B6A5 /* EQNReteSmartphone.swift */,
|
||||
8CF4F4D6216D3A110057110B /* EQNAreaCheck.h */,
|
||||
8CF4F4D7216D3A110057110B /* EQNAreaCheck.m */,
|
||||
@@ -1068,6 +1083,7 @@
|
||||
8C593E89217BA2470008B260 /* EQNSegnalazione.m */,
|
||||
8CF4F4D9216D44930057110B /* EQNPastquakes.h */,
|
||||
8CF4F4DA216D44930057110B /* EQNPastquakes.m */,
|
||||
65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@@ -1087,6 +1103,7 @@
|
||||
DCEFF21024F57163009D3FE1 /* Settings */,
|
||||
DC141968250E769B0059E060 /* Seismic Networks */,
|
||||
DCB5281F256015EB005288E5 /* Simulator */,
|
||||
658BC0272859A43C009EECAA /* Realtime Alert */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
@@ -1200,7 +1217,7 @@
|
||||
8CBD3DBE2149B9AD0070C963 /* Sources */,
|
||||
8CBD3DBF2149B9AD0070C963 /* Frameworks */,
|
||||
8CBD3DC02149B9AD0070C963 /* Resources */,
|
||||
8CADAAA521B98C550044E256 /* Embed App Extensions */,
|
||||
8CADAAA521B98C550044E256 /* Embed Foundation Extensions */,
|
||||
213FE27D012BFA5BA1F850E2 /* [CP] Embed Pods Frameworks */,
|
||||
DCF07F9824D40DB600DCCA63 /* ShellScript */,
|
||||
);
|
||||
@@ -1211,6 +1228,9 @@
|
||||
8CF12CDF21DE49B600613AC5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "Earthquake Network";
|
||||
packageProductDependencies = (
|
||||
6552C13729262119008E723C /* Shogun */,
|
||||
);
|
||||
productName = "Earthquake Network";
|
||||
productReference = 8CBD3DC22149B9AD0070C963 /* Earthquake Network.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
@@ -1228,6 +1248,9 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = EQNNotificationContent;
|
||||
packageProductDependencies = (
|
||||
6552C1392926261D008E723C /* Shogun */,
|
||||
);
|
||||
productName = EQNNotificationContent;
|
||||
productReference = 8CF12CD121DE49B600613AC5 /* EQNNotificationContent.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
@@ -1238,7 +1261,7 @@
|
||||
8CBD3DBA2149B9AD0070C963 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1200;
|
||||
LastUpgradeCheck = 1410;
|
||||
ORGANIZATIONNAME = "Earthquake Network";
|
||||
TargetAttributes = {
|
||||
8C4B0B7921CACE3F00AED489 = {
|
||||
@@ -1285,6 +1308,9 @@
|
||||
"id-ID",
|
||||
);
|
||||
mainGroup = 8CBD3DB92149B9AD0070C963;
|
||||
packageReferences = (
|
||||
6552C13629262119008E723C /* XCRemoteSwiftPackageReference "Shogun" */,
|
||||
);
|
||||
productRefGroup = 8CBD3DC32149B9AD0070C963 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
@@ -1409,6 +1435,7 @@
|
||||
6557CB2B2607676B00962757 /* star_purple.png in Resources */,
|
||||
6557CB462607676B00962757 /* dyamond_red.png in Resources */,
|
||||
6557CB682607676B00962757 /* dyamond_round_green.png in Resources */,
|
||||
6552C140292678BD008E723C /* warning_yellow.png in Resources */,
|
||||
6557CB7E2607676B00962757 /* star_red.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1424,7 +1451,6 @@
|
||||
DC958D672535788E00D73D4A /* alert_sound.wav in Resources */,
|
||||
8CBD3DD22149B9AD0070C963 /* Assets.xcassets in Resources */,
|
||||
65DBFB7425E2BBF20041CBA6 /* GADTMediumTemplateView.xib in Resources */,
|
||||
DCB6FBEC24D0B40600ED23B8 /* Colors.xcassets in Resources */,
|
||||
8CBD3DCD2149B9AD0070C963 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1450,7 +1476,6 @@
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Earthquake Network/Pods-Earthquake Network-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics/FirebaseCrashlytics.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
|
||||
@@ -1465,7 +1490,6 @@
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework",
|
||||
@@ -1526,6 +1550,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DCDAB31925188BB3001AE40D /* EQNAllertaSismica.m in Sources */,
|
||||
6531185928425B89006CBC29 /* NotificationService+Extension.swift in Sources */,
|
||||
8C4B0B7E21CACE3F00AED489 /* NotificationService.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1563,6 +1588,7 @@
|
||||
652C37BD26092B3C0068EC3B /* FiltersViewModel.swift in Sources */,
|
||||
DCF9E14F24F6EA07002B6B1D /* EQNSeismicNetwork.swift in Sources */,
|
||||
DC2814302519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift in Sources */,
|
||||
65CB83432915720400EE1E35 /* EQNUserData.swift in Sources */,
|
||||
654D18C425F93C0600BB6DB0 /* PasquakesMapViewController.swift in Sources */,
|
||||
8C14113721EE502800A59729 /* EQNAllertaSismica.m in Sources */,
|
||||
8C483CBC21FDACE500259FD2 /* VersioneProProducts.swift in Sources */,
|
||||
@@ -1574,8 +1600,10 @@
|
||||
DCA5B6E7252E4BD8002AEC96 /* EQNBaseTableViewCell.swift in Sources */,
|
||||
8CF66058214C566B009F4314 /* ServerRequest.m in Sources */,
|
||||
DCF9E14D24F6D1AA002B6B1D /* EQNData.swift in Sources */,
|
||||
65E1226C285C92AA000E294A /* EQNRealtimeAlert.swift in Sources */,
|
||||
DC52B8A524FCCD6900ABEBA6 /* AppTheme.swift in Sources */,
|
||||
653C680425F3DF8A00FE52AC /* EQNBaseMapViewController.swift in Sources */,
|
||||
658BC02B2859A4D3009EECAA /* RealtimeAlertView.swift in Sources */,
|
||||
DC27EB2F24F6EBE000ACBFE0 /* SettingsSeismicNetworksViewController.swift in Sources */,
|
||||
8CF66059214C566B009F4314 /* Reachability.m in Sources */,
|
||||
DC886A5D24E92D5500F7A5D3 /* EQNBaseViewController.m in Sources */,
|
||||
@@ -1592,7 +1620,6 @@
|
||||
DCBB84F0252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift in Sources */,
|
||||
DCD3E3C024D15576007C78D4 /* PurchaseProVersionViewController.swift in Sources */,
|
||||
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */,
|
||||
65E1B19B260F980600A0ACBA /* Dictionary+EQNExtensions.swift in Sources */,
|
||||
DC99A50324E66E270071BC9F /* EQNCommandProtocol.swift in Sources */,
|
||||
DCB45BC8250E86E100DB2D0C /* SeismicSettingsViewController.swift in Sources */,
|
||||
DCF10DC624D2B8C7009F34C3 /* EQNPurchaseUtility.swift in Sources */,
|
||||
@@ -1607,6 +1634,7 @@
|
||||
DC65B391250F243E00251693 /* SeismicSettingsNetworksViewController.swift in Sources */,
|
||||
65DBFB4B25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift in Sources */,
|
||||
DC08804124F5B41400186D97 /* SettingSliderTableViewCell.swift in Sources */,
|
||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */,
|
||||
8CBD3DD82149B9AD0070C963 /* main.m in Sources */,
|
||||
8CF05B57218C93BA0055012B /* EQNUtility.m in Sources */,
|
||||
8C4E34422152B5E8008B0D2A /* EQNRilevamento.m in Sources */,
|
||||
@@ -1625,8 +1653,6 @@
|
||||
65D409942619BA34008CF356 /* SegnalazioniSendReportCell.swift in Sources */,
|
||||
8CBD3DC72149B9AD0070C963 /* AppDelegate.m in Sources */,
|
||||
DC974AFF251748B300A139EC /* SeismicFiltersViewController.swift in Sources */,
|
||||
DC105641251E7ECE002579BB /* UIFont+Extensions.swift in Sources */,
|
||||
6535600425F398CD00BB57D2 /* Costanti+Extensions.swift in Sources */,
|
||||
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */,
|
||||
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */,
|
||||
DCC76BD8251F56050005C4DC /* SeismicCardSettingsViewController.swift in Sources */,
|
||||
@@ -1635,7 +1661,6 @@
|
||||
DC3CE50A250EB7A8005A7DD5 /* EQNGenericPickerViewController.swift in Sources */,
|
||||
DCEFF21A24F587E3009D3FE1 /* SettingItem.swift in Sources */,
|
||||
8C8EBBA721540039002784BA /* EQNUser.m in Sources */,
|
||||
DC553AF625692E37000B521B /* StoryboardInitializable.swift in Sources */,
|
||||
8CADAA9421B2627D0044E256 /* EQNLogViewController.m in Sources */,
|
||||
DC3BA11124D1A9C90062EE7F /* SubscriptionsViewController.swift in Sources */,
|
||||
DC646F27252B694A000AA5FD /* AlertsSeismicNotificationExpandedTableViewCell.swift in Sources */,
|
||||
@@ -1647,6 +1672,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8C465D9F21F7BE0600F04673 /* Assets.xcassets in Sources */,
|
||||
65D9938C2922647800F2B0EB /* AppTheme.swift in Sources */,
|
||||
DC0AE1B92538204100111307 /* EQNSegnalazione.m in Sources */,
|
||||
654D18DE25F943E200BB6DB0 /* EQNMapAnnotationUserReport.swift in Sources */,
|
||||
654D18D625F9420500BB6DB0 /* EQNMapAnnotationPastquake.swift in Sources */,
|
||||
@@ -1654,6 +1680,7 @@
|
||||
653C67E625F3CC8400FE52AC /* EQNCustomAnnotationView.swift in Sources */,
|
||||
654D18DA25F9424700BB6DB0 /* EQNUtility+Extensions.swift in Sources */,
|
||||
DC0AE1BA2538204100111307 /* EQNPastquakes.m in Sources */,
|
||||
65D9938A29219DEC00F2B0EB /* UIKit+Extensions.swift in Sources */,
|
||||
8CF12CD921DE49B600613AC5 /* NotificationViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1738,12 +1765,16 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationService/EQNNotificationService.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Service - Development";
|
||||
@@ -1762,12 +1793,16 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationService/EQNNotificationService.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Service - AppStore";
|
||||
@@ -1907,14 +1942,17 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1944,8 +1982,6 @@
|
||||
"-framework",
|
||||
"\"FirebaseCore\"",
|
||||
"-framework",
|
||||
"\"FirebaseCoreDiagnostics\"",
|
||||
"-framework",
|
||||
"\"FirebaseCrashlytics\"",
|
||||
"-framework",
|
||||
"\"FirebaseInstallations\"",
|
||||
@@ -2017,13 +2053,16 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -2053,8 +2092,6 @@
|
||||
"-framework",
|
||||
"\"FirebaseCore\"",
|
||||
"-framework",
|
||||
"\"FirebaseCoreDiagnostics\"",
|
||||
"-framework",
|
||||
"\"FirebaseCrashlytics\"",
|
||||
"-framework",
|
||||
"\"FirebaseInstallations\"",
|
||||
@@ -2122,12 +2159,16 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
|
||||
@@ -2146,12 +2187,16 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 101;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 5.0.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
|
||||
@@ -2202,6 +2247,30 @@
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
6552C13629262119008E723C /* XCRemoteSwiftPackageReference "Shogun" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/andreabusi-it/Shogun";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.0.1;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
6552C13729262119008E723C /* Shogun */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 6552C13629262119008E723C /* XCRemoteSwiftPackageReference "Shogun" */;
|
||||
productName = Shogun;
|
||||
};
|
||||
6552C1392926261D008E723C /* Shogun */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 6552C13629262119008E723C /* XCRemoteSwiftPackageReference "Shogun" */;
|
||||
productName = Shogun;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 8CBD3DBA2149B9AD0070C963 /* Project object */;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1200"
|
||||
LastUpgradeVersion = "1410"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
@@ -74,6 +74,7 @@
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1200"
|
||||
LastUpgradeVersion = "1410"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
@@ -74,6 +74,7 @@
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1200"
|
||||
LastUpgradeVersion = "1410"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "shogun",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/andreabusi-it/Shogun",
|
||||
"state" : {
|
||||
"revision" : "63d1fdb957d917410e58a958a49fdb52f8de10ac",
|
||||
"version" : "0.2.3"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
}
|
||||
@@ -43,6 +43,11 @@
|
||||
}];
|
||||
#endif
|
||||
|
||||
// execute commands
|
||||
EQNStartupCommandsBuilder *builder = [[EQNStartupCommandsBuilder alloc] init];
|
||||
self.commands = [builder build];
|
||||
[builder executeWithCommands:self.commands];
|
||||
|
||||
[EQNUser defaultUser];
|
||||
[EQNManager defaultManager];
|
||||
[FIRApp configure];
|
||||
@@ -52,11 +57,6 @@
|
||||
NSString *language = [[NSLocale preferredLanguages] firstObject];
|
||||
[[FIRCrashlytics crashlytics] setCustomValue:language forKey:@"lang"];
|
||||
|
||||
// execute commands
|
||||
EQNStartupCommandsBuilder *builder = [[EQNStartupCommandsBuilder alloc] init];
|
||||
self.commands = [builder build];
|
||||
[builder executeWithCommands:self.commands];
|
||||
|
||||
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
|
||||
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
|
||||
[[UNUserNotificationCenter currentNotificationCenter]
|
||||
@@ -124,7 +124,10 @@
|
||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||
{
|
||||
NSString *token = [self stringWithDeviceToken:deviceToken];
|
||||
NSLog(@"[DEBUG] push token: %@", token);
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:token forKey:EQNUserDefaultPushToken];
|
||||
FIRMessaging.messaging.APNSToken = deviceToken;
|
||||
}
|
||||
|
||||
- (NSString *)stringWithDeviceToken:(NSData *)deviceToken
|
||||
@@ -180,9 +183,9 @@
|
||||
EQNTabBarSection section = EQNTabBarSectionAllerte;
|
||||
if ([userInfo[@"type"] isEqualToString:@"eqn"]) {
|
||||
NSDate *dataRicezione = [NSDate date];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:dataRicezione forKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:dataRicezione forKey:EQNUserDefaultRealTimeAlertDate];
|
||||
|
||||
[EQNUtility storeDictionary:userInfo toUserDefaultForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
[EQNUtility storeDictionary:userInfo toUserDefaultForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
section = EQNTabBarSectionAllerte;
|
||||
} else if([userInfo[@"type"] isEqualToString:@"manual"]) {
|
||||
section = EQNTabBarSectionSegnalazioni;
|
||||
@@ -199,14 +202,14 @@
|
||||
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken
|
||||
{
|
||||
NSLog(@"[Firebase] fcmToken %@", fcmToken);
|
||||
if (![[NSUserDefaults standardUserDefaults] objectForKey:EQNUserDefaultUserFirebaseToken]) {
|
||||
if (EQNUserData.sharedData.isFirstStart) {
|
||||
// save default values for notification settings
|
||||
[EQNAllertaSismica saveDefaultValues];
|
||||
[EQNNotificheSegnalazioniUtente saveDefaultValues];
|
||||
[EQNNotificheReteSismiche saveDefaultValues];
|
||||
}
|
||||
|
||||
[EQNUser defaultUser].tokenUser = fcmToken;
|
||||
[EQNUser.defaultUser registerUserIfNeededWithFirebaseToken:fcmToken];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -104,7 +104,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
- (void)setupUI
|
||||
{
|
||||
self.title = [NSLocalizedString(@"tab_network", nil) capitalizedString];
|
||||
self.tableView.estimatedRowHeight = 200.0;
|
||||
self.tableView.estimatedRowHeight = 600.0;
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
}
|
||||
|
||||
@@ -116,15 +116,23 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
BOOL showAllCards = [[NSUserDefaults standardUserDefaults] boolForKey:EQNUserDefaultKeyAlertsShowAllCards];
|
||||
self.expandeCollapseButton.image = showAllCards ? [UIImage imageNamed:@"navbar-icon-arrow-collapse"] : [UIImage imageNamed:@"navbar-icon-arrow-expand"];
|
||||
|
||||
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
if (date) {
|
||||
if ([EQNUtility getDifferenceMinute:date] < TEMPO_VISUALIZZAZIONE_NOTIFICA)
|
||||
self.isNotificaAttiva = YES;
|
||||
else{
|
||||
self.isNotificaAttiva = NO;
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
// controlliamo se c'è una notifica in tempo reale da mostrare
|
||||
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:EQNUserDefaultRealTimeAlertDate];
|
||||
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
if (date && info && [EQNUtility getDifferenceMinute:date] < EQNRealtimeAlertExpiration) {
|
||||
self.isNotificaAttiva = YES;
|
||||
|
||||
// mostriamo la schermata solo se il countdown non è a zero
|
||||
EQNRealtimeAlert *alert = [[EQNRealtimeAlert alloc] initWithNotification:info];
|
||||
if (alert != nil && ![alert isCountdownExpired]) {
|
||||
RealtimeAlertViewController *controller = [[RealtimeAlertViewController alloc] initWithAlert:alert];
|
||||
if (@available(iOS 13.0, *)) {
|
||||
controller.modalInPresentation = YES;
|
||||
}
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
}
|
||||
} else {
|
||||
[self resetRealtimeAlert];
|
||||
}
|
||||
|
||||
[self.tableItems removeAllObjects];
|
||||
@@ -152,6 +160,13 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)resetRealtimeAlert
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertDate];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
self.isNotificaAttiva = NO;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)refreshDataTapped:(id)sender
|
||||
@@ -171,11 +186,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
|
||||
- (void)actionCloseNotification
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
self.isNotificaAttiva = NO;
|
||||
|
||||
[self resetRealtimeAlert];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
@@ -258,7 +269,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
} else if (tableRow == AllerteTableRowSismiRilevati) {
|
||||
if (self.isNotificaAttiva) {
|
||||
AlertsSeismicNotificationExpandedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SeismicNotificationExpandedCell" forIndexPath:indexPath];
|
||||
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
cell.notification = info;
|
||||
|
||||
__weak AllerteViewController *weakSelf = self;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
import Shogun
|
||||
|
||||
class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMapViewDelegate {
|
||||
|
||||
@@ -15,7 +16,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
|
||||
@objc var notification: [String: Any]? {
|
||||
didSet {
|
||||
startCountdown()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
@@ -64,17 +64,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
descriptionLabel.text = NSLocalizedString("map_smartphone_magnitude", comment: "")
|
||||
}
|
||||
|
||||
private func startCountdown() {
|
||||
guard let notification = notification else { return }
|
||||
|
||||
// calculate the impact timestamp and start a timer for the countdown label
|
||||
if let impactTimestamp = EQNUtility.calculateUserSeismicTimestamp(fromUserInfo: notification) {
|
||||
self.impactTimestamp = impactTimestamp
|
||||
countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdownTimerFired(_:)), userInfo: nil, repeats: true)
|
||||
countdownTimer?.fire()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
// clearn any other previous notifications
|
||||
notificationTitleLabel.text = ""
|
||||
@@ -85,7 +74,7 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
let aps = notification["aps"] as? [String: Any],
|
||||
let alert = aps["alert"] as? [String: Any] else { return }
|
||||
|
||||
let intensity = notification.eqn_intValue(for: "intensity") ?? 0
|
||||
let intensity = notification.integer(forKey: "intensity", orDefault: 0)
|
||||
containerView.backgroundColor = color(for: intensity)
|
||||
|
||||
if let title = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
|
||||
@@ -94,8 +83,8 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
|
||||
// get coordinate
|
||||
var coordinate: CLLocation?
|
||||
if let latitude = notification.eqn_doubleValue(for: "latitude"),
|
||||
let longitude = notification.eqn_doubleValue(for: "longitude") {
|
||||
if let latitude = notification.double(forKey: "latitude"),
|
||||
let longitude = notification.double(forKey: "longitude") {
|
||||
|
||||
coordinate = CLLocation(latitude: latitude, longitude: longitude)
|
||||
}
|
||||
@@ -149,20 +138,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func countdownTimerFired(_ sender: Timer) {
|
||||
guard let impactTimestamp = impactTimestamp else { return }
|
||||
|
||||
let now = Date()
|
||||
let difference = lround(max(impactTimestamp.timeIntervalSince(now), 0))
|
||||
waveTimeLabel.text = String(format: NSLocalizedString("alert_wave", comment: ""), difference)
|
||||
|
||||
if difference <= 0 {
|
||||
// stop the countdown
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = nil
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func shareAppTapped(_ sender: UIButton) {
|
||||
onTapShareApp?()
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ class PasquakesMapViewController: EQNBaseMapViewController {
|
||||
}
|
||||
|
||||
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
||||
mapView.deselectAnnotation(annotation, animated: true)
|
||||
|
||||
guard let annotation = annotation as? EQNMapAnnotationPastquake, let pastquake = annotation.pastquake else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
[[EQNManager defaultManager] avviaManager];
|
||||
[[EQNAccelerometroManager sharedInstance] startUpdatingLocationBackground];
|
||||
|
||||
self.testo = [NSString stringWithFormat:@" LOG ID UTENTE %@\n\nTOKEN FIREBASE:\n%@\n\n", [EQNUser defaultUser].user_ID, [EQNUser defaultUser].tokenUser];
|
||||
self.testo = [NSString stringWithFormat:@" LOG ID UTENTE %@\n\nTOKEN FIREBASE:\n%@\n\n", [EQNUser defaultUser].user_ID, EQNUserData.sharedData.firebaseToken];
|
||||
|
||||
self.logView.text = self.testo;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
|
||||
- (BOOL)isBannerVisible
|
||||
{
|
||||
#if ADS_ENABLED
|
||||
return ![EQNPurchaseUtility isProVersionEnabled];
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - View Lifecycle
|
||||
|
||||
@@ -63,7 +63,7 @@ static NSString * const SegueIdentifierLogs = @"ShowLogs";
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"retry", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
// retry server registration
|
||||
[[EQNUser defaultUser] verificaRegistrazione];
|
||||
[[EQNUser defaultUser] retryUserRegistration];
|
||||
}]];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"options_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
@@ -136,7 +136,7 @@ static NSString * const SegueIdentifierLogs = @"ShowLogs";
|
||||
}
|
||||
|
||||
// tap 5 times on "Settings" to open debug view
|
||||
if ([controller isKindOfClass:[SettingsViewController class]]) {
|
||||
if ([controller isKindOfClass:[SettingsViewController class]] && EQNEnableDebugView) {
|
||||
self.debugTapCounter += 1;
|
||||
if (self.debugTapCounter == 5) {
|
||||
self.debugTapCounter = 0;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
import Shogun
|
||||
|
||||
|
||||
class SubscriptionsViewController: UITableViewController {
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// RealtimeAlertView.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 15/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
|
||||
class RealtimeAlertView: UIView {
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .title2)
|
||||
label.text = NSLocalizedString("app_name", comment: "")
|
||||
return label
|
||||
}()
|
||||
|
||||
let descriptionLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
let waveTimeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .title3)
|
||||
label.textColor = AppTheme.Colors.red
|
||||
label.text = String(format: NSLocalizedString("alert_wave", comment: ""), 0)
|
||||
label.textAlignment = .center
|
||||
label.isHidden = true
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var mapView: MKMapView = {
|
||||
let map = MKMapView()
|
||||
map.translatesAutoresizingMaskIntoConstraints = false
|
||||
map.delegate = self
|
||||
map.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
||||
map.showsUserLocation = true
|
||||
return map
|
||||
}()
|
||||
|
||||
let closeButton: EQNBlurredCloseButton = {
|
||||
let button = EQNBlurredCloseButton()
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.setTitleColor(.darkGray, for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: .zero)
|
||||
configureUI()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func configureUI() {
|
||||
backgroundColor = AppTheme.Colors.lightGray
|
||||
|
||||
addSubview(closeButton)
|
||||
addSubview(titleLabel)
|
||||
addSubview(descriptionLabel)
|
||||
addSubview(waveTimeLabel)
|
||||
addSubview(mapView)
|
||||
|
||||
closeButton.addDefaultConstraint(to: self)
|
||||
|
||||
titleLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
titleLabel.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor, constant: -10.0).isActive = true
|
||||
titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 10.0).isActive = true
|
||||
|
||||
descriptionLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
descriptionLabel.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
|
||||
waveTimeLabel.leadingAnchor.constraint(equalTo: descriptionLabel.leadingAnchor).isActive = true
|
||||
waveTimeLabel.trailingAnchor.constraint(equalTo: descriptionLabel.trailingAnchor).isActive = true
|
||||
waveTimeLabel.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
|
||||
mapView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||
mapView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
||||
mapView.topAnchor.constraint(equalTo: waveTimeLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
mapView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func addMapCircle(
|
||||
center: CLLocationCoordinate2D,
|
||||
radius: CLLocationDistance,
|
||||
overlayId: String
|
||||
) {
|
||||
// remove any other existing overlays
|
||||
let overlays = mapView.overlays.filter { $0.title == overlayId }
|
||||
mapView.removeOverlays(overlays)
|
||||
|
||||
// add new overlay
|
||||
let circle = MKCircle(center: center, radius: radius)
|
||||
circle.title = overlayId
|
||||
mapView.addOverlay(circle)
|
||||
}
|
||||
|
||||
func addMapLine(
|
||||
coordinates: [CLLocationCoordinate2D]
|
||||
) {
|
||||
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
|
||||
mapView.addOverlay(polyline)
|
||||
}
|
||||
|
||||
func addMapAnnotation(
|
||||
title: String = "",
|
||||
center: CLLocationCoordinate2D,
|
||||
intensity: Int
|
||||
) {
|
||||
let annotation = EQNMapAnnotationPastquake(title: title, coordinate: center, intensity: intensity)
|
||||
mapView.addAnnotation(annotation)
|
||||
}
|
||||
}
|
||||
|
||||
extension RealtimeAlertView: MKMapViewDelegate {
|
||||
|
||||
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
switch overlay {
|
||||
case let circle as MKCircle:
|
||||
let circleRenderer = MKCircleRenderer(overlay: circle)
|
||||
circleRenderer.strokeColor = AppTheme.Colors.red
|
||||
circleRenderer.fillColor = AppTheme.Colors.red.withAlphaComponent(0.2)
|
||||
circleRenderer.lineWidth = 3.0
|
||||
return circleRenderer
|
||||
case let polyline as MKPolyline:
|
||||
let polylineRenderer = MKPolylineRenderer(polyline: polyline)
|
||||
polylineRenderer.strokeColor = .blue
|
||||
polylineRenderer.lineWidth = 2.0
|
||||
return polylineRenderer
|
||||
default:
|
||||
return MKOverlayRenderer(overlay: overlay)
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||
guard let annotation = annotation as? EQNMapAnnotationPastquake else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
|
||||
annotationView.image = annotation.image
|
||||
annotationView.title = annotation.title
|
||||
return annotationView
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
//
|
||||
// RealtimeAlertViewController.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 15/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
|
||||
class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
||||
|
||||
@objc var onClose: () -> Void = {}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
private let notificationView = RealtimeAlertView()
|
||||
/// Alert to display
|
||||
private let realtimeAlert: EQNRealtimeAlert
|
||||
/// 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
|
||||
|
||||
@objc
|
||||
init(alert: EQNRealtimeAlert) {
|
||||
self.realtimeAlert = alert
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.waveAnimationCurrentRadius = currentWavePosition()
|
||||
self.waveAnimationVelocity = evaluateWaveAnimationVelocity()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
// importante togliere il delegato, altrimenti causa crash
|
||||
notificationView.mapView.delegate = nil
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func loadView() {
|
||||
view = notificationView
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
configureUI()
|
||||
updateUI()
|
||||
|
||||
startCountdown()
|
||||
startWaveAnimation()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func configureUI() {
|
||||
notificationView.closeButton.addTarget(self, action: #selector(onTapClose(_:)), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
notificationView.descriptionLabel.text = realtimeAlert.title
|
||||
|
||||
// update title with distance from earthquake
|
||||
let distanceRound = Int(round(realtimeAlert.distanceFromUser() / 1_000))
|
||||
notificationView.descriptionLabel.text = (notificationView.descriptionLabel.text ?? "")
|
||||
+ ".\n"
|
||||
+ String(format: NSLocalizedString("timer_message2_other", comment: ""), distanceRound)
|
||||
|
||||
// center map on the earthquake coordinate
|
||||
let span = MKCoordinateSpan(latitudeDelta: 10.5, longitudeDelta: 10.5)
|
||||
let region = MKCoordinateRegion(center: realtimeAlert.coordinate.coordinate, span: span)
|
||||
notificationView.mapView.setCenter(realtimeAlert.coordinate.coordinate, animated: false)
|
||||
notificationView.mapView.setRegion(region, animated: true)
|
||||
|
||||
// aggiungiamo annotation con epicentro sisma
|
||||
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
|
||||
if let lastPosition = EQNUser.default().lastPosition {
|
||||
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
|
||||
|
||||
@objc private func onTapClose(_ sender: UIButton) {
|
||||
// invalidiamo i timer, altri
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = nil
|
||||
waveAnimationTimer?.invalidate()
|
||||
waveAnimationTimer = nil
|
||||
|
||||
onClose()
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Timer
|
||||
|
||||
@objc private func countdownTimerFired(_ sender: Timer) {
|
||||
let countdown = realtimeAlert.currentCountdown()
|
||||
notificationView.waveTimeLabel.text = String(format: NSLocalizedString("alert_wave", comment: ""), 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 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
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,8 @@ import UIKit
|
||||
class SegnalazioniLast24HoursCell: EQNBaseTableViewCell {
|
||||
|
||||
@IBOutlet private weak var headerLabel: UILabel!
|
||||
@IBOutlet private weak var mildReportsLabel: UILabel!
|
||||
@IBOutlet private weak var strongReportsLabel: UILabel!
|
||||
@IBOutlet private weak var veryStrongReportsLabel: UILabel!
|
||||
@IBOutlet private weak var reportsLabel: UILabel!
|
||||
@IBOutlet private weak var reportsDescriptionLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var twitterButton: UIButton! {
|
||||
didSet {
|
||||
@@ -38,11 +37,11 @@ class SegnalazioniLast24HoursCell: EQNBaseTableViewCell {
|
||||
// MARK: - Private
|
||||
|
||||
private func localizeUI() {
|
||||
headerLabel.text = NSLocalizedString("main_map", comment: "")
|
||||
headerLabel.text = NSLocalizedString("tab_manual", comment: "").capitalized
|
||||
reportsDescriptionLabel.text = NSLocalizedString("main_map", comment: "")
|
||||
mapButton.setTitle(NSLocalizedString("official_button_map", comment: ""), for: .normal)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@objc func updateUI(for smartphoneNetwork: EQNReteSmartphone?) {
|
||||
@@ -50,8 +49,6 @@ class SegnalazioniLast24HoursCell: EQNBaseTableViewCell {
|
||||
return
|
||||
}
|
||||
|
||||
self.mildReportsLabel.text = "\(smartphoneNetwork.manualGreen)"
|
||||
self.strongReportsLabel.text = "\(smartphoneNetwork.manualYellow)"
|
||||
self.veryStrongReportsLabel.text = "\(smartphoneNetwork.manualRed)"
|
||||
self.reportsLabel.text = "\(smartphoneNetwork.manual)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import MapKit
|
||||
import Shogun
|
||||
|
||||
class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
|
||||
@@ -16,10 +17,74 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
let circle: MKCircle
|
||||
}
|
||||
|
||||
override var isCloseButtonVisible: Bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Contains circles and related colors to draw overlays on the map
|
||||
private var mapCircles = [MapCircle]()
|
||||
/// Reports currently showned on the map
|
||||
private var filteredReports = [EQNSegnalazione]()
|
||||
/// Defines if time has to be shown on map annotations
|
||||
private var showAnnotationTime = false
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
// app icon and name displayed on the screenshot
|
||||
private lazy var watermarkView: UIView = {
|
||||
let view = UIView()
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.isHidden = true
|
||||
|
||||
let logo = UIImageView(image: .init(named: "eq_icon_transparent"))
|
||||
logo.translatesAutoresizingMaskIntoConstraints = false
|
||||
logo.contentMode = .scaleAspectFit
|
||||
view.addSubview(logo)
|
||||
logo.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
||||
logo.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
logo.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||
logo.widthAnchor.constraint(equalTo: logo.heightAnchor).isActive = true
|
||||
|
||||
let title = UILabel()
|
||||
title.translatesAutoresizingMaskIntoConstraints = false
|
||||
title.text = NSLocalizedString("app_name", comment: "") + " App"
|
||||
title.textColor = AppTheme.Colors.red
|
||||
title.font = .preferredFont(forTextStyle: .title3, weight: .semibold)
|
||||
view.addSubview(title)
|
||||
title.leadingAnchor.constraint(equalTo: logo.trailingAnchor, constant: 10.0).isActive = true
|
||||
title.centerYAnchor.constraint(equalTo: logo.centerYAnchor).isActive = true
|
||||
title.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var magnitudeLegendView: UIView = {
|
||||
let view = UIView()
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.axis = .horizontal
|
||||
stackView.distribution = .fillEqually
|
||||
[20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120].forEach { magnitude in
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.text = (magnitude / 10).romanNumber()
|
||||
label.backgroundColor = UIColor(named: "Mercalli \(magnitude)")
|
||||
label.textAlignment = .center
|
||||
label.font = .preferredFont(forTextStyle: .callout)
|
||||
label.textColor = magnitude >= 100 ? .white : .black
|
||||
stackView.addArrangedSubview(label)
|
||||
}
|
||||
|
||||
view.addSubview(stackView)
|
||||
stackView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
||||
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
|
||||
return view
|
||||
}()
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
@@ -29,8 +94,31 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func extraUI() {
|
||||
view.addSubview(magnitudeLegendView)
|
||||
view.addSubview(watermarkView)
|
||||
|
||||
magnitudeLegendView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
magnitudeLegendView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
magnitudeLegendView.heightAnchor.constraint(equalToConstant: 25.0).isActive = true
|
||||
magnitudeLegendView.topAnchor.constraint(equalTo: mapView.topAnchor).isActive = true
|
||||
|
||||
watermarkView.topAnchor.constraint(equalTo: mapView.topAnchor, constant: 10.0).isActive = true
|
||||
watermarkView.leadingAnchor.constraint(equalTo: mapView.leadingAnchor, constant: 10.0).isActive = true
|
||||
watermarkView.heightAnchor.constraint(equalToConstant: 40.0).isActive = true
|
||||
}
|
||||
|
||||
override func configureUI() {
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(onTapCloseButton(_:)))
|
||||
navigationItem.rightBarButtonItems = [
|
||||
UIBarButtonItem(image: UIImage(named: "navbar-icon-screenshot"), style: .plain, target: self, action: #selector(onTapScreenshotButton(_:))),
|
||||
UIBarButtonItem(image: UIImage(named: "navbar-icon-pin-arrow"), style: .plain, target: self, action: #selector(onTapMapDetailStyleButton(_:)))
|
||||
]
|
||||
}
|
||||
|
||||
override func registerMapAnnotationViews() {
|
||||
mapView.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
||||
mapView.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SmallIdentifier)
|
||||
}
|
||||
|
||||
override func loadDataSource() {
|
||||
@@ -96,27 +184,41 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
||||
guard let annotation = annotation as? EQNMapAnnotationUserReport, let report = annotation.report else {
|
||||
return
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func onTapCloseButton(_ sender: Any) {
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
@objc private func onTapMapDetailStyleButton(_ sender: Any) {
|
||||
showAnnotationTime.toggle()
|
||||
loadDataSource()
|
||||
}
|
||||
|
||||
@objc private func onTapScreenshotButton(_ sender: Any) {
|
||||
let snapshot = createSnapshot()
|
||||
|
||||
let controller = UIActivityViewController(activityItems: [snapshot], applicationActivities: [])
|
||||
present(controller, animated: true)
|
||||
}
|
||||
|
||||
public func createSnapshot() -> UIImage {
|
||||
// mostriamo il watermark e nascondiamo la legenda
|
||||
watermarkView.isHidden = false
|
||||
magnitudeLegendView.isHidden = true
|
||||
|
||||
// riduciamo la porzione da salvare alla sola mappa (eliminiamo i filtri)
|
||||
let size = CGSize(width: view.bounds.width, height: mapView.bounds.maxY)
|
||||
let renderer = UIGraphicsImageRenderer(size: size)
|
||||
let image = renderer.image { ctx in
|
||||
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
|
||||
}
|
||||
|
||||
let difference = Int(Date().timeIntervalSince(report.date) / 60.0)
|
||||
let title = EQNUtility.formattedString(forTimeDifference: difference) + " - \(report.intensity.description)"
|
||||
// torniamo allo stato originale
|
||||
watermarkView.isHidden = true
|
||||
magnitudeLegendView.isHidden = false
|
||||
|
||||
var message = ""
|
||||
+ "🏢 " + report.address
|
||||
+ "\n⏱ " + EQNUtility.formattedDate(from: report.date) + " \(NSLocalizedString("share_yourtime", comment: ""))"
|
||||
if !report.message.isEmpty {
|
||||
message += "\n💬 \(report.message)"
|
||||
}
|
||||
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("main_share", comment: ""), style: .default, handler: { [unowned self] _ in
|
||||
self.openShareActivity(for: report)
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("official_close", comment: ""), style: .cancel, handler: nil))
|
||||
present(alert, animated: true, completion: nil)
|
||||
return image
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -125,7 +227,7 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
let vector_latitude = reports.map { $0.coordinate.coordinate.latitude }
|
||||
let vector_longitude = reports.map { $0.coordinate.coordinate.longitude }
|
||||
let vector_date = reports.map { $0.date }
|
||||
let vector_state = reports.map { $0.intensity.rawValue }
|
||||
let vector_state = reports.map { $0.intensity }
|
||||
|
||||
let minutes: TimeInterval = filter.minutes
|
||||
|
||||
@@ -200,21 +302,7 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
}
|
||||
|
||||
let circles = Array(0..<cluster_code).map { (i) -> MapCircle in
|
||||
var value_distance = max_distance[i] / 20.0
|
||||
if value_distance > 1.0 {
|
||||
value_distance = 1.0
|
||||
}
|
||||
let value_intensity = (cluster_intensity[i]-1.0) / 2.0
|
||||
let value_reference = max(value_distance, value_intensity)
|
||||
|
||||
let color: UIColor
|
||||
if value_reference <= 0.5 {
|
||||
let red = round(value_reference * 510)
|
||||
color = UIColor(red: CGFloat(red / 255.0), green: 230.0/255.0, blue: 0.0, alpha: 1.0)
|
||||
} else {
|
||||
let green = round(230 - (value_reference - 0.5) * 460)
|
||||
color = UIColor(red: 255.0, green: CGFloat(green / 255.0), blue: 0.0, alpha: 1.0)
|
||||
}
|
||||
let color: UIColor = AppTheme.Colors.darkGray
|
||||
|
||||
let centre = CLLocation(latitude: lat_centre[i], longitude: lon_centre[i])
|
||||
let farest = CLLocation(latitude: lat_farest[i], longitude: lon_farest[i])
|
||||
@@ -244,25 +332,6 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
Date().timeIntervalSince(date) / 60.0
|
||||
}
|
||||
|
||||
private func openShareActivity(for report: EQNSegnalazione) {
|
||||
// create message to share
|
||||
let intensity = report.intensity.description
|
||||
let difference = Int(Date().timeIntervalSince(report.date) / 60.0)
|
||||
let time = EQNUtility.formattedString(forTimeDifference: difference)
|
||||
|
||||
let message = [
|
||||
NSLocalizedString("share_hashtag", comment: ""),
|
||||
intensity,
|
||||
NSLocalizedString("share_felt", comment: ""),
|
||||
report.address,
|
||||
time + ".",
|
||||
NSLocalizedString("share_notified", comment: "")
|
||||
].joined(separator: " ")
|
||||
|
||||
let controller = UIActivityViewController(activityItems: [message], applicationActivities: [])
|
||||
present(controller, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - Map
|
||||
|
||||
override func setupAnnotationView(for annotation: MKAnnotation, on mapView: MKMapView) -> MKAnnotationView? {
|
||||
@@ -270,10 +339,16 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
|
||||
return nil
|
||||
}
|
||||
|
||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
|
||||
let identifier = showAnnotationTime ? EQNCustomAnnotationView.SingleLineIdentifier : EQNCustomAnnotationView.SmallIdentifier
|
||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as! EQNCustomAnnotationView
|
||||
|
||||
annotationView.image = annotation.image
|
||||
annotationView.title = annotation.title
|
||||
annotationView.title = annotation.timeDifference
|
||||
annotationView.canShowCallout = true
|
||||
// Psizioniamo più in alto le segnalazioni con intensità maggiore.
|
||||
// Valori maggiori di anchorPointZ mettono la view più in basso,
|
||||
// quindi invertiamo il valore dell'intensità
|
||||
annotationView.layer.anchorPointZ = (1000 - CGFloat(annotation.report?.intensity ?? 0))
|
||||
|
||||
return annotationView
|
||||
}
|
||||
|
||||
@@ -10,15 +10,23 @@ import UIKit
|
||||
|
||||
class SegnalazioniSendReportCell: EQNBaseTableViewCell {
|
||||
|
||||
@IBOutlet private weak var headerLabel: UILabel!
|
||||
@IBOutlet private weak var descriptionLabel: UILabel!
|
||||
@IBOutlet private weak var mildLabel: UILabel!
|
||||
@IBOutlet private weak var mildButton: UIButton!
|
||||
@IBOutlet private weak var strongLabel: UILabel!
|
||||
@IBOutlet private weak var strongButton: UIButton!
|
||||
@IBOutlet private weak var veryStrongLabel: UILabel!
|
||||
@IBOutlet private weak var veryStrongButton: UIButton!
|
||||
@objc var onTapReport: (_ magnitude: Int) -> Void = { _ in }
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
@IBOutlet private weak var headerLabel: UILabel!
|
||||
@IBOutlet private weak var reportMercalli2: UILabel!
|
||||
@IBOutlet private weak var reportMercalli3: UILabel!
|
||||
@IBOutlet private weak var reportMercalli4: UILabel!
|
||||
@IBOutlet private weak var reportMercalli5: UILabel!
|
||||
@IBOutlet private weak var reportMercalli6: UILabel!
|
||||
@IBOutlet private weak var reportMercalli7: UILabel!
|
||||
@IBOutlet private weak var reportMercalli8: UILabel!
|
||||
@IBOutlet private weak var reportMercalli9: UILabel!
|
||||
@IBOutlet private weak var reportMercalli10: UILabel!
|
||||
@IBOutlet private weak var reportMercalli11: UILabel!
|
||||
@IBOutlet private weak var reportMercalli12: UILabel!
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func awakeFromNib() {
|
||||
@@ -31,21 +39,23 @@ class SegnalazioniSendReportCell: EQNBaseTableViewCell {
|
||||
|
||||
private func localizeUI() {
|
||||
headerLabel.text = NSLocalizedString("main_feel", comment: "")
|
||||
descriptionLabel.text = NSLocalizedString("manual_usebutton", comment: "")
|
||||
mildLabel.text = NSLocalizedString("manual_mild", comment: "")
|
||||
strongLabel.text = NSLocalizedString("manual_strong", comment: "")
|
||||
veryStrongLabel.text = NSLocalizedString("manual_verystrong", comment: "")
|
||||
reportMercalli2.text = NSLocalizedString("mercalli_II", comment: "")
|
||||
reportMercalli3.text = NSLocalizedString("mercalli_III", comment: "")
|
||||
reportMercalli4.text = NSLocalizedString("mercalli_IV", comment: "")
|
||||
reportMercalli5.text = NSLocalizedString("mercalli_V", comment: "")
|
||||
reportMercalli6.text = NSLocalizedString("mercalli_VI", comment: "")
|
||||
reportMercalli7.text = NSLocalizedString("mercalli_VII", comment: "")
|
||||
reportMercalli8.text = NSLocalizedString("mercalli_VIII", comment: "")
|
||||
reportMercalli9.text = NSLocalizedString("mercalli_IX", comment: "")
|
||||
reportMercalli10.text = NSLocalizedString("mercalli_X", comment: "")
|
||||
reportMercalli11.text = NSLocalizedString("mercalli_XI", comment: "")
|
||||
reportMercalli12.text = NSLocalizedString("mercalli_XII", comment: "")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
let labels: [UILabel] = [mildLabel, strongLabel, veryStrongLabel]
|
||||
labels.forEach { (label) in
|
||||
label.layer.borderWidth = AppTheme.shared.buttonBorderWidth
|
||||
label.layer.borderColor = AppTheme.shared.buttonBorderColor.cgColor
|
||||
label.layer.cornerRadius = AppTheme.shared.buttonCornerRadius
|
||||
label.clipsToBounds = true
|
||||
}
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func onTapReportButton(_ sender: UIButton) {
|
||||
let magnitude = sender.tag
|
||||
onTapReport(magnitude)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,14 +70,6 @@
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
switch (indexPath.row) {
|
||||
case 0: return 140;
|
||||
default: return UITableViewAutomaticDimension;
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.row == 0) {
|
||||
@@ -87,7 +79,10 @@
|
||||
return cell;
|
||||
}
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ReportEarthquakeCell" forIndexPath:indexPath];
|
||||
SegnalazioniSendReportCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ReportEarthquakeCell" forIndexPath:indexPath];
|
||||
cell.onTapReport = ^(NSInteger magnitude) {
|
||||
[self sendReportTappedWithMagnitude:magnitude];
|
||||
};
|
||||
return cell;
|
||||
}
|
||||
|
||||
@@ -96,7 +91,8 @@
|
||||
- (IBAction)openMapTapped:(id)sender
|
||||
{
|
||||
SegnalazioniMapViewController *controller = [[SegnalazioniMapViewController alloc] init];
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
|
||||
[self presentViewController:navController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)openTwitterTapped:(id)sender
|
||||
@@ -117,7 +113,7 @@
|
||||
[[EQNManager defaultManager] sincronizza];
|
||||
}
|
||||
|
||||
- (IBAction)sendReportTapped:(UIButton *)sender
|
||||
- (void)sendReportTappedWithMagnitude:(NSInteger)magnitude
|
||||
{
|
||||
// check to avoid multiple consecutive reports
|
||||
if ([self.userDefoult objectForKey:CODE_MESSAGE_EQN]) {
|
||||
@@ -133,7 +129,7 @@
|
||||
// ask for user confirmation
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"attention", @"") message:NSLocalizedString(@"manual_sure", nil) preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"manual_yes", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
[self executeSendReportWithMagnitude:sender.tag];
|
||||
[self executeSendReportWithMagnitude:magnitude];
|
||||
}]];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"options_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
@@ -165,9 +161,7 @@
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"report", @"")
|
||||
message:NSLocalizedString(@"manual_ok", @"")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
[self sendComment];
|
||||
}]];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
} failure:^(NSError * error) {
|
||||
@@ -177,42 +171,6 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)sendComment
|
||||
{
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"manual_sendmessage_button" , @"")
|
||||
message:NSLocalizedString(@"manual_sendmessage", @"")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
|
||||
}];
|
||||
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ok" ,@"") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
UITextField * messaggio = alertController.textFields.firstObject;
|
||||
|
||||
NSURL *url = [EQNGeneratoreURLServer urlInvioCommentoTerremoto:messaggio.text codeMessage:[self.userDefoult objectForKey:CODE_MESSAGE_EQN]];
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:url richiesta:EQNTipoChiamataCommentoTerremoto success:^(id result) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"manual_sendmessage_button" , @"")
|
||||
message:NSLocalizedString(@"manual_message_received", @"")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleCancel handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
|
||||
} failure:^(NSError * error) {
|
||||
[self showErrorAlertWithMessage:error.localizedDescription];
|
||||
}];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self refreshUI];
|
||||
});
|
||||
}]];
|
||||
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"options_cancel", @"") style:UIAlertActionStyleCancel handler:nil]];
|
||||
[self presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)showErrorAlertWithMessage:(NSString *)errorMessage
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import UIKit
|
||||
import MapKit
|
||||
import CoreLocation
|
||||
import Shogun
|
||||
|
||||
protocol SeismicNetworkTableViewCellDelegate: AnyObject {
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell)
|
||||
@@ -55,7 +56,7 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
private static let DefaultVerticalSpacing: CGFloat = 6.0
|
||||
private static let DefaultBodyFont = UIFont.preferredFont(forTextStyle: .body)
|
||||
private static let DefaultBodyFontLight = UIFont.preferredFont(for: .body, weight: .light)
|
||||
private static let DefaultBodyFontLight = UIFont.preferredFont(forTextStyle: .body, weight: .light)
|
||||
|
||||
/// Seismic to show
|
||||
private var seismic: EQNSisma?
|
||||
@@ -89,7 +90,7 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
private lazy var placeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = UIFont.preferredFont(for: .title2, weight: .semibold)
|
||||
label.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
|
||||
label.numberOfLines = 3
|
||||
return label
|
||||
}()
|
||||
@@ -505,16 +506,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
updateUI()
|
||||
}
|
||||
|
||||
/// Creates a snapshot of the current cell
|
||||
/// - Returns: Image with the snapshot of the cell
|
||||
public func createSnapshot() -> UIImage {
|
||||
let renderer = UIGraphicsImageRenderer(size: contentView.bounds.size)
|
||||
let image = renderer.image { ctx in
|
||||
contentView.drawHierarchy(in: contentView.bounds, afterScreenUpdates: true)
|
||||
}
|
||||
return image
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc func shareTapped(_ sender: UIButton) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Shogun
|
||||
|
||||
protocol SeismicFiltersViewControllerDelegate: AnyObject {
|
||||
func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController)
|
||||
@@ -66,7 +67,8 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
super.viewDidLoad()
|
||||
|
||||
setupUI()
|
||||
updateUI()
|
||||
loadDataSource()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
@@ -83,7 +85,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
closeButton.setLocalizedTitle(key: "official_close", uppercased: false)
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
private func loadDataSource() {
|
||||
currentMagnitudoMinima = EQNData.magitudoDebole(for: EQNSeismic.shared.magnitudoMinima)
|
||||
if initialMagnitudoMinima == nil {
|
||||
initialMagnitudoMinima = currentMagnitudoMinima
|
||||
@@ -97,7 +99,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
initialQualsiasiMagnitudo = currentSismiQualsiasiMagnitudo
|
||||
}
|
||||
currentModificaImpostazioni = EQNSeismic.shared.modificaImpostazioniAbilitato
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
// MARK: - Table view delegate and data source
|
||||
@@ -111,7 +112,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
|
||||
switch setting.type {
|
||||
case .slider:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: SettingSliderTableViewCell.Identifier, for: indexPath) as! SettingSliderTableViewCell
|
||||
let cell = SettingSliderTableViewCell(style: .default, reuseIdentifier: nil)
|
||||
cell.titleLabel.text = setting.displayTitle
|
||||
|
||||
if indexPath.row == RowIdentifier.magnitudoMinima.rawValue {
|
||||
@@ -120,7 +121,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentMagnitudoMinima = value
|
||||
EQNSeismic.shared.magnitudoMinima = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
cell.dragEnded = { [unowned self] in
|
||||
showWarningAlertIfNeeded(for: currentMagnitudoMinima)
|
||||
@@ -131,7 +131,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentDistanzaMassima = value
|
||||
EQNSeismic.shared.distanzaMassima = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.periodoTemporale.rawValue {
|
||||
cell.configureSlider(with: dataSourcePeriodoTemporale, current: currentPeriodoTemporale)
|
||||
@@ -139,7 +138,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentPeriodoTemporale = value
|
||||
EQNSeismic.shared.periodoTemporale = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.sismiFortiDistanza.rawValue {
|
||||
cell.isDisabled = !currentSismiFortiAbilitati
|
||||
@@ -148,13 +146,12 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiFortiDistanza = value
|
||||
EQNSeismic.shared.sismiFortiMagnitudo = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
return cell
|
||||
case .enable:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: SettingEnableTableViewCell.Identifier, for: indexPath) as! SettingEnableTableViewCell
|
||||
let cell = SettingEnableTableViewCell(style: .default, reuseIdentifier: nil)
|
||||
cell.titleLabel.text = setting.displayTitle
|
||||
cell.detailTextLabel?.text = setting.subtitle
|
||||
|
||||
@@ -164,7 +161,9 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiFortiAbilitati = value
|
||||
EQNSeismic.shared.sismiFortiAbilitati = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
|
||||
loadDataSource()
|
||||
tableView.reloadData()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.sismiQualsiasiMagnitudo.rawValue {
|
||||
cell.toggleSwitch.isOn = currentSismiQualsiasiMagnitudo
|
||||
@@ -172,7 +171,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiQualsiasiMagnitudo = value
|
||||
EQNSeismic.shared.sismiQualsiasiAbilitati = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.modificaImpostazioni.rawValue {
|
||||
cell.toggleSwitch.isOn = currentModificaImpostazioni
|
||||
@@ -180,7 +178,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentModificaImpostazioni = value
|
||||
EQNSeismic.shared.modificaImpostazioniAbilitato = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
import Shogun
|
||||
|
||||
protocol SeismicNetworksMapDetailViewControllerDelegate: AnyObject {
|
||||
func seismicNetworksMapDetailControllerWillUpdateData(_ controller: SeismicNetworksMapDetailViewController, needsDataUpdate: Bool)
|
||||
@@ -107,6 +108,8 @@ class SeismicNetworksMapDetailViewController: EQNBaseMapViewController {
|
||||
}
|
||||
|
||||
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
||||
mapView.deselectAnnotation(annotation, animated: true)
|
||||
|
||||
guard let annotation = annotation as? EQNMapAnnotationSeismic else { return }
|
||||
|
||||
let viewModel = SeismicNetworkViewModel(seismic: annotation.seismic)
|
||||
@@ -162,7 +165,7 @@ class SeismicNetworksMapDetailViewController: EQNBaseMapViewController {
|
||||
// MARK: - Actions
|
||||
|
||||
@objc override func filtersTapped(_ sender: UIGestureRecognizer) {
|
||||
let controller = SeismicFiltersViewController.makeController()
|
||||
let controller = SeismicFiltersViewController.makeViewController()
|
||||
controller.delegate = self
|
||||
controller.modalPresentationStyle = .overCurrentContext
|
||||
controller.modalTransitionStyle = .crossDissolve
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import UIKit
|
||||
import EventKitUI
|
||||
import DZNEmptyDataSet
|
||||
import Shogun
|
||||
|
||||
class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
@@ -317,7 +318,7 @@ extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
|
||||
guard let index = tableView?.indexPath(for: cell), case let .seismic(seismic) = rows[index.row] else { return }
|
||||
|
||||
// create a snapshot of the cell and share with default share sheet
|
||||
let snapshot = cell.createSnapshot()
|
||||
let snapshot = cell.contentView.createSnapshot()
|
||||
|
||||
// text to share with the snapshot
|
||||
let shareHashtag = NSLocalizedString("share_hashtag", comment: "")
|
||||
|
||||
@@ -86,7 +86,12 @@ class SeismicSettingsNetworksViewController: UITableViewController {
|
||||
savedNetworks.append(network.acronym)
|
||||
}
|
||||
|
||||
tableView.reloadRows(at: [indexPath], with: .automatic)
|
||||
// reload all rows with the given acronym
|
||||
let indexes = networks
|
||||
.enumerated()
|
||||
.filter { $0.element.acronym == network.acronym }
|
||||
.map { IndexPath(row: $0.offset, section: 0) }
|
||||
tableView.reloadRows(at: indexes, with: .automatic)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@@ -98,6 +98,12 @@ class SettingSliderTableViewCell: UITableViewCell {
|
||||
let index = Int(sender.value)
|
||||
let item = items[index]
|
||||
|
||||
// make slider with step values
|
||||
let step: Float = 1
|
||||
let roundedValue = round(sender.value / step) * step
|
||||
sender.value = roundedValue
|
||||
|
||||
// update value
|
||||
valueLabel.text = item.display
|
||||
valueChanged?(item)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,11 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
!availableFilters.isEmpty
|
||||
}
|
||||
|
||||
/// If `true` the close button will be shown on top of the map view
|
||||
var isCloseButtonVisible: Bool {
|
||||
true
|
||||
}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
/// Annotations displayed on the map
|
||||
@@ -116,13 +121,14 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
private func setupUI() {
|
||||
view.backgroundColor = .white
|
||||
view.addSubview(mapView)
|
||||
view.addSubview(closeButton)
|
||||
view.addSubview(containerView)
|
||||
if isFilterViewVisible {
|
||||
view.addSubview(filtersView)
|
||||
}
|
||||
|
||||
closeButton.addDefaultConstraint(to: view)
|
||||
if isCloseButtonVisible {
|
||||
view.addSubview(closeButton)
|
||||
closeButton.addDefaultConstraint(to: view)
|
||||
}
|
||||
|
||||
containerView.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor).isActive = true
|
||||
containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
@@ -145,6 +151,8 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
mapView.bottomAnchor.constraint(equalTo: (isFilterViewVisible ? filtersView : containerView).topAnchor).isActive = true
|
||||
|
||||
extraUI()
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
@@ -152,6 +160,7 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
configureUI()
|
||||
registerMapAnnotationViews()
|
||||
loadDataSource()
|
||||
}
|
||||
@@ -167,6 +176,16 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
/// Add extra UI not available in the base class
|
||||
func extraUI() {
|
||||
// nope, subclass will implement some logic
|
||||
}
|
||||
|
||||
/// Configure UI after view initialization
|
||||
func configureUI() {
|
||||
// nope, subclass will implement some logic
|
||||
}
|
||||
|
||||
/// Load data to display on the map
|
||||
func loadDataSource() {
|
||||
// nope, subclass will implement some logic
|
||||
@@ -277,7 +296,5 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
|
||||
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
|
||||
guard let annotation = view.annotation else { return }
|
||||
didTapAnnotation(annotation)
|
||||
|
||||
mapView.deselectAnnotation(annotation, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
import Shogun
|
||||
|
||||
class AlertSimulatorViewController: UIViewController, MKMapViewDelegate {
|
||||
|
||||
@@ -243,7 +244,7 @@ class AlertSimulatorViewController: UIViewController, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
private func navigateToSubscriptions() {
|
||||
let controller = SubscriptionsViewController.makeController()
|
||||
let controller = SubscriptionsViewController.makeViewController()
|
||||
let navigationController = UINavigationController(rootViewController: controller)
|
||||
present(navigationController, animated: true)
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// Costanti+Extensions.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 06/03/21.
|
||||
// Copyright © 2021 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
extension EQNPastquakeIntensity {
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .mild: return NSLocalizedString("widget_mild", comment: "")
|
||||
case .strong: return NSLocalizedString("widget_strong", comment: "")
|
||||
case .veryStrong: return NSLocalizedString("widget_verystring", comment: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
/// Stampa le risposte delle chiamate al server
|
||||
static BOOL const EQNDebugPrintResponse = NO;
|
||||
/// Visualizza schermata con info di debug (ex. push token)
|
||||
static BOOL const EQNEnableDebugView = NO;
|
||||
|
||||
#pragma mark - Urls
|
||||
|
||||
@@ -47,15 +49,15 @@ static NSString * const EQNServerUrlUserLocation = @"https://srv.earthquakenetwo
|
||||
|
||||
static NSString * const EQNServerUrlCalibration = @"https://srv.earthquakenetwork.it/distquake_upload4.php";
|
||||
// download rete smartphone
|
||||
static NSString * const EQNServerUrlDownloadSmartphoneNetwork = @"https://srv.earthquakenetwork.it/distquake_count_redis.php";
|
||||
static NSString * const EQNServerUrlDownloadSmartphoneNetwork = @"https://srv.earthquakenetwork.it/distquake_count_redis2.php";
|
||||
// download area check
|
||||
static NSString * const EQNServerUrlDownloadAreaCheck = @"https://srv.earthquakenetwork.it/distquake_download_areacheck.php";
|
||||
// download pastquakes
|
||||
static NSString * const EQNServerUrlDownloadPastQuakes = @"https://srv.earthquakenetwork.it/distquake_download_pastquakes.php";
|
||||
// download segnalazioni
|
||||
static NSString * const EQNServerUrlDownloadUserReports = @"https://srv.earthquakenetwork.it/distquake_download_manual.php";
|
||||
static NSString * const EQNServerUrlDownloadUserReports = @"https://srv.earthquakenetwork.it/distquake_download_manual3.php";
|
||||
// Invio segnalazione
|
||||
static NSString * const EQNServerUrlSendUserReport = @"https://srv.earthquakenetwork.it/distquake_upload_manual3.php";
|
||||
static NSString * const EQNServerUrlSendUserReport = @"https://srv.earthquakenetwork.it/distquake_upload_manual4.php";
|
||||
static NSString * const EQNServerUrlSendUserReportMessage = @"https://srv.earthquakenetwork.it/distquake_upload_manual_message.php";
|
||||
/// Effettua un test delle notifiche push
|
||||
static NSString * const EQNServerUrlTestAlarm = @"https://srv.earthquakenetwork.it/distquake_upload_testalarm.php";
|
||||
@@ -71,6 +73,11 @@ static NSString * const EQNUserDefaultKeySesmicInformations = @"EQNetwork.Seismi
|
||||
static NSString * const EQNUserDefaultKeyOneShotShowCountry = @"EQNetwork.OneShot.CountrySelection";
|
||||
static NSString * const EQNUserDefaultLastLocation = @"EQNLast_Location";
|
||||
static NSString * const EQNUserDefaultSeismicNetworkCards = @"EQNData.RetiSismiche";
|
||||
static NSString * const EQNUserDefaultRealTimeAlertPayload = @"EQNData.RealtimeAlertPayload";
|
||||
static NSString * const EQNUserDefaultRealTimeAlertDate = @"EQNData.RealtimeAlertDate";
|
||||
|
||||
static NSString * const EQNUserDefaultMigrationV5_3 = @"EQNUserDefaultMigrationV5_3";
|
||||
|
||||
/// Numero di aperture dell'app per sbloccare la versione Pro scontata
|
||||
static NSString * const EQNUserDefaultProDiscountOpenCounter = @"CONTEGGIO_APERTURE_PER_SCONTO";
|
||||
/// Prezzo scontato per la versione pro scaduto
|
||||
@@ -106,6 +113,8 @@ static NSTimeInterval const EQNSeismicDataRefreshInterval = 120.0;
|
||||
static NSTimeInterval const EQNSendReportDelayBetweenMessages = 5.0;
|
||||
/// Tempo di attesa (minuti) per l'invio di due commenti
|
||||
static NSTimeInterval const EQNSendReportDelayBetweenComments = 30.0;
|
||||
/// Tempo (in minuti) entro cui vengono mostrate allerte in tempo reale ricevute
|
||||
static NSTimeInterval const EQNRealtimeAlertExpiration = 480;
|
||||
|
||||
#ifdef DEBUG
|
||||
static NSString * const EQNAdMobAppIdAdaptiveBanner = @"ca-app-pub-3940256099942544/2934735716"; // test
|
||||
@@ -216,11 +225,6 @@ typedef enum : NSInteger {
|
||||
#define NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
|
||||
#define NOTIFICHE_ALLERA_SISMICA_ORA_FINE @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
|
||||
|
||||
// NOTIFICHE RETE SMARTPHONE
|
||||
#define NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA @"NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA"
|
||||
#define NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA @"NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA"
|
||||
#define TEMPO_VISUALIZZAZIONE_NOTIFICA 10800
|
||||
|
||||
|
||||
// FILTRO ENTI
|
||||
#define EQN_MAGNITUDO_MINIMA @"EQN_MAGNITUDO_MINIMA"
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
//
|
||||
// Dictionary+EQNExtensions.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 27/03/21.
|
||||
// Copyright © 2021 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
extension Dictionary {
|
||||
|
||||
func eqn_intValue(for key: Key) -> Int? {
|
||||
if let value = self[key] as? Int {
|
||||
return value
|
||||
} else if let stringValue = self[key] as? String, let value = Int(stringValue) {
|
||||
return value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func eqn_doubleValue(for key: Key) -> Double? {
|
||||
if let value = self[key] as? Double {
|
||||
return value
|
||||
} else if let stringValue = self[key] as? String, let value = Double(stringValue) {
|
||||
return value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
//
|
||||
// UIFont+Extensions.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Busi Andrea on 25/09/2020.
|
||||
// Copyright © 2020 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
extension UIFont {
|
||||
static func preferredFont(for style: TextStyle, weight: Weight) -> UIFont {
|
||||
let metrics = UIFontMetrics(forTextStyle: style)
|
||||
let desc = UIFontDescriptor.preferredFontDescriptor(withTextStyle: style)
|
||||
let font = UIFont.systemFont(ofSize: desc.pointSize, weight: weight)
|
||||
return metrics.scaledFont(for: font)
|
||||
}
|
||||
}
|
||||
@@ -22,3 +22,29 @@ extension UIButton {
|
||||
setTitle(title, for: .normal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension UIImage {
|
||||
class func circle(
|
||||
diameter: CGFloat,
|
||||
color: UIColor,
|
||||
borderWidth: CGFloat = 0.0,
|
||||
borderColor: UIColor = .black
|
||||
) -> UIImage {
|
||||
let size = CGSize(width: diameter, height: diameter)
|
||||
let renderer = UIGraphicsImageRenderer(size: size)
|
||||
let img = renderer.image { ctx in
|
||||
ctx.cgContext.setFillColor(color.cgColor)
|
||||
ctx.cgContext.setStrokeColor(borderColor.cgColor)
|
||||
ctx.cgContext.setLineWidth(borderWidth)
|
||||
|
||||
// reduce circle size to keep space for the border
|
||||
// without this, the image view is cropped
|
||||
let circleDiameter = diameter - 2*borderWidth
|
||||
let rectangle = CGRect(x: borderWidth, y: borderWidth, width: circleDiameter, height: circleDiameter)
|
||||
ctx.cgContext.addEllipse(in: rectangle)
|
||||
ctx.cgContext.drawPath(using: .fillStroke)
|
||||
}
|
||||
return img
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// StoryboardInitializable.swift
|
||||
//
|
||||
// Created by Busi Andrea on 10/11/2020.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
protocol StoryboardInitializable where Self: UIViewController {
|
||||
static var storyboardName: String { get }
|
||||
static var storyboardControllerId: String { get }
|
||||
|
||||
static func makeController() -> Self
|
||||
}
|
||||
|
||||
extension StoryboardInitializable {
|
||||
static func makeController() -> Self {
|
||||
let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle(for: Self.self))
|
||||
guard let controller = storyboard.instantiateViewController(withIdentifier: storyboardControllerId) as? Self else {
|
||||
fatalError("Unable to instantiate controller with anem \(storyboardControllerId)")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
|
||||
|
||||
public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
@@ -18,6 +19,8 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
|
||||
applyDefaultSettings()
|
||||
saveMissingValues()
|
||||
|
||||
migrationV5_3()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -37,4 +40,24 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
UserDefaults.standard.set("600", forKey: NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI)
|
||||
}
|
||||
}
|
||||
|
||||
private func migrationV5_3() {
|
||||
let migrationPerformed = UserDefaults.standard.bool(forKey: EQNUserDefaultMigrationV5_3)
|
||||
if migrationPerformed {
|
||||
print("[EQNUserDefaultsCommand] Migration v5.3 already performed")
|
||||
return
|
||||
}
|
||||
|
||||
// l'ultima posizione era salvata come array, la trasformiamo in valore singolo
|
||||
let lastLocations = EQNUtility.loadArray(of: CLLocation.self, fromUserDefaultsForKey: EQNUserDefaultLastLocation) as? [CLLocation]
|
||||
if let lastLocation = lastLocations?.last {
|
||||
UserDefaults.standard.removeObject(forKey: EQNUserDefaultLastLocation)
|
||||
EQNUserData.shared.saveLastLocation(lastLocation)
|
||||
}
|
||||
|
||||
// resettiamo il Firebase token in modo da ri-eseguire la procedura di registrazione corretta
|
||||
EQNUserData.shared.saveFirebaseToken(nil)
|
||||
|
||||
UserDefaults.standard.set(true, forKey: EQNUserDefaultMigrationV5_3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// EQNRealtimeAlert.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 17/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
import Shogun
|
||||
|
||||
|
||||
@objc
|
||||
class EQNRealtimeAlert: NSObject {
|
||||
|
||||
typealias NotificationPayload = [String: Any]
|
||||
|
||||
/// Title to display
|
||||
var title: String = ""
|
||||
/// Earthquake coordinate
|
||||
let coordinate: CLLocation
|
||||
/// Earthquake intensity
|
||||
let intensity: Int
|
||||
/// Earthquake wave speed
|
||||
let waveSpeed: Double
|
||||
/// Calculated timestamp for earthquake on user position
|
||||
let impactTimestamp: Date
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
@objc
|
||||
init?(notification: [String: Any]) {
|
||||
guard let alert = Self.getPushAlertPayload(from: notification),
|
||||
let coordinate = Self.getCoordinate(from: notification),
|
||||
let impactTimestamp = EQNUtility.calculateUserSeismicTimestamp(fromUserInfo: notification) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.coordinate = coordinate
|
||||
self.impactTimestamp = impactTimestamp
|
||||
if let title = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
|
||||
self.title = String(format: NSLocalizedString(title, comment: ""), arg)
|
||||
}
|
||||
self.intensity = notification.integer(forKey: "intensity", orDefault: 0)
|
||||
self.waveSpeed = notification.double(forKey: "wave_speed", orDefault: 0.0) * 1000 // m/s
|
||||
}
|
||||
|
||||
func distanceFromUser() -> CLLocationDistance {
|
||||
EQNUser.default().lastPosition?.distance(from: coordinate) ?? 0.0
|
||||
}
|
||||
|
||||
/// Remaining time before earthquake gets user position
|
||||
func currentCountdown() -> Int {
|
||||
let now = Date()
|
||||
let difference = lround(max(impactTimestamp.timeIntervalSince(now), 0))
|
||||
return difference
|
||||
}
|
||||
|
||||
@objc
|
||||
func isCountdownExpired() -> Bool {
|
||||
currentCountdown() <= 0
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// Get `aps.alert` object inside a given notification payload
|
||||
/// - Parameter notification: Notification payload
|
||||
/// - Returns: `aps.alert` object if found, nil otherwise
|
||||
static func getPushAlertPayload(
|
||||
from notification: NotificationPayload
|
||||
) -> NotificationPayload? {
|
||||
guard let aps = notification["aps"] as? [String: Any],
|
||||
let alert = aps["alert"] as? [String: Any] else {
|
||||
return nil
|
||||
}
|
||||
return alert
|
||||
}
|
||||
|
||||
/// Retrieve coordinate of earthquake from the notification payload
|
||||
/// - Parameter notification: Notification payload
|
||||
/// - Returns: Coordinate if found, nil otherwise
|
||||
static func getCoordinate(
|
||||
from notification: NotificationPayload
|
||||
) -> CLLocation? {
|
||||
guard let latitude = notification.double(forKey: "latitude"),
|
||||
let longitude = notification.double(forKey: "longitude") else {
|
||||
return nil
|
||||
}
|
||||
return CLLocation(latitude: latitude, longitude: longitude)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Shogun
|
||||
|
||||
|
||||
@objc
|
||||
@@ -14,9 +15,7 @@ class EQNReteSmartphone: NSObject {
|
||||
@objc let counterLastDayAlerts: Int
|
||||
@objc let counterTotalAlerts: Int
|
||||
@objc let counterSmartphones: Int
|
||||
@objc let manualGreen: Int
|
||||
@objc let manualYellow: Int
|
||||
@objc let manualRed: Int
|
||||
@objc let manual: Int
|
||||
@objc let lastSubscriptionDiff: Int
|
||||
@objc let subscriptionsDiscounted: Bool
|
||||
|
||||
@@ -28,30 +27,14 @@ class EQNReteSmartphone: NSObject {
|
||||
return result.merging(dictionary, uniquingKeysWith: { (_, new) in new })
|
||||
}
|
||||
|
||||
self.counterLastDayAlerts = Self.getValue(from: allValues, for: "eq")
|
||||
self.counterTotalAlerts = Self.getValue(from: allValues, for: "eq_p")
|
||||
self.counterSmartphones = Self.getValue(from: allValues, for: "green")
|
||||
self.manualGreen = Self.getValue(from: allValues, for: "g_man")
|
||||
self.manualYellow = Self.getValue(from: allValues, for: "y_man")
|
||||
self.manualRed = Self.getValue(from: allValues, for: "r_man")
|
||||
self.lastSubscriptionDiff = Self.getValue(from: allValues, for: "diff")
|
||||
let subscriptionsDiscounted = Self.getValue(from: allValues, for: "st")
|
||||
self.counterLastDayAlerts = allValues.integer(forKey: "eq", orDefault: 0)
|
||||
self.counterTotalAlerts = allValues.integer(forKey: "eq_p", orDefault: 0)
|
||||
self.counterSmartphones = allValues.integer(forKey: "green", orDefault: 0)
|
||||
self.manual = allValues.integer(forKey: "man", orDefault: 0)
|
||||
self.lastSubscriptionDiff = allValues.integer(forKey: "diff", orDefault: 0)
|
||||
let subscriptionsDiscounted = allValues.integer(forKey: "st", orDefault: 0)
|
||||
self.subscriptionsDiscounted = subscriptionsDiscounted == 1
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
/// This method helps to extract an int value from the received values (where data are both strings and integers).
|
||||
/// If convertion is not possible, it will return zero.
|
||||
private static func getValue(from values: [String: Any], for key: String) -> Int {
|
||||
if let intValue = values[key] as? Int {
|
||||
return intValue
|
||||
}
|
||||
if let stringValue = values[key] as? String, let intValue = Int(stringValue) {
|
||||
return intValue
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,23 +9,15 @@
|
||||
@import Foundation;
|
||||
@import CoreLocation;
|
||||
|
||||
// Intensità terremoti segnalazioni utente
|
||||
typedef NS_CLOSED_ENUM(NSInteger, EQNPastquakeIntensity) {
|
||||
EQNPastquakeIntensityMild = 1,
|
||||
EQNPastquakeIntensityStrong = 2,
|
||||
EQNPastquakeIntensityVeryStrong = 3
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface EQNSegnalazione : NSObject
|
||||
|
||||
@property (nonatomic, strong) CLLocation *coordinate;
|
||||
@property (nonatomic, strong) NSString *address;
|
||||
@property (nonatomic, strong) NSDate *date;
|
||||
@property (nonatomic) NSInteger difference;
|
||||
@property (nonatomic) EQNPastquakeIntensity intensity;
|
||||
@property (nonatomic, strong) NSString *message;
|
||||
// values are from 20 to 120
|
||||
@property (nonatomic) NSInteger intensity;
|
||||
|
||||
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
|
||||
|
||||
|
||||
@@ -17,15 +17,12 @@
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
double latitude = [dictionary[@"latitude"] doubleValue];
|
||||
double longitude = [dictionary[@"longitude"] doubleValue];
|
||||
double latitude = [dictionary[@"la"] doubleValue];
|
||||
double longitude = [dictionary[@"lo"] doubleValue];
|
||||
_coordinate = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
|
||||
_address = dictionary[@"address"];
|
||||
NSDate *date = [EQNUtility getDateFromString:dictionary[@"date"]];
|
||||
NSDate *date = [EQNUtility getDateFromString:dictionary[@"dt"]];
|
||||
_date = date == nil ? [NSDate date] : date;
|
||||
_difference = [dictionary[@"difference"] integerValue];
|
||||
_intensity = [dictionary[@"magnitude"] integerValue];
|
||||
_message = dictionary[@"msg"];
|
||||
_intensity = [dictionary[@"ma"] integerValue];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -34,24 +31,18 @@
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeObject:self.address forKey:@"address"];
|
||||
[encoder encodeObject:self.date forKey:@"date"];
|
||||
[encoder encodeInteger:self.difference forKey:@"difference"];
|
||||
[encoder encodeObject:self.coordinate forKey:@"coordinate"];
|
||||
[encoder encodeInteger:self.intensity forKey:@"intensity"];
|
||||
[encoder encodeObject:self.message forKey:@"message"];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.address = [decoder decodeObjectForKey:@"address"];
|
||||
self.date = [decoder decodeObjectForKey:@"date"];
|
||||
self.difference = [decoder decodeIntegerForKey:@"difference"];
|
||||
self.coordinate = [decoder decodeObjectForKey:@"coordinate"];
|
||||
self.intensity = [decoder decodeIntegerForKey:@"intensity"];
|
||||
self.message = [decoder decodeObjectForKey:@"message"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -15,20 +15,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface EQNUser : NSObject
|
||||
|
||||
@property (nonatomic, strong, nullable) NSString *tokenUser;
|
||||
@property (nonatomic, strong, nullable) NSString *user_ID;
|
||||
@property (nonatomic, strong, nullable) CLLocation *lastPosition;
|
||||
@property (nonatomic, assign) CLLocationDistance distanza;
|
||||
@property (nonatomic, assign) BOOL monitorOn;
|
||||
@property (nonatomic, assign) BOOL inCarica;
|
||||
@property (nonatomic, assign) BOOL registrato;
|
||||
|
||||
+ (instancetype)defaultUser;
|
||||
- (void)inviaPosizioneServer;
|
||||
- (void)saveUserInfo;
|
||||
- (void)removeUser;
|
||||
- (void)verificaRegistrazione;
|
||||
|
||||
- (void)retryUserRegistration;
|
||||
- (void)registerUserIfNeededWithFirebaseToken:(NSString *)firebaseToken;
|
||||
- (void)downloadOfferTimeRemainingWithCompletion:(timeRemainingCompletion)completionHandler;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
|
||||
#import "EQNUser.h"
|
||||
#import "Costanti.h"
|
||||
#import "EQNAccelerometroManager.h"
|
||||
#import "ServerRequest.h"
|
||||
#import "EQNAccelerometroManager.h"
|
||||
#import "EQNGeneratoreURLServer.h"
|
||||
#import "EQNUtility.h"
|
||||
#import "EQNManager.h"
|
||||
|
||||
@interface EQNUser ()
|
||||
@property (strong, nonatomic) NSString *currentFirebaseToken;
|
||||
@property (nonatomic) BOOL registrationInProgress;
|
||||
@end
|
||||
|
||||
@implementation EQNUser
|
||||
|
||||
@@ -35,112 +39,61 @@
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_tokenUser = [[NSUserDefaults standardUserDefaults] objectForKey:EQNUserDefaultUserFirebaseToken];
|
||||
id savedUserId = [[NSUserDefaults standardUserDefaults] objectForKey:EQNUserDefaultUserId];
|
||||
_user_ID = [self convertUserIdIntoString:savedUserId];
|
||||
self.registrationInProgress = NO;
|
||||
self.user_ID = EQNUserData.sharedData.userId;
|
||||
self.lastPosition = EQNUserData.sharedData.lastLocation;
|
||||
|
||||
NSArray *lastPosArray = [EQNUtility loadArrayOfClass:[CLLocation class] fromUserDefaultsForKey:EQNUserDefaultLastLocation];
|
||||
if (lastPosArray.count > 0) {
|
||||
_lastPosition = [lastPosArray lastObject];
|
||||
}
|
||||
|
||||
_registrato = NO;
|
||||
if (_user_ID) {
|
||||
_registrato = YES;
|
||||
}
|
||||
|
||||
[[EQNAccelerometroManager sharedInstance] addObserver:(id)self
|
||||
forKeyPath:@"currentLocation"
|
||||
options:NSKeyValueObservingOptionNew
|
||||
context:nil];
|
||||
|
||||
[[EQNAccelerometroManager sharedInstance] startUpdatingLocationBackground];
|
||||
[self registerForLocationUpdates];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Accessories
|
||||
|
||||
- (void)setTokenUser:(NSString *)tokenUser
|
||||
{
|
||||
// token could be retrieved after some times
|
||||
// thanks to this, we force the server registration when the token is received
|
||||
_tokenUser = tokenUser;
|
||||
[[NSUserDefaults standardUserDefaults] setObject:tokenUser forKey:EQNUserDefaultUserFirebaseToken];
|
||||
[self verificaRegistrazione];
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)saveUserInfo
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setObject:self.tokenUser forKey:EQNUserDefaultUserFirebaseToken];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:self.user_ID forKey:EQNUserDefaultUserId];
|
||||
if (self.lastPosition) {
|
||||
NSArray *lastPosiArray = @[self.lastPosition];
|
||||
[EQNUtility storeArray:lastPosiArray toUserDefaultForKey:EQNUserDefaultLastLocation];
|
||||
}
|
||||
[EQNUserData.sharedData saveFirebaseToken:self.currentFirebaseToken];
|
||||
[EQNUserData.sharedData saveUserId:self.user_ID];
|
||||
[EQNUserData.sharedData saveLastLocation:self.lastPosition];
|
||||
}
|
||||
|
||||
- (void)removeUser
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultUserFirebaseToken];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultUserId];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultLastLocation];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
self.tokenUser = nil;
|
||||
self.currentFirebaseToken = nil;
|
||||
[EQNUserData.sharedData removeAllData];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)retryUserRegistration
|
||||
{
|
||||
if ([keyPath isEqualToString:@"currentLocation"]) {
|
||||
// do some stuff
|
||||
if (self.lastPosition) {
|
||||
self.distanza = [self.lastPosition distanceFromLocation:[EQNAccelerometroManager sharedInstance].currentLocation];
|
||||
}
|
||||
self.lastPosition = [EQNAccelerometroManager sharedInstance].currentLocation;
|
||||
[self verificaRegistrazione];
|
||||
|
||||
if (![EQNManager defaultManager].isBackground)
|
||||
[[EQNAccelerometroManager sharedInstance] stopUpdatingLocation];
|
||||
}
|
||||
[self registerUserIfNeededWithFirebaseToken:self.currentFirebaseToken];
|
||||
}
|
||||
|
||||
- (void)verificaRegistrazione
|
||||
- (void)registerUserIfNeededWithFirebaseToken:(NSString *)firebaseToken
|
||||
{
|
||||
if (!self.user_ID && self.tokenUser) {
|
||||
[self inviaregistrazioneServer:self.tokenUser withPosition:self.lastPosition];
|
||||
self.currentFirebaseToken = firebaseToken;
|
||||
NSString *previousFirebaseToken = EQNUserData.sharedData.firebaseToken;
|
||||
|
||||
// dobbiamo effettuare la registrazione se:
|
||||
// - userId non disponibile (si tratta di prima registrazione)
|
||||
// - i due token di Firebase sono diversi (il token è stato aggiornato)
|
||||
|
||||
if (!self.user_ID) {
|
||||
// prima registrazione dell'utente
|
||||
NSLog(@"[EQNUser] perform first registration");
|
||||
[self performServerRegistrationWithFirebaseToken:firebaseToken existingUserId:nil];
|
||||
} else if (![previousFirebaseToken isEqualToString:firebaseToken]) {
|
||||
// token cambiato, effettuiamo una nuova registrazione
|
||||
NSLog(@"[EQNUser] firebase token is changed, update registration");
|
||||
[self performServerRegistrationWithFirebaseToken:firebaseToken existingUserId:self.user_ID];
|
||||
} else {
|
||||
[self inviaPosizioneServer];
|
||||
// non serve la registrazione, monitorniamo la posizione
|
||||
NSLog(@"[EQNUser] user already registered, start location update");
|
||||
[self registerForLocationUpdates];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)inviaregistrazioneServer:(NSString *)token withPosition:(CLLocation *)location
|
||||
{
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[EQNGeneratoreURLServer urlRegistrazione] richiesta:EQNTipoChiamataRegistrazione success:^(id result) {
|
||||
|
||||
self.user_ID = [self convertUserIdIntoString:result];
|
||||
[self saveUserInfo];
|
||||
|
||||
} failure:^(NSError *errore) {
|
||||
NSLog(@"USER_ID Error %@", errore);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:EQNServerRegistrationDidFailNotification object:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)inviaPosizioneServer
|
||||
{
|
||||
NSLog(@"URLPosizione %@", [EQNGeneratoreURLServer urlPosizione]);
|
||||
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[EQNGeneratoreURLServer urlPosizione] richiesta:EQNTipoChiamataPosizione success:^(id result) {
|
||||
|
||||
NSLog(@"inviato");
|
||||
|
||||
} failure:^(NSError *errore) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)downloadOfferTimeRemainingWithCompletion:(_Nonnull timeRemainingCompletion)completionHandler
|
||||
{
|
||||
NSURL *url = [EQNGeneratoreURLServer urlDownloadOfferTimeRemaining];
|
||||
@@ -160,8 +113,92 @@
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Network
|
||||
|
||||
- (void)performServerRegistrationWithFirebaseToken:(NSString *)token existingUserId:(NSString *)userId
|
||||
{
|
||||
if (self.registrationInProgress) {
|
||||
NSLog(@"[EQNUser] Registration already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
self.registrationInProgress = YES;
|
||||
NSURL *url = [EQNGeneratoreURLServer urlRegistrazioneFirebaseToken:token existingUserId:userId];
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:url richiesta:EQNTipoChiamataRegistrazione success:^(id result) {
|
||||
NSLog(@"[EQNUser] User registration completed");
|
||||
|
||||
// store userId
|
||||
self.registrationInProgress = NO;
|
||||
self.user_ID = [self convertUserIdIntoString:result];
|
||||
[self saveUserInfo];
|
||||
|
||||
// inviamo, se già disponibile, la posizione al server
|
||||
[self performServerSendLocation];
|
||||
} failure:^(NSError *errore) {
|
||||
NSLog(@"[EQNUser] Unable to perform user registration: %@", errore);
|
||||
self.registrationInProgress = NO;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:EQNServerRegistrationDidFailNotification object:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)performServerSendLocation
|
||||
{
|
||||
if (!self.user_ID) {
|
||||
NSLog(@"[EQNUser] User id not available");
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *url = [EQNGeneratoreURLServer urlPosizione];
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:url richiesta:EQNTipoChiamataPosizione success:^(id result) {
|
||||
|
||||
if ([result isKindOfClass:[NSString class]]) {
|
||||
NSString *stringResult = (NSString *)result;
|
||||
if ([stringResult isEqualToString:@"reg"]) {
|
||||
// l'utente non è stato trovato sul server, ri-eseguiamo la registrazione
|
||||
NSLog(@"[EQNUser] User not found, retry registration");
|
||||
[self retryUserRegistration];
|
||||
} else {
|
||||
NSLog(@"[EQNUser] Position saved on server");
|
||||
}
|
||||
}
|
||||
|
||||
[self saveUserInfo];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"[EQNUser] Unable to save position. Error: %@", error.localizedDescription);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)registerForLocationUpdates
|
||||
{
|
||||
[[EQNAccelerometroManager sharedInstance] addObserver:(id)self
|
||||
forKeyPath:@"currentLocation"
|
||||
options:NSKeyValueObservingOptionNew
|
||||
context:nil];
|
||||
|
||||
[[EQNAccelerometroManager sharedInstance] startUpdatingLocationBackground];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if ([keyPath isEqualToString:@"currentLocation"]) {
|
||||
NSLog(@"[EQNUser] currentLocation changed");
|
||||
// do some stuff
|
||||
if (self.lastPosition) {
|
||||
self.distanza = [self.lastPosition distanceFromLocation:[EQNAccelerometroManager sharedInstance].currentLocation];
|
||||
}
|
||||
self.lastPosition = [EQNAccelerometroManager sharedInstance].currentLocation;
|
||||
[self performServerSendLocation];
|
||||
|
||||
if (![EQNManager defaultManager].isBackground) {
|
||||
[[EQNAccelerometroManager sharedInstance] stopUpdatingLocation];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
/// user_id saved as a Number, but is used as a NSString
|
||||
- (NSString *)convertUserIdIntoString:(id)userId
|
||||
{
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// EQNUserData.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 04/11/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
|
||||
|
||||
@objc class EQNUserData: NSObject {
|
||||
|
||||
@objc(sharedData) static let shared = EQNUserData()
|
||||
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@objc
|
||||
var isFirstStart: Bool {
|
||||
firebaseToken == nil
|
||||
}
|
||||
|
||||
// MARK: - Firebase Token
|
||||
|
||||
@objc
|
||||
var firebaseToken: String? {
|
||||
UserDefaults.standard.object(forKey: EQNUserDefaultUserFirebaseToken) as? String
|
||||
}
|
||||
|
||||
@objc
|
||||
func saveFirebaseToken(_ token: String?) {
|
||||
if let token = token {
|
||||
UserDefaults.standard.set(token, forKey: EQNUserDefaultUserFirebaseToken)
|
||||
} else {
|
||||
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserFirebaseToken)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - User id
|
||||
|
||||
@objc
|
||||
var userId: String? {
|
||||
let userId = UserDefaults.standard.object(forKey: EQNUserDefaultUserId)
|
||||
|
||||
// nel corso delle versioni l'id è stato salvato in diversi modi
|
||||
// per evitare problemi, cerchiamo di convertirlo in modi diveri
|
||||
if let userId = userId as? String {
|
||||
return userId
|
||||
} else if let userId = userId as? Int {
|
||||
return "\(userId)"
|
||||
} else if let userId = userId as? NSNumber {
|
||||
return userId.stringValue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@objc
|
||||
func saveUserId(_ userId: String) {
|
||||
UserDefaults.standard.set(userId, forKey: EQNUserDefaultUserId)
|
||||
}
|
||||
|
||||
// MARK: - Last location
|
||||
|
||||
@objc
|
||||
var lastLocation: CLLocation? {
|
||||
guard let encodedLocation = UserDefaults.standard.object(forKey: EQNUserDefaultLastLocation) as? Data else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let location = try? NSKeyedUnarchiver.unarchivedObject(ofClass: CLLocation.self, from: encodedLocation)
|
||||
return location
|
||||
}
|
||||
|
||||
@objc
|
||||
func saveLastLocation(_ location: CLLocation) {
|
||||
guard let encodedLocation = try? NSKeyedArchiver.archivedData(withRootObject: location, requiringSecureCoding: false) else {
|
||||
return
|
||||
}
|
||||
UserDefaults.standard.set(encodedLocation, forKey: EQNUserDefaultLastLocation)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@objc
|
||||
func removeAllData() {
|
||||
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserFirebaseToken)
|
||||
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserId)
|
||||
UserDefaults.standard.removeObject(forKey: EQNUserDefaultLastLocation)
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,10 @@
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSData *data = [defaults objectForKey:keyName];
|
||||
if (!data) {
|
||||
NSLog(@"[EQNUtility] No array saved for key '%@'", keyName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
|
||||
@@ -119,6 +123,10 @@
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSData *data = [defaults objectForKey:keyName];
|
||||
if (!data) {
|
||||
NSLog(@"[EQNUtility] No dictionary saved for key '%@'", keyName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import MapKit
|
||||
import Shogun
|
||||
|
||||
|
||||
@objc
|
||||
@@ -15,36 +16,60 @@ class EQNMapAnnotationUserReport: NSObject, MKAnnotation {
|
||||
|
||||
@objc var coordinate: CLLocationCoordinate2D
|
||||
@objc var title: String?
|
||||
@objc var subtitle: String?
|
||||
@objc var image: UIImage?
|
||||
@objc var timeDifference: String?
|
||||
|
||||
var report: EQNSegnalazione?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
convenience init(report: EQNSegnalazione) {
|
||||
let coordinate = CLLocationCoordinate2D(latitude: report.coordinate.coordinate.latitude, longitude: report.coordinate.coordinate.longitude)
|
||||
let magnitude = report.intensity.rawValue
|
||||
let title = EQNUtility.formattedTimeDifference(from: report.date)
|
||||
let coordinate = report.coordinate.coordinate
|
||||
let magnitude = report.intensity
|
||||
|
||||
self.init(title: title, coordinate: coordinate, magnitude: magnitude)
|
||||
self.init(magnitude: magnitude, coordinate: coordinate)
|
||||
self.report = report
|
||||
self.timeDifference = EQNUtility.formattedTimeDifference(from: report.date)
|
||||
}
|
||||
|
||||
@objc init(title: String, coordinate: CLLocationCoordinate2D, magnitude: Int) {
|
||||
self.title = title
|
||||
self.image = Self.image(for: magnitude)
|
||||
@objc init(
|
||||
magnitude: Int,
|
||||
coordinate: CLLocationCoordinate2D
|
||||
) {
|
||||
self.title = Self.title(for: magnitude)
|
||||
self.subtitle = Self.subtitle(for: magnitude)
|
||||
self.coordinate = coordinate
|
||||
super.init()
|
||||
self.image = Self.image(for: magnitude)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
// MARK: - Helper
|
||||
|
||||
private static func image(for magnitute: Int) -> UIImage? {
|
||||
switch magnitute {
|
||||
case 1: return UIImage(named: "star_report_green")
|
||||
case 2: return UIImage(named: "star_report_yellow")
|
||||
case 3: return UIImage(named: "star_report_red")
|
||||
default: return nil
|
||||
guard let color = UIColor(named: "Mercalli \(magnitute)") else {
|
||||
print("[EQNMapAnnotationUserReport] Unable to get a color for magnitude: \(magnitute)")
|
||||
return nil
|
||||
}
|
||||
|
||||
return UIImage.circle(diameter: EQNCustomAnnotationView.SmallHeight, color: color, borderWidth: 1.0, borderColor: .darkGray)
|
||||
}
|
||||
|
||||
private static func title(for magnitude: Int) -> String {
|
||||
let grade = magnitude / 10
|
||||
let roman = grade.romanNumber()
|
||||
return String(format: NSLocalizedString("mercalli_intensity", comment: ""), roman)
|
||||
}
|
||||
|
||||
private static func subtitle(for magnitude: Int) -> String {
|
||||
let grade = magnitude / 10
|
||||
let roman = grade.romanNumber()
|
||||
let string = NSLocalizedString("mercalli_\(roman)", comment: "")
|
||||
// strings are in the format like "II - Appena percepito"
|
||||
// so we are going to remove the "II" from the string
|
||||
let components = string.components(separatedBy: " - ")
|
||||
if components.count > 1 {
|
||||
return components[1]
|
||||
}
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xCA",
|
||||
"green" : "0xCA",
|
||||
"red" : "0xCA"
|
||||
"blue" : "0.792",
|
||||
"green" : "0.792",
|
||||
"red" : "0.792"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAA",
|
||||
"green" : "0xAA",
|
||||
"red" : "0xAA"
|
||||
"blue" : "0.667",
|
||||
"green" : "0.667",
|
||||
"red" : "0.667"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x51",
|
||||
"green" : "0x90",
|
||||
"red" : "0x00"
|
||||
"blue" : "0.318",
|
||||
"green" : "0.565",
|
||||
"red" : "0.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "250",
|
||||
"green" : "192",
|
||||
"red" : "129"
|
||||
"blue" : "0.980",
|
||||
"green" : "0.753",
|
||||
"red" : "0.506"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.149",
|
||||
"green" : "0.153",
|
||||
"red" : "0.792"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.329",
|
||||
"green" : "0.067",
|
||||
"red" : "0.867"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.529",
|
||||
"green" : "0.024",
|
||||
"red" : "0.792"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.953",
|
||||
"green" : "0.937",
|
||||
"red" : "0.929"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.851",
|
||||
"green" : "0.769",
|
||||
"red" : "0.749"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.890",
|
||||
"green" : "0.843",
|
||||
"red" : "0.671"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.565",
|
||||
"green" : "0.784",
|
||||
"red" : "0.596"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.137",
|
||||
"green" : "0.925",
|
||||
"red" : "0.961"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.059",
|
||||
"green" : "0.765",
|
||||
"red" : "0.937"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.145",
|
||||
"green" : "0.529",
|
||||
"red" : "0.867"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.141",
|
||||
"green" : "0.329",
|
||||
"red" : "0.820"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xCE",
|
||||
"red" : "0xA3"
|
||||
"blue" : "1.000",
|
||||
"green" : "0.808",
|
||||
"red" : "0.639"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.000",
|
||||
"green" : "0.149",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "eq_icon_transparent.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |