Compare commits

...

53 Commits

Author SHA1 Message Date
Andrea Busi 093b6471e8 release: Increase version for release 2023-07-27 17:06:41 +02:00
Andrea Busi 8ca814561b fix: Improve colors in home 2023-07-27 17:06:33 +02:00
Andrea Busi 359667b659 release: Increase version for release 2023-07-24 17:31:39 +02:00
Andrea Busi 468659ee9f refactor: Align card colors with Android app 2023-07-24 17:30:28 +02:00
Andrea Busi ff50abd58a fix: Solve glitch in allerte table 2023-07-24 17:20:27 +02:00
Andrea Busi 4770578ae3 release: Increase version for release 2023-07-21 08:08:55 +02:00
Andrea Busi f0fe102901 feat: Use intensity color for alert card 2023-07-21 08:08:55 +02:00
Andrea Busi 9dacb33736 release: Increase version for release 2023-07-14 17:26:16 +02:00
Andrea Busi aed78e44cd feat: Add background animation in realtime alert 2023-07-14 16:59:58 +02:00
Andrea Busi e531088c86 feat: Add helper class for debug purpose 2023-07-14 16:17:26 +02:00
Andrea Busi 7e0112bf94 refactor: Use new extension method to evaluate difference between dates 2023-07-14 16:17:26 +02:00
Andrea Busi 5d12a86cfe refactor: Move alert expiration login inside new EQNRealtimePushNotification class 2023-07-14 16:17:26 +02:00
Andrea Busi 09e7786e65 feat: Handle realtime alert notification message based on intensity value 2023-07-14 16:17:26 +02:00
Andrea Busi 8671533e91 feat: Store lastLocation in appGroup instead of app user defaults 2023-07-14 16:17:15 +02:00
Andrea Busi 9bd94def0f refactor: Migrate UserDefaults key for app migration 2023-07-14 16:17:15 +02:00
Andrea Busi 29c325b7e2 refactor: Migrate UserDefaults key for user data informations 2023-07-14 16:17:15 +02:00
Andrea Busi 8366f2eabb refactor: Use new UserDefaults constants in NotificationService 2023-07-14 16:17:15 +02:00
Andrea Busi 7e26fee45b refactor: Migrate some UserDefaults from Macro to new constants 2023-07-14 16:17:15 +02:00
Andrea Busi 76d551b847 refactor: Create Swift constants file for UserDefaults 2023-07-14 16:17:15 +02:00
Andrea Busi 8f55553759 refactor: Print notification payload 2023-07-14 16:17:15 +02:00
Andrea Busi b44a0a2e27 refactor: Create a model to handle realtime push notification 2023-07-14 16:17:15 +02:00
Andrea Busi 2b98a4e292 dependency: Update Pods 2023-07-13 17:20:56 +02:00
Andrea Busi 44a27536ad refactor: Remove PurchasePro controller 2023-05-19 17:07:12 +02:00
Andrea Busi 76dcabdc5e fix: Use localized name for time zone in position cell 2023-05-19 17:07:03 +02:00
Andrea Busi 2405be895c refactor: Remove radius and intensity filters for real time notifications
Resolves: https://gitlab.steamware.net/eqn/eqn.ios/-/issues/61
2023-05-19 17:06:54 +02:00
Andrea Busi 89ca785864 refactor: Remove unused logic for Do not disturb notifications 2023-05-19 17:06:32 +02:00
Andrea Busi 60678d0839 refactor: Use proper way to manage plural in localized strings 2023-05-18 12:02:01 +02:00
Andrea Busi 88b36a501d refactor: Align strings with Android app and some reorder 2023-05-18 12:01:26 +02:00
Andrea Busi c5b4448830 refactor: Let Xcode reorganize storyboard 2023-05-18 12:00:43 +02:00
Andrea Busi 58b8960e21 refactor: Remove unused "Convert to pro" cell in allerts 2023-05-18 12:00:43 +02:00
Andrea Busi 49d210eca1 refactor: Remove unused strings 2023-05-12 10:46:14 +02:00
Andrea Busi 068e457297 release: Increase version for release 2023-03-28 18:10:53 +02:00
Andrea Busi 9796a40e0e release: Update changelg 2023-03-28 18:09:40 +02:00
Andrea Busi 01e8996572 refactor: Use new request parameters for network downloads endpoint 2023-03-28 18:09:40 +02:00
Andrea Busi 19c6b3d642 refactor: Move selected seismis networks management to EQNUserData 2023-03-28 18:09:40 +02:00
Andrea Busi 0c63a59f19 feat: Add UOA as seismic network 2023-03-28 18:09:40 +02:00
Andrea Busi f0c56584b8 chore: Update gitignore 2023-03-28 18:09:40 +02:00
Andrea Busi e9961af792 fix: Try to improve ObjC-Swift interoperability 2023-03-24 09:54:39 +01:00
Andrea Busi 806b4b67bf feat: Migrate to new network downloads endpoint and remove weather feature 2023-03-24 09:54:27 +01:00
Andrea Busi 851ece0a3b feat: Migrate smartphone download and subscription counter to new cached endpoints 2023-03-24 09:53:10 +01:00
Andrea Busi 0a76768f88 feat: Migrate user report endpoint to cache 2023-03-24 09:52:21 +01:00
Andrea Busi b15efe83e0 dependency: Rework Firebase configuration, as per official documentation 2023-03-21 18:06:18 +01:00
Andrea Busi d84dc8657a dependency: Update Shogun 2023-03-21 17:58:07 +01:00
Andrea Busi bac5e909bb dependency: Update Pods 2023-03-21 17:55:22 +01:00
Andrea Busi 15088b744f release: Increase version for release 2022-12-30 00:18:07 +01:00
Andrea Busi ac03a0cccb refactor: Update translations for tracking permission 2022-12-30 00:17:57 +01:00
Andrea Busi 76a26e3100 release: Increase version for release 2022-12-07 17:56:52 +01:00
Andrea Busi cac6ed67ac feat: Configure AppTracking and Facebook required flags 2022-12-07 09:26:37 +01:00
Andrea Busi 094c682dbd refactor: Reorganize Firebase configuration 2022-12-07 09:26:03 +01:00
Andrea Busi c44f46ca46 refactor: Reorganize push notification configuration 2022-12-07 09:25:38 +01:00
Andrea Busi 5e8c3d0796 release: Increase version fo release 2022-12-06 09:12:53 +01:00
Andrea Busi 61ce27ed4b feat: Enable Facebook SDK in app 2022-12-02 17:33:42 +01:00
Andrea Busi 3aea60e560 dependency: Add Facebook SDK 2022-12-02 15:18:18 +01:00
83 changed files with 2273 additions and 1700 deletions
+3
View File
@@ -1,3 +1,6 @@
# MacOS files
.DS_Store
# Exclude Pods
Sources/Pods
+19
View File
@@ -1,5 +1,24 @@
# Changelog
## Versione 5.5
- Aggiornata integrazione Firebase
- Migrati alcuni endpooint a cache.earthquakenetwork.it
- Rimossa funzionalità meteo
- Aggiunta rete UOA
- Rimosse stringhe non utilizzate
- Rimosse sezioni non utilizzate (es PRO)
- Aggiunta gestione localizzata plurali
- Rimossi filtri intensità da notifiche in tempo reale
- Rivista gestione notifiche push allerte
- Migrate costanti in nuova struttura Swift
## Versione 5.4
- Aggiunto SDK Facebook
## Versione 5.3.2
- Corretto problema con notifiche critiche
@@ -94,7 +94,7 @@
NSTimeInterval difference = MAX([self.userSeismicTimestamp timeIntervalSinceDate:now], 0);
NSInteger seconds = (int)lround(difference);
self.waveLabel.text = [NSString stringWithFormat:NSLocalizedString(@"alert_wave", @""), seconds];
self.waveLabel.text = [NSString localizedStringWithFormat:NSLocalizedString(@"alert_wave", @""), seconds];
if (difference <= 0) {
// stop the countdown
@@ -7,13 +7,11 @@
//
import UserNotifications
import CoreLocation
import Shogun
class NotificationService: UNNotificationServiceExtension {
// riportiamo queste costanti dall'app bundle, per non dover referenziare file in ObjC
private static let EQNUserDefaultAppGroupSuite = "group.com.finazzi.distquake"
private static let NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS = "NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
private static let EQNSoundNotification = UNNotificationSoundName("alert_sound.wav")
@@ -41,8 +39,7 @@ class NotificationService: UNNotificationServiceExtension {
switch notificationType.lowercased() {
case "eqn":
// check if user has enabled critical alerts
let sharedDefaults = UserDefaults(suiteName: Self.EQNUserDefaultAppGroupSuite)
let criticalAlertsEnabled = sharedDefaults?.bool(forKey: Self.NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS) ?? false
let criticalAlertsEnabled = UserDefaults.appGroup?.bool(forKey: UserDefaults.AllertaSismicaCriticalAlerts) ?? false
// !!WORKAROUND
// this is a workaround to use critical alerts with legacy FCM api
@@ -65,6 +62,36 @@ class NotificationService: UNNotificationServiceExtension {
default:
break
}
// evaluate intensity and get proper string to display
guard let latitude = userInfo.double(forKey: "latitude"),
let longitude = userInfo.double(forKey: "longitude"),
let peak = userInfo.double(forKey: "peak") else {
print("[NotificationService] Unable to get base info for intensity calculation")
return
}
let location = CLLocation(latitude: latitude, longitude: longitude)
guard let distance = EQNUserData.shared.lastLocation?.distance(from: location) else {
print("[NotificationService] Unable to calculate distance or get last location")
return
}
let distanceKm = distance / 1_000
let intensita = peak * exp(-distanceKm/peak/250)
let stringSuffix: String
if intensita < 0.004 {
stringSuffix = "no_shaking"
} else if intensita < 0.30 {
stringSuffix = "mild"
} else if intensita < 0.70 {
stringSuffix = "moderate"
} else {
stringSuffix = "strong"
}
bestAttemptContent.body = "alert_intensity_\(stringSuffix)".localized
case "manual":
// there are 12 levels, so a customized icon doesn't make sense
// use a generic warning icon instead
@@ -178,6 +205,7 @@ class NotificationService: UNNotificationServiceExtension {
case "IGN": return "square\(color).png"
case "UASD", "BDTIM", "NCS": return "thick_star\(color).png"
case "RSPR": return "star6f\(color).png"
case "UOA": return "triangle\(color).png"
default: return ""
}
}
@@ -7,6 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
6502470D2A612E4A001AC512 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6502470C2A612E4A001AC512 /* Constants.swift */; };
6502470E2A6136F0001AC512 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6502470C2A612E4A001AC512 /* Constants.swift */; };
6502470F2A613AD7001AC512 /* EQNUserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65CB83422915720400EE1E35 /* EQNUserData.swift */; };
650247122A61832F001AC512 /* EQNDebugHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650247112A61832F001AC512 /* EQNDebugHelper.swift */; };
650247152A618D7F001AC512 /* Foundation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650247142A618D7F001AC512 /* Foundation+Extensions.swift */; };
650B23AB2632CCD3007AE752 /* UIView+EQNExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650B23AA2632CCD3007AE752 /* UIView+EQNExtensions.swift */; };
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 651901B825F5358700CAFF20 /* EQNMapAnnotationSeismic.swift */; };
6525A82625E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */; };
@@ -26,9 +31,10 @@
6552C13829262119008E723C /* Shogun in Frameworks */ = {isa = PBXBuildFile; productRef = 6552C13729262119008E723C /* Shogun */; };
6552C13A2926261D008E723C /* Shogun in Frameworks */ = {isa = PBXBuildFile; productRef = 6552C1392926261D008E723C /* Shogun */; };
6552C1462926DBA1008E723C /* AppPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6552C1452926DBA1008E723C /* AppPreferences.swift */; };
655839FD261B824200ECA9F9 /* AlertsProVersionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655839FC261B824200ECA9F9 /* AlertsProVersionTableViewCell.swift */; };
65583A05261B83BE00ECA9F9 /* UIKit+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */; };
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */; };
656EB9362A15FD16009DADF3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 656EB9382A15FD16009DADF3 /* Localizable.stringsdict */; };
656EB9412A16288A009DADF3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 656EB9382A15FD16009DADF3 /* Localizable.stringsdict */; };
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 */; };
@@ -43,7 +49,8 @@
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 */; };
65E1226C285C92AA000E294A /* EQNRealtimeAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */; };
65EA58802A60269C0038EE9D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
65EA58822A60360D0038EE9D /* EQNRealtimePushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65EA58812A60360D0038EE9D /* EQNRealtimePushNotification.swift */; };
65FFDC95292F672B00EA821B /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65FFDC94292F672B00EA821B /* NotificationService.swift */; };
65FFDC99292F672B00EA821B /* EQNNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 65FFDC92292F672B00EA821B /* EQNNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
65FFDC9E292F682600EA821B /* Shogun in Frameworks */ = {isa = PBXBuildFile; productRef = 65FFDC9D292F682600EA821B /* Shogun */; };
@@ -237,7 +244,6 @@
DCC23DEF24D28F58003A2404 /* EQNEdgeInsetLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC23DEE24D28F58003A2404 /* EQNEdgeInsetLabel.swift */; };
DCC76BD8251F56050005C4DC /* SeismicCardSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC76BD7251F56050005C4DC /* SeismicCardSettingsViewController.swift */; };
DCC76BE4251F69FB0005C4DC /* EQNUserDefaultsCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC76BE3251F69FB0005C4DC /* EQNUserDefaultsCommand.swift */; };
DCD3E3C024D15576007C78D4 /* PurchaseProVersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD3E3BF24D15576007C78D4 /* PurchaseProVersionViewController.swift */; };
DCD4571C24F6CF0D00B58304 /* EQNGenericValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD4571B24F6CF0D00B58304 /* EQNGenericValue.swift */; };
DCDE0BD924E58CCE00209778 /* EQNMainTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDE0BD824E58CCE00209778 /* EQNMainTabBarController.m */; };
DCEFF21324F5821E009D3FE1 /* SettingDetailTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCEFF21224F5821E009D3FE1 /* SettingDetailTableViewCell.swift */; };
@@ -287,6 +293,9 @@
/* Begin PBXFileReference section */
25A8BFFE29D46740E8A8A7A3 /* Pods_Earthquake_Network.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Earthquake_Network.framework; sourceTree = BUILT_PRODUCTS_DIR; };
40CD2E5581CF2FA3D52F392D /* Pods-Earthquake Network.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Earthquake Network.release.xcconfig"; path = "Pods/Target Support Files/Pods-Earthquake Network/Pods-Earthquake Network.release.xcconfig"; sourceTree = "<group>"; };
6502470C2A612E4A001AC512 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
650247112A61832F001AC512 /* EQNDebugHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNDebugHelper.swift; sourceTree = "<group>"; };
650247142A618D7F001AC512 /* Foundation+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Foundation+Extensions.swift"; sourceTree = "<group>"; };
650B23AA2632CCD3007AE752 /* UIView+EQNExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+EQNExtensions.swift"; sourceTree = "<group>"; };
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>"; };
@@ -302,9 +311,16 @@
654D18C825F93CD700BB6DB0 /* EQNMapAnnotationPastquake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationPastquake.swift; sourceTree = "<group>"; };
6552C1452926DBA1008E723C /* AppPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPreferences.swift; sourceTree = "<group>"; };
6557CBBC26078A1700962757 /* EQNNotificationContent.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EQNNotificationContent.entitlements; sourceTree = "<group>"; };
655839FC261B824200ECA9F9 /* AlertsProVersionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsProVersionTableViewCell.swift; sourceTree = "<group>"; };
65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIKit+Extensions.swift"; sourceTree = "<group>"; };
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkViewModel.swift; sourceTree = "<group>"; };
656EB9372A15FD16009DADF3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
656EB93A2A15FD1B009DADF3 /* hr-HR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "hr-HR"; path = "hr-HR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
656EB93B2A15FD1B009DADF3 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
656EB93C2A15FD1D009DADF3 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "el-GR"; path = "el-GR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
656EB93D2A15FD1E009DADF3 /* id-ID */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "id-ID"; path = "id-ID.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
656EB93E2A15FD1E009DADF3 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
656EB93F2A15FD1F009DADF3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = es; path = es.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
656EB9402A15FD1F009DADF3 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "tr-TR"; path = "tr-TR.lproj/Localizable.stringsdict"; 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>"; };
@@ -329,7 +345,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>"; };
65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNRealtimeAlert.swift; sourceTree = "<group>"; };
65EA58812A60360D0038EE9D /* EQNRealtimePushNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNRealtimePushNotification.swift; sourceTree = "<group>"; };
65FFDC92292F672B00EA821B /* EQNNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = EQNNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
65FFDC94292F672B00EA821B /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
65FFDC96292F672B00EA821B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -557,7 +573,6 @@
DCC23DEE24D28F58003A2404 /* EQNEdgeInsetLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNEdgeInsetLabel.swift; sourceTree = "<group>"; };
DCC76BD7251F56050005C4DC /* SeismicCardSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicCardSettingsViewController.swift; sourceTree = "<group>"; };
DCC76BE3251F69FB0005C4DC /* EQNUserDefaultsCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNUserDefaultsCommand.swift; sourceTree = "<group>"; };
DCD3E3BF24D15576007C78D4 /* PurchaseProVersionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchaseProVersionViewController.swift; sourceTree = "<group>"; };
DCD4571B24F6CF0D00B58304 /* EQNGenericValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNGenericValue.swift; sourceTree = "<group>"; };
DCDE0BD724E58CCE00209778 /* EQNMainTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EQNMainTabBarController.h; sourceTree = "<group>"; };
DCDE0BD824E58CCE00209778 /* EQNMainTabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EQNMainTabBarController.m; sourceTree = "<group>"; };
@@ -813,6 +828,7 @@
isa = PBXGroup;
children = (
8CF66050214C0F7F009F4314 /* Costanti.h */,
6502470C2A612E4A001AC512 /* Constants.swift */,
8CBD3DC52149B9AD0070C963 /* AppDelegate.h */,
8CBD3DC62149B9AD0070C963 /* AppDelegate.m */,
DCB6FBEA24D0B11300ED23B8 /* Controllers */,
@@ -868,6 +884,7 @@
children = (
8C7A3B65225A5EA40045B266 /* NSDictionary+EQNExtensions.h */,
8C7A3B64225A5EA30045B266 /* NSDictionary+EQNExtensions.m */,
650247142A618D7F001AC512 /* Foundation+Extensions.swift */,
65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */,
650B23AA2632CCD3007AE752 /* UIView+EQNExtensions.swift */,
);
@@ -923,6 +940,7 @@
8C10B0C42282360900125C9F /* Info.plist */,
8C4DD4FB228237E000AE77ED /* InfoPlist.strings */,
8C10B0BD2281FE7F00125C9F /* Localizable.strings */,
656EB9382A15FD16009DADF3 /* Localizable.stringsdict */,
8C6CBAE421597E79005C426A /* GoogleService-Info.plist */,
8CBD3DDE2149BA300070C963 /* Earthquake Network.entitlements */,
8CBD3DD32149B9AD0070C963 /* LaunchScreen.storyboard */,
@@ -996,7 +1014,6 @@
DC47D1BB252A0C2B004119F6 /* AlertsPastEartquakesTableViewCell.swift */,
DC7EEE49252A11C9004B4A2A /* AlertsSmartphoneNetworkTableViewCell.swift */,
DC7EEE4E252A1634004B4A2A /* AlertsPriorityServiceTableViewCell.swift */,
655839FC261B824200ECA9F9 /* AlertsProVersionTableViewCell.swift */,
DCF01889252F055800C783F0 /* AlertsPositionDataTableViewCell.swift */,
);
path = Cells;
@@ -1076,8 +1093,9 @@
8C593E89217BA2470008B260 /* EQNSegnalazione.m */,
8CF4F4D9216D44930057110B /* EQNPastquakes.h */,
8CF4F4DA216D44930057110B /* EQNPastquakes.m */,
65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */,
65EA58812A60360D0038EE9D /* EQNRealtimePushNotification.swift */,
6552C1452926DBA1008E723C /* AppPreferences.swift */,
650247112A61832F001AC512 /* EQNDebugHelper.swift */,
);
path = Models;
sourceTree = "<group>";
@@ -1118,7 +1136,6 @@
DCD3E3BE24D1555F007C78D4 /* InApp */ = {
isa = PBXGroup;
children = (
DCD3E3BF24D15576007C78D4 /* PurchaseProVersionViewController.swift */,
DC3BA11024D1A9C90062EE7F /* SubscriptionsViewController.swift */,
DCC23DEB24D281CE003A2404 /* SubscriptionsActiveTableViewCell.swift */,
DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */,
@@ -1390,6 +1407,7 @@
65FFDD6B292F70E800EA821B /* dyamond_yellow.png in Resources */,
65FFDD44292F70E800EA821B /* triround_white.png in Resources */,
65FFDD60292F70E800EA821B /* oct_red.png in Resources */,
65EA58802A60269C0038EE9D /* Localizable.strings in Resources */,
65FFDD57292F70E800EA821B /* star4r_red.png in Resources */,
65FFDD15292F70E800EA821B /* triround_inner_red.png in Resources */,
65FFDD0B292F70E800EA821B /* triangle2_red.png in Resources */,
@@ -1441,6 +1459,7 @@
files = (
8C4DD4F9228237E000AE77ED /* InfoPlist.strings in Resources */,
8CBD3DD52149B9AD0070C963 /* LaunchScreen.storyboard in Resources */,
656EB9362A15FD16009DADF3 /* Localizable.stringsdict in Resources */,
8C10B0B92281FE7F00125C9F /* Localizable.strings in Resources */,
8C6CBAE521597E79005C426A /* GoogleService-Info.plist in Resources */,
DC958D672535788E00D73D4A /* alert_sound.wav in Resources */,
@@ -1456,6 +1475,7 @@
files = (
8CF12CDC21DE49B600613AC5 /* MainInterface.storyboard in Resources */,
8C10B0BB2281FE7F00125C9F /* Localizable.strings in Resources */,
656EB9412A16288A009DADF3 /* Localizable.stringsdict in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1471,29 +1491,41 @@
"${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}/FirebaseCoreExtension/FirebaseCoreExtension.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics/FirebaseCrashlytics.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseSessions/FirebaseSessions.framework",
"${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework",
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
"${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework",
"${BUILT_PRODUCTS_DIR}/PromisesSwift/Promises.framework",
"${BUILT_PRODUCTS_DIR}/Solar/Solar.framework",
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBAEMKit/FBAEMKit.framework/FBAEMKit",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/FBSDKCoreKit",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics.framework/FBSDKCoreKit_Basics",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.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",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseSessions.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Promises.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Solar.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBAEMKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit_Basics.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -1545,6 +1577,8 @@
buildActionMask = 2147483647;
files = (
65FFDC95292F672B00EA821B /* NotificationService.swift in Sources */,
6502470E2A6136F0001AC512 /* Constants.swift in Sources */,
6502470F2A613AD7001AC512 /* EQNUserData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1569,6 +1603,7 @@
6544416B25E9599000C41714 /* EQNDebugViewController.swift in Sources */,
DCF0188A252F055800C783F0 /* AlertsPositionDataTableViewCell.swift in Sources */,
DCBB267E24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift in Sources */,
65EA58822A60360D0038EE9D /* EQNRealtimePushNotification.swift in Sources */,
6525A82625E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift in Sources */,
DC99A50524E66E430071BC9F /* EQNAppearanceCommand.swift in Sources */,
65DBFB7525E2BBF20041CBA6 /* GADTMediumTemplateView.m in Sources */,
@@ -1581,6 +1616,7 @@
652C37BD26092B3C0068EC3B /* FiltersViewModel.swift in Sources */,
DCF9E14F24F6EA07002B6B1D /* EQNSeismicNetwork.swift in Sources */,
DC2814302519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift in Sources */,
650247122A61832F001AC512 /* EQNDebugHelper.swift in Sources */,
65CB83432915720400EE1E35 /* EQNUserData.swift in Sources */,
654D18C425F93C0600BB6DB0 /* PasquakesMapViewController.swift in Sources */,
8C14113721EE502800A59729 /* EQNAllertaSismica.m in Sources */,
@@ -1593,7 +1629,6 @@
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 */,
@@ -1612,14 +1647,13 @@
8CF6604F214C0E58009F4314 /* EQNCalibrazione.m in Sources */,
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */,
DCBB84F0252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift in Sources */,
DCD3E3C024D15576007C78D4 /* PurchaseProVersionViewController.swift in Sources */,
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */,
DC99A50324E66E270071BC9F /* EQNCommandProtocol.swift in Sources */,
DCB45BC8250E86E100DB2D0C /* SeismicSettingsViewController.swift in Sources */,
DCF10DC624D2B8C7009F34C3 /* EQNPurchaseUtility.swift in Sources */,
DC0E551324F8063300D54270 /* SettingSegmentedTableViewCell.swift in Sources */,
650247152A618D7F001AC512 /* Foundation+Extensions.swift in Sources */,
65BBB22C26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift in Sources */,
655839FD261B824200ECA9F9 /* AlertsProVersionTableViewCell.swift in Sources */,
DC47D1BC252A0C2B004119F6 /* AlertsPastEartquakesTableViewCell.swift in Sources */,
654D18C925F93CD700BB6DB0 /* EQNMapAnnotationPastquake.swift in Sources */,
DCEFF21724F58569009D3FE1 /* SettingSectionHeaderView.swift in Sources */,
@@ -1649,6 +1683,7 @@
DC974AFF251748B300A139EC /* SeismicFiltersViewController.swift in Sources */,
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */,
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */,
6502470D2A612E4A001AC512 /* Constants.swift in Sources */,
DCC76BD8251F56050005C4DC /* SeismicCardSettingsViewController.swift in Sources */,
650B23AB2632CCD3007AE752 /* UIView+EQNExtensions.swift in Sources */,
653C67FC25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift in Sources */,
@@ -1695,6 +1730,21 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
656EB9382A15FD16009DADF3 /* Localizable.stringsdict */ = {
isa = PBXVariantGroup;
children = (
656EB9372A15FD16009DADF3 /* en */,
656EB93A2A15FD1B009DADF3 /* hr-HR */,
656EB93B2A15FD1B009DADF3 /* fr */,
656EB93C2A15FD1D009DADF3 /* el-GR */,
656EB93D2A15FD1E009DADF3 /* id-ID */,
656EB93E2A15FD1E009DADF3 /* it */,
656EB93F2A15FD1F009DADF3 /* es */,
656EB9402A15FD1F009DADF3 /* tr-TR */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
};
8C10B0BD2281FE7F00125C9F /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
@@ -1761,7 +1811,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -1778,7 +1828,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
@@ -1803,7 +1853,7 @@
CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
GENERATE_INFOPLIST_FILE = YES;
@@ -1816,7 +1866,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1959,7 +2009,7 @@
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = WJA4MR4CPC;
@@ -1969,7 +2019,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1995,8 +2045,6 @@
"-framework",
"\"FBLPromises\"",
"-framework",
"\"FirebaseAnalytics\"",
"-framework",
"\"FirebaseCore\"",
"-framework",
"\"FirebaseCrashlytics\"",
@@ -2070,7 +2118,7 @@
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
CODE_SIGN_IDENTITY = "Apple Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = WJA4MR4CPC;
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
@@ -2079,7 +2127,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -2105,8 +2153,6 @@
"-framework",
"\"FBLPromises\"",
"-framework",
"\"FirebaseAnalytics\"",
"-framework",
"\"FirebaseCore\"",
"-framework",
"\"FirebaseCrashlytics\"",
@@ -2176,7 +2222,7 @@
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEVELOPMENT_TEAM = WJA4MR4CPC;
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
@@ -2185,7 +2231,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
@@ -2204,7 +2250,7 @@
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 104;
CURRENT_PROJECT_VERSION = 113;
DEVELOPMENT_TEAM = WJA4MR4CPC;
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
@@ -2213,7 +2259,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.3.2;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
@@ -2271,7 +2317,7 @@
repositoryURL = "https://github.com/andreabusi-it/Shogun";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.0.1;
minimumVersion = 1.0.0;
};
};
/* End XCRemoteSwiftPackageReference section */
@@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/andreabusi-it/Shogun",
"state" : {
"revision" : "4120014b7e567296a95cd05a8a801a198f4cdac9",
"version" : "0.5.0"
"revision" : "3ffa7cfbdcbfb9868c853900f63d7e3248db797e",
"version" : "1.1.1"
}
}
],
+75 -26
View File
@@ -18,11 +18,15 @@
#import "EQNNotificheSegnalazioniUtente.h"
#import "EQNNotificheReteSismiche.h"
#import "EQNMainTabBarController.h"
#import "NSDictionary+EQNExtensions.h"
@import Firebase;
@import FirebaseCrashlytics;
@import UserNotifications;
@import AppTrackingTransparency;
@import FirebaseCore;
@import FirebaseMessaging;
@import FirebaseCrashlytics;
@import GoogleMobileAds;
@import FBSDKCoreKit;
@interface AppDelegate () <FIRMessagingDelegate, UNUserNotificationCenterDelegate>
@property (strong, nonatomic) NSArray<id<EQNCommandProtocol>> *commands;
@@ -50,20 +54,14 @@
[EQNUser defaultUser];
[EQNManager defaultManager];
[FIRApp configure];
[FIRMessaging messaging].delegate = self;
[self configureFirebase];
[self configureFacebookSDKWithApplication:application andOptions:launchOptions];
// add some generic logs for Crashlytics
NSString *language = [[NSLocale preferredLanguages] firstObject];
[[FIRCrashlytics crashlytics] setCustomValue:language forKey:@"lang"];
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
[self registraNotifica];
}];
[self configurePushNotifications];
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
[application registerForRemoteNotifications];
@@ -89,9 +87,9 @@
[[EQNManager defaultManager] avviaManager];
[[EQNAccelerometroManager sharedInstance] startUpdatingLocationBackground];
NSUInteger counter = [[NSUserDefaults standardUserDefaults] integerForKey:EQNUserDefaultProDiscountOpenCounter];
NSUInteger counter = [[NSUserDefaults standardUserDefaults] integerForKey:NSUserDefaults.UserDataProDiscountOpenCounter];
counter += 1;
[[NSUserDefaults standardUserDefaults] setInteger:counter forKey:EQNUserDefaultProDiscountOpenCounter];
[[NSUserDefaults standardUserDefaults] setInteger:counter forKey:NSUserDefaults.UserDataProDiscountOpenCounter];
}
@@ -126,7 +124,7 @@
NSString *token = [self stringWithDeviceToken:deviceToken];
NSLog(@"[DEBUG] push token: %@", token);
[[NSUserDefaults standardUserDefaults] setObject:token forKey:EQNUserDefaultPushToken];
[[NSUserDefaults standardUserDefaults] setObject:token forKey:NSUserDefaults.UserDataPushToken];
FIRMessaging.messaging.APNSToken = deviceToken;
}
@@ -149,8 +147,8 @@
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
// execute common logic and refresh the proper tab
NSDictionary *userInfo = notification.request.content.userInfo;
[self handlePushNotificationWithUserInfo:userInfo];
UNNotificationContent *content = notification.request.content;
[self handlePushNotificationWithNotificationContent:content];
// Change this to your preferred presentation option
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
@@ -159,9 +157,11 @@
// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler
{
NSLog(@"[DEBUG] push payload\n%@", [response.notification.request.content.userInfo eqn_jsonStringWithPrettyPrint:YES]);
// execute common logic and refresh the proper tab
NSDictionary *userInfo = response.notification.request.content.userInfo;
[self handlePushNotificationWithUserInfo:userInfo];
UNNotificationContent *content = response.notification.request.content;
[self handlePushNotificationWithNotificationContent:content];
completionHandler();
}
@@ -178,18 +178,24 @@
#pragma mark - Private
- (void)handlePushNotificationWithUserInfo:(NSDictionary *)userInfo
- (void)handlePushNotificationWithNotificationContent:(UNNotificationContent *)content
{
NSString *type = content.userInfo[@"type"];
EQNTabBarSection section = EQNTabBarSectionAllerte;
if ([userInfo[@"type"] isEqualToString:@"eqn"]) {
NSDate *dataRicezione = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:dataRicezione forKey:EQNUserDefaultRealTimeAlertDate];
[EQNUtility storeDictionary:userInfo toUserDefaultForKey:EQNUserDefaultRealTimeAlertPayload];
if ([type isEqualToString:@"eqn"]) {
// Store both original payload and modified title/body
// This will be usefull to avoid to re-evaluate logic for title display.
NSDictionary *notification = @{
@"title": content.title,
@"body": content.body,
@"userInfo": content.userInfo
};
[EQNRealtimePushNotification storeNotificationWithPayload:notification];
section = EQNTabBarSectionAllerte;
} else if([userInfo[@"type"] isEqualToString:@"manual"]) {
} else if([type isEqualToString:@"manual"]) {
section = EQNTabBarSectionSegnalazioni;
} else if([userInfo[@"type"] isEqualToString:@"official"]) {
} else if([type isEqualToString:@"official"]) {
section = EQNTabBarSectionRetiSismiche;
}
@@ -197,6 +203,49 @@
[self.mainTabBarController selectSection:section];
}
#pragma mark - Configurations
- (void)configurePushNotifications
{
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
[self registraNotifica];
[self configureAppTracking];
}];
}
- (void)configureAppTracking
{
if (@available(iOS 14, *)) {
// add a delay otherwise the alert will not be displayed
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
} else {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = NO;
}
}];
});
} else {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
}
}
- (void)configureFirebase
{
[FIRApp configure];
[FIRMessaging messaging].delegate = self;
}
- (void)configureFacebookSDKWithApplication:(UIApplication *)application andOptions:(NSDictionary *)launchOptions
{
[FBSDKApplicationDelegate.sharedInstance application:application didFinishLaunchingWithOptions:launchOptions];
[FBSDKSettings.sharedSettings setIsAdvertiserIDCollectionEnabled:YES];
[FBSDKSettings.sharedSettings setIsAdvertiserIDCollectionEnabled:YES];
}
#pragma mark - FIRMessagingDelegate
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken
@@ -0,0 +1,70 @@
//
// Constants.swift
// Earthquake Network
//
// Created by Andrea Busi on 14/07/23.
// Copyright © 2023 Earthquake Network. All rights reserved.
//
import Foundation
@objc
extension UserDefaults {
// UserDefaults condivisi con l'AppGroup
@objc(appGroupUserDefaults)
static let appGroup = UserDefaults(suiteName: "group.com.finazzi.distquake")
// Impostazioni della sezione `Allerta in tempo reale`
static let AllertaSismicaAbilitato = "NOTIFICHE_ALLERA_SISMICA_ABILITATO"
static let AllertaSismicaCriticalAlerts = "NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
static let AllertaSismicaSismiDaNotificare = "NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE"
static let AllertaSismicaRaggioSismiLievi = "NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI"
static let AllertaSismicaRaggioSismiForti = "NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI"
static let AllertaSismicaImpostaVolume = "NOTIFICHE_ALLERA_SISMICA_IMPOSTA_VOLUME"
static let AllertaSismicaTestaAllarma = "NOTIFICHE_ALLERA_SISMICA_TESTA_ALLARME"
static let AllertaSismicaAbilitaIntervallo = "NOTIFICHE_ALLERA_SISMICA_ABILITA_INTERVALLO"
static let AllertaSismicaOraInizio = "NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
static let AllertaSismicaOraFine = "NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
// Impostazioni della sezione `Notifiche da reti sismiche`
static let NotificheRetiSismicheAbilitato = "NOTIFICHE_ATTIVA_RETI_SISMICHE"
static let NotificheRetiSismicheViciniAbilitato = "NOTIFICHE_ATTIVA_RETI_SISMICHE_VICINE"
static let NotificheRetiSismicheTerremotiFortiAbilitato = "NOTIFICHE_ATTIVA_RETI_TERREMOTI_FORTI"
static let NotificheRetiSismicheDistanzaPosizione = "NOTIFICHE_DISTANZA_POSIZIONE_RETI_SISMICHE"
static let NotificheRetiSismicheEnergiaSisma = "NOTIFICHE_ATTIVA_RETI_ENERGIA_SISMI"
static let NotificheRetiSismicheEnergiaTerremotiForti = "NOTIFICHE_ATTIVA_RETI_ENERGIA_FORTI"
static let NotificheRetiSismicheListaEnti = "NOTIFICHE_ATTIVA_RETI_LISTA_ENTI"
// Impostazioni della sezione `Notifiche segnalazioni utente`
static let NotificheSegnalazioniUtenteAbilitato = "NOTIFICHE_SU_ATTIVA_SEGNALAZIONE_UTENTE"
static let NotificheSegnalazioniUtenteDistanzaPosizione = "NOTIFICHE_SU_DISTANZA_POSIZIONE"
// Messaggio in segnalazione utente
static let UserReportMessage = "DATA_MESSAGE_EQN"
static let UserReportCodeStatus = "CODE_MESSAGE_EQN"
// Proprietà e preferenze dell'utente
/// Ultima posizione conosciuta dell'utente
static let UserDataLastLocation = "EQNLast_Location"
/// Token Firebase dell'utente corrente
static let UserDataFirebaseToken = "EQNToken_User"
/// Server user ID dell'utente corrente
static let UserDataUserId = "EQNUSER_ID"
/// Reti sismiche selezionate
static let UserDataSelectedSeismicNetworks = "IMPOSTAZIONE_ENTI_RETI_SISMICHEI"
/// Token delle notifiche push
static let UserDataPushToken = "EQNetwork.PushToken"
/// Numero di aperture dell'app per sbloccare la versione Pro scontata
static let UserDataProDiscountOpenCounter = "CONTEGGIO_APERTURE_PER_SCONTO"
/// Prezzo scontato per la versione pro scaduto
static let UserDataProDiscountExpired = "PREZZO_SCONTATO_SCADUTO"
// Migrazioni
static let AppMigrationV5_3 = "EQNUserDefaultMigrationV5_3"
static let AppMigrationV5_4 = "EQNUserDefaultMigrationV5_4"
// Notifica allerta salvata
static let RealTimeAlertPayload = "EQNData.RealtimePushNotificationPayload"
static let RealTimeAlertDate = "EQNData.RealtimeAlertDate"
}
@@ -26,7 +26,6 @@
@implementation AllerteViewController
static NSString * const SegueIdentifierProVersion = @"ShowProVersion";
static NSString * const SegueIdentifierPrioritySubscriptions = @"ShowPrioritySubscriptions";
/// Sections inside the app
@@ -36,7 +35,6 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
AllerteTableRowAllertePassate,
AllerteTableRowReteSmartphone,
AllerteTableRowServizioPriorita,
AllerteTableRowVersionePro, // non più visualizzata con passaggio dell'app a pagamento
AllerteTableRowDatiPosizione
};
@@ -104,7 +102,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
- (void)setupUI
{
self.title = [NSLocalizedString(@"tab_network", nil) capitalizedString];
self.tableView.estimatedRowHeight = 600.0;
self.tableView.estimatedRowHeight = 200.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
@@ -117,15 +115,13 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
self.expandeCollapseButton.image = showAllCards ? [UIImage imageNamed:@"navbar-icon-arrow-collapse"] : [UIImage imageNamed:@"navbar-icon-arrow-expand"];
// 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) {
EQNRealtimePushNotification *notification = [EQNRealtimePushNotification storedNotification];
if (notification) {
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 (![notification isCountdownExpired]) {
RealtimeAlertViewController *controller = [[RealtimeAlertViewController alloc] initWithNotification:notification];
if (@available(iOS 13.0, *)) {
controller.modalInPresentation = YES;
}
@@ -162,8 +158,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
- (void)resetRealtimeAlert
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertDate];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertPayload];
[EQNRealtimePushNotification removeStoredNotification];
self.isNotificaAttiva = NO;
}
@@ -267,8 +262,8 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
} else if (tableRow == AllerteTableRowSismiRilevati) {
if (self.isNotificaAttiva) {
AlertsSeismicNotificationExpandedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SeismicNotificationExpandedCell" forIndexPath:indexPath];
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:EQNUserDefaultRealTimeAlertPayload];
cell.notification = info;
EQNRealtimePushNotification *notification = [EQNRealtimePushNotification storedNotification];
cell.notification = notification;
__weak AllerteViewController *weakSelf = self;
cell.onTapClose = ^{
@@ -327,10 +322,6 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
cell.smartphoneNetwork = [EQNManager defaultManager].rete_smartphone;
return cell;
} else if (tableRow == AllerteTableRowVersionePro) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ProVersionCell" forIndexPath:indexPath];
return cell;
} else if (tableRow == AllerteTableRowDatiPosizione) {
AlertsPositionDataTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PositionDataCell" forIndexPath:indexPath];
cell.position = [EQNUser defaultUser].lastPosition;
@@ -349,9 +340,6 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
case AllerteTableRowServizioPriorita:
[self performSegueWithIdentifier:SegueIdentifierPrioritySubscriptions sender:nil];
break;
case AllerteTableRowVersionePro:
[self performSegueWithIdentifier:SegueIdentifierProVersion sender:nil];
break;
default:
break;
}
@@ -43,11 +43,12 @@ class AlertsPositionDataTableViewCell: EQNBaseTableViewCell {
positionLabel.text = EQNUtility.coordinateString(coordinate: position.coordinate)
if let solar = Solar(coordinate: position.coordinate) {
let timeZone = TimeZone.current.localizedName(for: .generic, locale: .current) ?? TimeZone.current.identifier
if let sunrise = solar.sunrise {
sunriseTimeLabel.text = dateFormatter.string(from: sunrise) + " (\(TimeZone.current.identifier))"
sunriseTimeLabel.text = dateFormatter.string(from: sunrise) + " \(timeZone)"
}
if let sunset = solar.sunset {
sunsetTimeLabel.text = dateFormatter.string(from: sunset) + " (\(TimeZone.current.identifier))"
sunsetTimeLabel.text = dateFormatter.string(from: sunset) + " \(timeZone)"
}
}
}
@@ -40,7 +40,24 @@ class AlertsPriorityServiceTableViewCell: EQNBaseTableViewCell {
private func updateUI() {
guard let smartphoneNetwork = smartphoneNetwork else { return }
let formattedTime = EQNUtility.formattedString(forTimeDifference: smartphoneNetwork.lastSubscriptionDiff)
lastSubscriptionLabel.text = String(format: NSLocalizedString("inapp_adv_time", comment: ""), formattedTime)
lastSubscriptionLabel.text = subscriptionText(for: smartphoneNetwork.lastSubscriptionDiff)
}
private func subscriptionText(for time: Int) -> String {
var format = ""
var finalValue = time
// check for minutes, hours or days
if time < 60 {
format = NSLocalizedString("inapp_adv_minutes", comment: "")
} else if time < 1440 {
finalValue = time / 60
format = NSLocalizedString("inapp_adv_hours", comment: "")
} else {
finalValue = time / 1440
format = NSLocalizedString("inapp_adv_days", comment: "")
}
return String.localizedStringWithFormat(format, finalValue)
}
}
@@ -1,30 +0,0 @@
//
// AlertsProVersionTableViewCell.swift
// Earthquake Network
//
// Created by Andrea Busi on 05/04/21.
// Copyright © 2021 Earthquake Network. All rights reserved.
//
import UIKit
class AlertsProVersionTableViewCell: EQNBaseTableViewCell {
@IBOutlet private weak var headerLabel: UILabel!
@IBOutlet private weak var descriptionLabel: UILabel!
// MARK: - View Lifecycle
override func awakeFromNib() {
super.awakeFromNib()
localizeUI()
}
// MARK: - Private
private func localizeUI() {
headerLabel.text = NSLocalizedString("network_pro", comment: "")
descriptionLabel.text = NSLocalizedString("network_topro", comment: "")
}
}
@@ -14,7 +14,7 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
typealias DefaultCompletion = () -> Void
@objc var notification: [String: Any]? {
@objc var notification: EQNRealtimePushNotification? {
didSet {
updateUI()
}
@@ -29,6 +29,7 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
@IBOutlet weak var notificationTitleLabel: UILabel!
@IBOutlet weak var notificationDescriptionLabel: UILabel!
@IBOutlet weak var notificationIntensityLabel: UILabel!
@IBOutlet weak var waveTimeLabel: UILabel!
@IBOutlet weak var mapView: MKMapView! {
didSet {
@@ -52,6 +53,7 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
super.awakeFromNib()
localizeUI()
setUI()
}
// MARK: - Private
@@ -64,56 +66,46 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
descriptionLabel.text = NSLocalizedString("map_smartphone_magnitude", comment: "")
}
private func setUI() {
shareButton.layer.borderColor = AppTheme.Colors.darkGray.cgColor
rateAppButton.layer.borderColor = AppTheme.Colors.darkGray.cgColor
viewOnTwitterButton.layer.borderColor = AppTheme.Colors.darkGray.cgColor
closeButton.layer.borderColor = AppTheme.Colors.darkGray.cgColor
}
private func updateUI() {
// clearn any other previous notifications
notificationTitleLabel.text = ""
notificationDescriptionLabel.text = ""
mapView.removeAnnotations(mapView.annotations)
guard let notification = notification,
let aps = notification["aps"] as? [String: Any],
let alert = aps["alert"] as? [String: Any] else { return }
guard let notification = notification else { return }
let intensity = notification.integer(forKey: "intensity", orDefault: 0)
containerView.backgroundColor = color(for: intensity)
containerView.backgroundColor = backgroundColor(for: notification.relativeIntensity())
notificationTitleLabel.text = notification.title
notificationIntensityLabel.text = notification.displayBody
notificationIntensityLabel.textColor = notification.relativeIntensityColor
if let title = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
notificationTitleLabel.text = String(format: NSLocalizedString(title, comment: ""), arg)
}
// get coordinate
var coordinate: CLLocation?
if let latitude = notification.double(forKey: "latitude"),
let longitude = notification.double(forKey: "longitude") {
if let date = notification.dateTime {
coordinate = CLLocation(latitude: latitude, longitude: longitude)
}
if let coordinate = coordinate,
let counter = notification["counter"],
let dateString = notification["datetime"] as? String,
let date = EQNUtility.getDateFrom(dateString) {
let distance = EQNUser.default().lastPosition?.distance(from: coordinate) ?? 0.0
let distance = EQNUser.default().lastPosition?.distance(from: notification.coordinate) ?? 0.0
let distanceRound = Int(round(distance / 1_000))
let difference = Int(NSDate().timeIntervalSince(date) / 60.0)
notificationDescriptionLabel.text = ""
+ NSLocalizedString("official_card_distance", comment: "") + " \(distanceRound) km"
+ " - " + EQNUtility.formattedString(forTimeDifference: difference)
+ "\n" + String(format: NSLocalizedString("map_number", comment: ""), "\(counter)")
+ "\n" + String(format: NSLocalizedString("map_number", comment: ""), "\(notification.counter)")
}
if let coordinate = coordinate {
let span = MKCoordinateSpan(latitudeDelta: 10.5, longitudeDelta: 10.5)
let region = MKCoordinateRegion(center: coordinate.coordinate, span: span)
mapView.setCenter(coordinate.coordinate, animated: false)
mapView.setRegion(region, animated: true)
let annotation = EQNMapAnnotationPastquake(title: "", coordinate: coordinate.coordinate, intensity: intensity)
mapView.addAnnotation(annotation)
}
let span = MKCoordinateSpan(latitudeDelta: 10.5, longitudeDelta: 10.5)
let region = MKCoordinateRegion(center: notification.coordinate.coordinate, span: span)
mapView.setCenter(notification.coordinate.coordinate, animated: false)
mapView.setRegion(region, animated: true)
let annotation = EQNMapAnnotationPastquake(title: "", coordinate: notification.coordinate.coordinate, intensity: notification.intensity)
mapView.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
@@ -126,15 +118,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
annotationView.title = annotation.title
return annotationView
}
private func color(for intensity: Int) -> UIColor {
switch intensity {
case 0: return UIColor(red: 208.0/255.0, green: 234.0/255.0, blue: 201.0/255.0, alpha:1.0)
case 1: return UIColor(red: 254.0/255.0, green: 252.0/255.0, blue: 203.0/255.0, alpha:1.0)
case 2: return UIColor(red: 254.0/255.0, green: 186.0/255.0, blue: 186.0/255.0, alpha:1.0)
default: return UIColor.white
}
}
// MARK: - Actions
@@ -153,4 +136,19 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
@IBAction private func closeTapped(_ sender: UIButton) {
onTapClose?()
}
// MARK: - Helpers
private func backgroundColor(for intensity: Double) -> UIColor {
switch intensity {
case _ where intensity < 0.004:
return UIColor(named: "Gray (card background)")!
case _ where intensity < 0.30:
return UIColor(named: "Green (card background)")!
case _ where intensity < 0.70:
return UIColor(named: "Yellow (card background)")!
default:
return UIColor(named: "Red (card background)")!
}
}
}
@@ -57,8 +57,8 @@ class EQNDebugViewController: UIViewController {
}
private func loadDebugData() {
let firebaseToken = UserDefaults.standard.string(forKey: EQNUserDefaultUserFirebaseToken) ?? ""
let pushToken = UserDefaults.standard.string(forKey: EQNUserDefaultPushToken) ?? ""
let firebaseToken = UserDefaults.standard.string(forKey: UserDefaults.UserDataFirebaseToken) ?? ""
let pushToken = UserDefaults.standard.string(forKey: UserDefaults.UserDataPushToken) ?? ""
let text =
"""
@@ -65,7 +65,7 @@ static NSString * const SegueIdentifierLogs = @"ShowLogs";
// retry server registration
[[EQNUser defaultUser] retryUserRegistration];
}]];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"options_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"status_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
});
}
@@ -1,181 +0,0 @@
//
// PurchaseProVersionViewController.swift
// Earthquake Network
//
// Created by Busi Andrea on 29/07/2020.
// Copyright © 2020 Earthquake Network. All rights reserved.
//
import UIKit
import SafariServices
import StoreKit
class PurchaseProVersionViewController: UIViewController {
@IBOutlet private weak var containerView: UIView!
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var subtitleLabel: UILabel!
@IBOutlet private weak var discountTextLabel: UILabel!
@IBOutlet private weak var descriptionTextLabel: UILabel!
@IBOutlet private weak var openPrivacyButton: UIButton!
@IBOutlet private weak var openTermsButton: UIButton!
@IBOutlet private weak var payingLabel: UILabel!
@IBOutlet private weak var priceLabel: UILabel!
@IBOutlet private weak var purchaseButton: UIButton!
// MARK: - Internal
private var products = [SKProduct]()
private var proProduct: SKProduct?
private var restoreTapped = false
/// Time remaining (in hours) for discounted price. If zero, no discount available
private var discountTimeRemaining: Int = 0
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(handlePurchaseNotification(_:)),
name: .EQNInAppPurchaseDidComplete,
object: nil)
configureUI()
loadProducts()
checkDiscountPrice()
}
// MARK: - Private
private func configureUI() {
let restoreButton = UIBarButtonItem(title: NSLocalizedString("purchase_pro_restore", comment: ""),
style: .plain,
target: self,
action: #selector(restoreTapped(_:)))
navigationItem.rightBarButtonItem = restoreButton
purchaseButton.isEnabled = false
titleLabel.text = NSLocalizedString("network_pro", comment: "")
subtitleLabel.text = NSLocalizedString("network_pro_subtitle", comment: "")
descriptionTextLabel.text = NSLocalizedString("purchase_pro_description", comment: "")
discountTextLabel.text = NSLocalizedString("purchase_pro_discount", comment: "")
discountTextLabel.isHidden = true
openPrivacyButton.setTitle(NSLocalizedString("network_pro_privacy_disclaimer", comment: ""), for: .normal)
openTermsButton.setTitle(NSLocalizedString("network_pro_terms_conditions", comment: ""), for: .normal)
payingLabel.text = NSLocalizedString("network_pro_paying", comment: "")
purchaseButton.setTitle(NSLocalizedString("network_pro_convert", comment: "").uppercased(), for: .normal)
containerView.eqn_applyShadowAndRoundedCorners()
}
private func updateUI() {
// search for the Pro product
let isDiscountEnabled = discountTimeRemaining > 0
let identifier = isDiscountEnabled ? VersioneProProducts.Identifier.ProVersionDiscounted : VersioneProProducts.Identifier.ProVersionFullPrice
guard let proProduct = products.first(where: { $0.productIdentifier.lowercased() == identifier.lowercased() }) else {
return
}
self.proProduct = proProduct
priceFormatter.locale = proProduct.priceLocale
if isDiscountEnabled {
discountTextLabel.isHidden = false
let string = NSLocalizedString("purchase_pro_discount", comment: "")
discountTextLabel.text = String(format: string, discountTimeRemaining)
}
priceLabel.text = priceFormatter.string(from: proProduct.price)
purchaseButton.isEnabled = true
if UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.ProVersionFullPrice) ||
UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.ProVersionDiscounted) ||
UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.Subscription10kYearly) ||
UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.Subscription10kYearlyDiscounted) ||
UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.Subscription100kYearly) ||
UserDefaults.standard.bool(forKey: VersioneProProducts.Identifier.Subscription100kYearlyDiscounted) {
purchaseButton.isEnabled = false
priceLabel.text = "-"
}
}
private func loadProducts() {
VersioneProProducts.store.requestProducts { [weak self] success, products in
guard let self = self, let products = products, success == true else { return }
self.products = products
self.updateUI()
}
}
private func checkDiscountPrice() {
EQNPurchaseUtility.offerTimeRemaining { (timeRemaining) in
DispatchQueue.main.async {
self.discountTimeRemaining = timeRemaining
self.updateUI()
}
}
}
// MARK: - Actions
@objc func restoreTapped(_ sender: Any) {
restoreTapped = true
VersioneProProducts.store.restorePurchases()
}
@IBAction func purchaseTapped(_ sender: UIButton) {
guard let product = proProduct else { return }
VersioneProProducts.store.buyProduct(product)
}
@IBAction func openExternalLinkTapped(_ sender: UIButton) {
var linkUrl: URL?
if sender == openPrivacyButton {
linkUrl = URL(string: "\(EQNWebsiteAddress)/privacy/")
} else if sender == openTermsButton {
linkUrl = URL(string: "\(EQNWebsiteAddress)/terms-conditions/")
}
if let url = linkUrl {
let controller = SFSafariViewController(url: url)
present(controller, animated: true, completion: nil)
}
}
// MARK: - Notifications
@objc func handlePurchaseNotification(_ notification: Notification) {
guard let productId = notification.object as? String,
products.contains(where: { $0.productIdentifier == productId }) else {
print("[PurchasePro] Unable to find the product")
return
}
if restoreTapped {
restoreTapped = false
let alert = UIAlertController(title: NSLocalizedString("purchase_pro_restore_alert_title", comment: ""),
message: NSLocalizedString("purchase_pro_restore_alert_message", comment: ""),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "ok", style: .default) { [weak self] _ in
self?.navigationController?.popViewController(animated: true)
})
present(alert, animated: true)
} else {
navigationController?.popViewController(animated: true)
}
}
// MARK: - Helper
private var priceFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.formatterBehavior = .behavior10_4
formatter.numberStyle = .currency
return formatter
}()
}
@@ -10,6 +10,52 @@ import UIKit
import MapKit
class RealtimeAlertContainerView: UIView {
lazy var alertView: RealtimeAlertView = {
let view = RealtimeAlertView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var animationColor: UIColor = .white
// MARK: - Init
convenience init() {
self.init(frame: .zero)
configureUI()
}
// MARK: - Private
private func configureUI() {
backgroundColor = .white
addSubview(alertView)
let margin: CGFloat = 24
alertView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: margin).isActive = true
alertView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -margin).isActive = true
alertView.topAnchor.constraint(equalTo: topAnchor, constant: margin).isActive = true
alertView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -margin).isActive = true
}
// MARK: - Public
func startBackgroundAnimation() {
let animation = CABasicAnimation(keyPath: "backgroundColor")
animation.fromValue = UIColor.white.cgColor
animation.toValue = animationColor.cgColor
animation.duration = 2.0
animation.beginTime = CACurrentMediaTime() + 1
animation.autoreverses = true
animation.repeatCount = .infinity
layer.add(animation, forKey: "backgroundColor")
}
}
class RealtimeAlertView: UIView {
let titleLabel: UILabel = {
@@ -25,20 +71,31 @@ class RealtimeAlertView: UIView {
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .preferredFont(forTextStyle: .body)
label.numberOfLines = 0
label.textAlignment = .center
return label
}()
let waveTimeLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .preferredFont(forTextStyle: .title3)
label.font = .preferredFont(forTextStyle: .title2)
label.textColor = AppTheme.Colors.red
label.text = String(format: NSLocalizedString("alert_wave", comment: ""), 0)
label.text = String.localizedStringWithFormat(NSLocalizedString("alert_wave", comment: ""), 0)
label.textAlignment = .center
label.isHidden = true
return label
}()
let intensityLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .preferredFont(forTextStyle: .title3)
label.textColor = AppTheme.Colors.red
label.textAlignment = .center
label.numberOfLines = 2
return label
}()
lazy var mapView: MKMapView = {
let map = MKMapView()
map.translatesAutoresizingMaskIntoConstraints = false
@@ -70,7 +127,6 @@ class RealtimeAlertView: UIView {
addSubview(closeButton)
addSubview(titleLabel)
addSubview(descriptionLabel)
addSubview(waveTimeLabel)
addSubview(mapView)
closeButton.addDefaultConstraint(to: self)
@@ -83,13 +139,20 @@ class RealtimeAlertView: UIView {
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
let stackView = UIStackView(arrangedSubviews: [waveTimeLabel, intensityLabel])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.spacing = 20.0
addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: descriptionLabel.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: descriptionLabel.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 20.0).isActive = true
mapView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
mapView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
mapView.topAnchor.constraint(equalTo: waveTimeLabel.bottomAnchor, constant: 20.0).isActive = true
mapView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 20.0).isActive = true
mapView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
@@ -16,9 +16,12 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
// MARK: - Internal
private let notificationView = RealtimeAlertView()
private let containerView = RealtimeAlertContainerView()
private var notificationView: RealtimeAlertView {
containerView.alertView
}
/// Alert to display
private let realtimeAlert: EQNRealtimeAlert
private let realtimeAlert: EQNRealtimePushNotification
/// Timer to constantly update countdown label
private var countdownTimer: Timer?
/// Refresh time for wave animation
@@ -32,8 +35,8 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
// MARK: - Init
@objc
init(alert: EQNRealtimeAlert) {
self.realtimeAlert = alert
init(notification: EQNRealtimePushNotification) {
self.realtimeAlert = notification
super.init(nibName: nil, bundle: nil)
self.waveAnimationCurrentRadius = currentWavePosition()
@@ -52,7 +55,7 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
// MARK: - View Lifecycle
override func loadView() {
view = notificationView
view = containerView
}
override func viewDidLoad() {
@@ -65,10 +68,19 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
startWaveAnimation()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
containerView.startBackgroundAnimation()
}
// MARK: - Private
private func configureUI() {
notificationView.closeButton.addTarget(self, action: #selector(onTapClose(_:)), for: .touchUpInside)
// configure color for animation
containerView.animationColor = realtimeAlert.relativeIntensityColor
}
private func updateUI() {
@@ -78,7 +90,10 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
let distanceRound = Int(round(realtimeAlert.distanceFromUser() / 1_000))
notificationView.descriptionLabel.text = (notificationView.descriptionLabel.text ?? "")
+ ".\n"
+ String(format: NSLocalizedString("timer_message2_other", comment: ""), distanceRound)
+ String(format: NSLocalizedString("official_distance", comment: ""), distanceRound)
notificationView.intensityLabel.text = realtimeAlert.displayBody
notificationView.intensityLabel.textColor = realtimeAlert.relativeIntensityColor
// center map on the earthquake coordinate
let span = MKCoordinateSpan(latitudeDelta: 10.5, longitudeDelta: 10.5)
@@ -131,7 +146,8 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
@objc private func countdownTimerFired(_ sender: Timer) {
let countdown = realtimeAlert.currentCountdown()
notificationView.waveTimeLabel.text = String(format: NSLocalizedString("alert_wave", comment: ""), countdown)
notificationView.waveTimeLabel.text = String.localizedStringWithFormat(NSLocalizedString("alert_wave", comment: ""), countdown)
notificationView.waveTimeLabel.textColor = waveTimeTextColor(for: countdown)
if countdown <= 0 {
// stop the countdown
@@ -165,4 +181,16 @@ class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
let velocity = realtimeAlert.waveSpeed
return velocity * waveAnimationRefreshRate
}
/// Returns the text color based on impact countdown
private func waveTimeTextColor(for countdown: Int) -> UIColor {
switch countdown {
case _ where countdown > 15:
return UIColor(red: 255.0/255.0, green: 140.0/255.0, blue: 0.0, alpha: 1.0)
case _ where countdown > 5:
return UIColor(red: 255.0/255.0, green: 100.0/255.0, blue: 0.0, alpha: 1.0)
default:
return UIColor(red: 255.0/255.0, green: 0.0/255.0, blue: 0.0, alpha: 1.0)
}
}
}
@@ -46,11 +46,11 @@
{
[super refreshUI];
if ([self.userDefoult objectForKey:DATA_MESSAGE_EQN]){
NSDate *dateMessage = [self.userDefoult objectForKey:DATA_MESSAGE_EQN];
if ([EQNUtility getDifferenceMinute:dateMessage] >= EQNSendReportDelayBetweenComments){
[self.userDefoult removeObjectForKey:DATA_MESSAGE_EQN];
[self.userDefoult removeObjectForKey:CODE_MESSAGE_EQN];
if ([self.userDefoult objectForKey:NSUserDefaults.UserReportMessage]){
NSDate *dateMessage = [self.userDefoult objectForKey:NSUserDefaults.UserReportMessage];
if (![dateMessage isBeforeInterval:EQNSendReportDelayBetweenComments]) {
[self.userDefoult removeObjectForKey:NSUserDefaults.UserReportMessage];
[self.userDefoult removeObjectForKey:NSUserDefaults.UserReportCodeStatus];
}
}
@@ -116,9 +116,9 @@
- (void)sendReportTappedWithMagnitude:(NSInteger)magnitude
{
// check to avoid multiple consecutive reports
if ([self.userDefoult objectForKey:CODE_MESSAGE_EQN]) {
NSDate *dateMessage = [self.userDefoult objectForKey:DATA_MESSAGE_EQN];
if ([EQNUtility getDifferenceMinute:dateMessage] <= EQNSendReportDelayBetweenMessages){
if ([self.userDefoult objectForKey:NSUserDefaults.UserReportCodeStatus]) {
NSDate *dateMessage = [self.userDefoult objectForKey:NSUserDefaults.UserReportMessage];
if (![dateMessage isBeforeInterval:EQNSendReportDelayBetweenMessages]) {
NSString *message = NSLocalizedString(@"manual_wait", @"");
[self showErrorAlertWithMessage:message];
[self performSelectorOnMainThread:@selector(sincronizzazione) withObject:nil waitUntilDone:YES];
@@ -131,7 +131,7 @@
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"manual_yes", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self executeSendReportWithMagnitude:magnitude];
}]];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"options_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"status_cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
@@ -154,8 +154,8 @@
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:url richiesta:EQNTipoChiamataSegnalazioneTerremoto success:^(id result) {
[self.userDefoult setObject:result forKey:CODE_MESSAGE_EQN];
[self.userDefoult setObject:[NSDate date] forKey:DATA_MESSAGE_EQN];
[self.userDefoult setObject:result forKey:NSUserDefaults.UserReportCodeStatus];
[self.userDefoult setObject:[NSDate date] forKey:NSUserDefaults.UserReportMessage];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"report", @"")
@@ -15,7 +15,6 @@ protocol SeismicNetworkTableViewCellDelegate: AnyObject {
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell)
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell)
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell)
func seismicNetworkCellDidTapWeather(_ cell: SeismicNetworkTableViewCell, hasValidWeatherData: Bool)
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkTableViewCell)
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkTableViewCell)
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell)
@@ -45,8 +44,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
case normal
/// Cell with map visible
case mapExpanded
/// Cell with weather info visible
case weatherExpanded
}
/// Delegate
@@ -174,20 +171,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
return mapView
}()
private lazy var weatherImageView: UIImageView = {
let imageView = UIImageView(frame: .zero)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
private lazy var weatherInfoLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.font = Self.DefaultBodyFontLight
return label
}()
// MARK: - Init
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
@@ -345,8 +328,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
let buttonMap = createRoundedButton(title: "🗺", action: #selector(mapTapped(_:)))
stackViewButtons.addArrangedSubview(buttonMap)
let buttonWeather = createRoundedButton(title: "🌤", action: #selector(weatherTapped(_:)))
stackViewButtons.addArrangedSubview(buttonWeather)
let buttonCalendar = createRoundedButton(title: "📆", action: #selector(calendarTapped(_:)))
stackViewButtons.addArrangedSubview(buttonCalendar)
let buttonSettings = createRoundedButton(title: "🔧", action: #selector(settingsTapped(_:)))
@@ -369,32 +350,9 @@ class SeismicNetworkTableViewCell: UITableViewCell {
mapView.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
previousView = mapView
} else if displayType == .weatherExpanded {
let weatherTitleLabel = UILabel()
weatherTitleLabel.translatesAutoresizingMaskIntoConstraints = false
weatherTitleLabel.text = NSLocalizedString("weather_weather", comment: "")
weatherTitleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
containerView.addSubview(weatherTitleLabel)
weatherTitleLabel.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: Self.DefaultVerticalSpacing).isActive = true
weatherTitleLabel.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
weatherTitleLabel.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
containerView.addSubview(weatherInfoLabel)
containerView.addSubview(weatherImageView)
weatherImageView.heightAnchor.constraint(equalToConstant: 60.0).isActive = true
weatherImageView.widthAnchor.constraint(equalTo: weatherImageView.heightAnchor).isActive = true
weatherImageView.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
weatherImageView.trailingAnchor.constraint(equalTo: weatherInfoLabel.leadingAnchor, constant: -8.0).isActive = true
weatherImageView.centerYAnchor.constraint(equalTo: weatherInfoLabel.centerYAnchor).isActive = true
weatherInfoLabel.topAnchor.constraint(equalTo: weatherTitleLabel.bottomAnchor, constant: 4.0).isActive = true
weatherInfoLabel.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
previousView = weatherInfoLabel
}
if (displayType == .mapExpanded || displayType == .weatherExpanded) {
if (displayType == .mapExpanded) {
let buttonClose = createRoundedButton(title: NSLocalizedString("official_close", comment: "").uppercased(), action: #selector(closeTapped(_:)))
containerView.addSubview(buttonClose)
@@ -463,14 +421,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(mapDetailTapped(_:)))
mapView.addGestureRecognizer(tapRecognizer)
} else if displayType == .weatherExpanded {
weatherInfoLabel.text = ""
+ String(format: NSLocalizedString("weather_temperature", comment: ""), seismic.weatherTemperature.doubleValue - EQNMathKelvin) + "\n"
+ String(format: NSLocalizedString("weather_pressure", comment: ""), seismic.weatherPressure) + "\n"
+ String(format: NSLocalizedString("weather_windspeed", comment: ""), seismic.weatherWindSpeed) + "\n"
+ String(format: NSLocalizedString("weather_humidity", comment: ""), seismic.weatherHumidity) + "\n"
+ String(format: NSLocalizedString("weather_clouds", comment: ""), seismic.weatherCloud)
weatherImageView.image = UIImage(named: "weather_\(seismic.weatherIcon).png")
}
}
@@ -516,13 +466,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
delegate?.seismicNetworkCellDidTapMap(self)
}
}
@objc func weatherTapped(_ sender: UIButton) {
if displayType != .weatherExpanded {
let validData = seismic?.weatherCode != nil
delegate?.seismicNetworkCellDidTapWeather(self, hasValidWeatherData: validData)
}
}
@objc func calendarTapped(_ sender: UIButton) {
delegate?.seismicNetworkCellDidTapCalendar(self)
@@ -38,7 +38,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
private var settings = [
SettingItem(type: .slider, title: NSLocalizedString("filter_magnitude", comment: "")),
SettingItem(type: .slider, title: NSLocalizedString("Distanza massima", comment: "")),
SettingItem(type: .slider, title: NSLocalizedString("filter_distance", comment: "")),
SettingItem(type: .slider, title: NSLocalizedString("filter_timeframe", comment: "")),
SettingItem(type: .enable, title: NSLocalizedString("filter_strong", comment: "")),
SettingItem(type: .slider, title: NSLocalizedString("options_strong_magnitude", comment: "")),
@@ -52,7 +52,7 @@ struct SeismicNetworkViewModel {
// distance
let distanceRounded = Int(round(seismic.userDistance))
self.distance = String(format: NSLocalizedString("timer_message2_other", comment: ""), distanceRounded)
self.distance = String(format: NSLocalizedString("official_distance", comment: ""), distanceRounded)
let coordinateText = EQNUtility.coordinateString(coordinate: seismic.coordinate.coordinate)
self.coordinate = "\(coordinateText)"
@@ -44,8 +44,6 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
private var informations = [SeismicNetworkTableViewCell.InformationType]()
/// Index path of row with map expanded
private var openMapIndexPath: IndexPath?
/// Index path of row with weather expanded
private var openWeatherIndexPath: IndexPath?
// MARK: - View Lifecycle
@@ -117,7 +115,6 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
@objc func didReceiveDownloadCompleteNotification(_ sender: Notification) {
self.openMapIndexPath = nil
self.openWeatherIndexPath = nil
DispatchQueue.main.async {
self.refreshUI()
@@ -219,8 +216,6 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
var type = SeismicNetworkTableViewCell.DisplayType.normal
if openMapIndexPath == indexPath {
type = .mapExpanded
} else if openWeatherIndexPath == indexPath {
type = .weatherExpanded
}
cell.configure(with: seismic, type: type, informations: informations)
@@ -331,32 +326,12 @@ extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
present(controller, animated: true)
}
func seismicNetworkCellDidTapWeather(_ cell: SeismicNetworkTableViewCell, hasValidWeatherData: Bool) {
guard let index = tableView?.indexPath(for: cell) else { return }
if !hasValidWeatherData {
let alert = UIAlertController(title: NSLocalizedString("attention", comment: ""),
message: NSLocalizedString("weather_nodata", comment: ""),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("ok", comment: ""), style: .default))
present(alert, animated: true)
return
}
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
openWeatherIndexPath = index
openMapIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
let indexToReloads = [openMapIndexPath, index].compactMap { $0 }
openMapIndexPath = index
openWeatherIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
@@ -379,10 +354,9 @@ extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
let indexToReloads = [openMapIndexPath, index].compactMap { $0 }
openMapIndexPath = nil
openWeatherIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
}
@@ -39,7 +39,8 @@ class SeismicSettingsNetworksViewController: UITableViewController {
networks = EQNData.seismicNetworks().sorted(by: { $0.acronym < $1.acronym })
// load saved selected networks or fill with all available networks
if let savedNetworks = UserDefaults.standard.object(forKey: IMPOSTAZIONE_ENTI_RETI_SISMICHEI) as? [String] {
let savedNetworks = EQNUserData.shared.seismicNetworksSelected()
if !savedNetworks.isEmpty {
self.savedNetworks = savedNetworks
} else {
self.savedNetworks = EQNData.seismicNetworkAcronyms()
@@ -102,7 +103,7 @@ class SeismicSettingsNetworksViewController: UITableViewController {
@IBAction func saveTapped(_ sender: Any) {
// save selected networks
UserDefaults.standard.set(savedNetworks, forKey: IMPOSTAZIONE_ENTI_RETI_SISMICHEI)
EQNUserData.shared.saveSelectedSeismicNetworks(savedNetworks)
// se solo un'ente è selezionato, salviamolo anche come nazione
if savedNetworks.count == 1 {
@@ -54,7 +54,7 @@ class SeismicSettingsViewController: UIViewController {
confirmButton.setLocalizedTitle(key: "official_select_confirm", uppercased: false)
otherwiseLabel.text = NSLocalizedString("official_select_or", comment: "")
manageNetworksButton.setLocalizedTitle(key: "official_select_networks", uppercased: false)
cancelButton.setLocalizedTitle(key: "options_cancel", uppercased: false)
cancelButton.setLocalizedTitle(key: "status_cancel", uppercased: false)
// load saved country (if exists)
let savedCountry = UserDefaults.standard.object(forKey: IMPOSTAZIONE_NAZIONE_RETI_SISMICHE) as? String
@@ -82,7 +82,7 @@ class SeismicSettingsViewController: UIViewController {
// gli enti selezionati conterranno solo l'ente della nazione selezionata
let selectedNetworks = [network.acronym]
UserDefaults.standard.set(selectedNetworks, forKey: IMPOSTAZIONE_ENTI_RETI_SISMICHEI)
EQNUserData.shared.saveSelectedSeismicNetworks(selectedNetworks)
// aggiorniamo le impostazioni di notifica
EQNNotificheReteSismiche.shared().listaEnti = selectedNetworks
@@ -112,7 +112,7 @@ class SeismicSettingsViewController: UIViewController {
let alert = UIAlertController(title: NSLocalizedString("attention", comment: ""),
message: NSLocalizedString("official_select_message", comment: ""),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("options_cancel", comment: ""), style: .cancel))
alert.addAction(UIAlertAction(title: NSLocalizedString("status_cancel", comment: ""), style: .cancel))
alert.addAction(UIAlertAction(title: NSLocalizedString("official_select_confirm", comment: ""), style: .default, handler: { [unowned self] (action) in
self.performSave(for: network)
}))
@@ -14,35 +14,17 @@
@property (nonatomic, strong) NSArray<SettingItem *> *settings;
@property (strong, nonatomic) NSArray<EQNGenericValue *> *dataSourceSismi;
@property (nonatomic, strong) NSArray<EQNGenericValue *> *dataSourceRaggioSisma;
@property (nonatomic, strong) EQNGenericValue *currentSeismicToNotify;
@property (strong, nonatomic) EQNGenericValue *currentLowSeismicRadius;
@property (strong, nonatomic) EQNGenericValue *currentStrongSeismicRadius;
@property (strong, nonatomic) NSDate *currentStartTime;
@property (nonatomic) BOOL isStartTimeExpanded;
@property (strong, nonatomic) NSDate *currentEndTime;
@property (nonatomic) BOOL isEndTimeExpanded;
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, assign) BOOL notificationEnabled;
@property (nonatomic, assign) BOOL criticalAlertsEnabled;
@property (nonatomic, assign) BOOL doNotDisturbEnabled;
@end
@implementation SettingsRealTimeAlertsViewController
typedef NS_ENUM(NSInteger, RowIdentifier) {
RowIdentifierAbilitaNotifiche = 0,
RowIdentifierAbilitaCriticalAlerts,
RowIdentifierSismiDaNotificare,
RowIdentifierRaggioSismiLievi,
RowIndntifierRaggioSismiForti,
RowIdentifierNonDisturbare,
RowIdentifierNonDisturbareOraInizio,
RowIdentifierNonDisturbareOraFine
RowIdentifierAbilitaCriticalAlerts
};
#pragma mark - Accessories
@@ -66,14 +48,8 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
self.settings = @[
[[SettingItem alloc] initWithType:SettingTypeEnable title:NSLocalizedString(@"options_notification_enable_alarm", @"")],
[[SettingItem alloc] initWithType:SettingTypeEnable title:NSLocalizedString(@"critical_alerts_setting", @"")],
[[SettingItem alloc] initWithType:SettingTypeSegmented title:NSLocalizedString(@"options_notification_eqn_intensity", @"") subtitle:NSLocalizedString(@"", @"")],
[[SettingItem alloc] initWithType:SettingTypeSlider title:NSLocalizedString(@"options_radius_mild", @"")],
[[SettingItem alloc] initWithType:SettingTypeSlider title:NSLocalizedString(@"options_radius_strong", @"")]
[[SettingItem alloc] initWithType:SettingTypeEnable title:NSLocalizedString(@"critical_alerts_setting", @"")]
];
self.dataSourceSismi = [EQNData seismicToNotify];
self.dataSourceRaggioSisma = [EQNData raggioSismi];
[self loadDataSource];
[self.tableView reloadData];
@@ -99,27 +75,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
{
self.notificationEnabled = [EQNAllertaSismica sharedInstance].isAbilitato;
self.criticalAlertsEnabled = [EQNAllertaSismica sharedInstance].isCriticalAlertsEnabled;
self.doNotDisturbEnabled = [EQNAllertaSismica sharedInstance].isintervalloAllarme;
// sismi da notificare
EQNGenericValue *sismiDaNotificare = [EQNData seismicToNotifyFor:[EQNAllertaSismica sharedInstance].sismiDaNotificare];
self.currentSeismicToNotify = sismiDaNotificare;
// raggio sismi lievi
EQNGenericValue *raggioSismiLievi = [EQNData raggioSismaFor:[EQNAllertaSismica sharedInstance].raggioSismiLievi];
self.currentLowSeismicRadius = raggioSismiLievi;
// raggio sismi forti
EQNGenericValue *raggioSismiForti = [EQNData raggioSismaFor:[EQNAllertaSismica sharedInstance].raggioSismiForti];
self.currentStrongSeismicRadius = raggioSismiForti;
// non disturbare, orari
NSDate *startTime = [EQNData doNotDisturbEndDateFrom:[EQNAllertaSismica sharedInstance].oraioInizio];
self.currentStartTime = startTime;
NSDate *endTime = [EQNData doNotDisturbEndDateFrom:[EQNAllertaSismica sharedInstance].orarioFine];
self.currentEndTime = endTime;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
}
@@ -172,89 +128,22 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self.tableView reloadData];
};
} else if (indexPath.row == RowIdentifierNonDisturbare) {
cell.toggleSwitch.on = self.doNotDisturbEnabled;
cell.isDisabled = !self.notificationEnabled;
cell.valueChanged = ^(BOOL enabled) {
self.doNotDisturbEnabled = enabled;
[EQNAllertaSismica sharedInstance].isintervalloAllarme = self.doNotDisturbEnabled;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self.tableView reloadData];
};
}
return cell;
} else if (setting.type == SettingTypeSegmented) {
SettingSegmentedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SettingSegmentedTableViewCell.Identifier forIndexPath:indexPath];
cell.titleLabel.text = setting.displayTitle;
if (indexPath.row == RowIdentifierSismiDaNotificare) {
cell.isDisabled = !self.notificationEnabled;
[cell configureControlWith:self.dataSourceSismi current:self.currentSeismicToNotify];
cell.valueChanged = ^(EQNGenericValue *item) {
[self updateSismicToNotify:item];
};
}
return cell;
} else if (setting.type == SettingTypeSlider) {
SettingSliderTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SettingSliderTableViewCell.Identifier forIndexPath:indexPath];
cell.titleLabel.text = setting.displayTitle;
if (indexPath.row == RowIdentifierRaggioSismiLievi) {
cell.isDisabled = !self.notificationEnabled;
[cell configureSliderWith:self.dataSourceRaggioSisma current:self.currentLowSeismicRadius];
cell.valueChanged = ^(EQNGenericValue *item) {
[self updateLowSeismicRadius:item];
};
} else if (indexPath.row == RowIndntifierRaggioSismiForti) {
cell.isDisabled = !self.notificationEnabled;
[cell configureSliderWith:self.dataSourceRaggioSisma current:self.currentStrongSeismicRadius];
cell.valueChanged = ^(EQNGenericValue *item) {
[self updateStrongSeismicRadius:item];
};
}
return cell;
} else if (setting.type == SettingTypeDate) {
SettingDateTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SettingDateTableViewCell.Identifier forIndexPath:indexPath];
cell.isDisabled = !self.doNotDisturbEnabled || !self.notificationEnabled;
cell.userInteractionEnabled = self.doNotDisturbEnabled && self.notificationEnabled;
cell.titleLabel.text = setting.title;
if (indexPath.row == RowIdentifierNonDisturbareOraInizio) {
cell.isPickerVisible = self.isStartTimeExpanded;
[cell updateDate:self.currentStartTime];
cell.valuesLabel.text = [self.dateFormatter stringFromDate:self.currentStartTime];
cell.valueChanged = ^(NSDate *date) {
[self updateStartTime:date];
};
} else if (indexPath.row == RowIdentifierNonDisturbareOraFine) {
cell.isPickerVisible = self.isEndTimeExpanded;
[cell updateDate:self.currentEndTime];
cell.valuesLabel.text = [self.dateFormatter stringFromDate:self.currentEndTime];
cell.valueChanged = ^(NSDate *date) {
[self updateEndTime:date];
};
}
return cell;
}
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == RowIdentifierNonDisturbareOraInizio) {
self.isStartTimeExpanded = !self.isStartTimeExpanded;
} else if (indexPath.row == RowIdentifierNonDisturbareOraFine) {
self.isEndTimeExpanded = !self.isEndTimeExpanded;
}
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Private
- (void)updateSismicToNotify:(EQNGenericValue *)seismic
@@ -265,38 +154,6 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
[self loadDataSource];
}
- (void)updateLowSeismicRadius:(EQNGenericValue *)radius
{
[EQNAllertaSismica sharedInstance].raggioSismiLievi = radius.value;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self loadDataSource];
}
- (void)updateStrongSeismicRadius:(EQNGenericValue *)radius
{
[EQNAllertaSismica sharedInstance].raggioSismiForti = radius.value;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self loadDataSource];
}
- (void)updateStartTime:(NSDate *)date
{
[EQNAllertaSismica sharedInstance].oraioInizio = date;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self loadDataSource];
}
- (void)updateEndTime:(NSDate *)date
{
[EQNAllertaSismica sharedInstance].orarioFine = date;
[[EQNAllertaSismica sharedInstance] saveUserInfo];
[self loadDataSource];
}
- (void)askForCriticalAlertsPermission
{
UNAuthorizationOptions authOptions = UNAuthorizationOptionCriticalAlert;
@@ -268,7 +268,7 @@ class EQNBaseMapViewController: EQNBaseViewController, MKMapViewDelegate {
self.applyFilter(filter)
}))
}
sheet.addAction(UIAlertAction(title: NSLocalizedString("options_cancel", comment: ""), style: .cancel, handler: nil))
sheet.addAction(UIAlertAction(title: NSLocalizedString("status_cancel", comment: ""), style: .cancel, handler: nil))
present(sheet, animated: true, completion: nil)
}
+7 -60
View File
@@ -33,11 +33,9 @@ static double const EQNMathKelvin = 273.15;
#pragma mark - Server APIs
/// Download reti sismiche
static NSString * const EQNServerUrlDownloadRetiSismiche = @"https://srv.earthquakenetwork.it/distquake_download_automatic18%@.php";
static NSString * const EQNServerUrlDownloadRetiSismiche = @"https://cache.earthquakenetwork.it/distquake_download_automatic21.php%@";
/// Recupera il tempo ancora disponibile per la versione Pro scontata
static NSString * const EQNServerUrlOfferTimeRemaining = @"https://srv.earthquakenetwork.it/distquake_download_offer_time_remaining.php";
/// Recupera il numero di sottoscrizioni ancora disponibili per ogni prodotto
static NSString * const EQNServerUrlAvailableSubscriptionsCounter = @"https://srv.earthquakenetwork.it/distquake_count_top_redis.php";
/// Registra l'abbonamento acquistato dall'utente
static NSString * const EQNServerUrlRegisterSubscription = @"https://srv.earthquakenetwork.it/distquake_upload_subscription.php";
/// Carica le impostazioni delle notifiche definite dall'utente
@@ -49,13 +47,13 @@ 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_redis2.php";
static NSString * const EQNServerUrlDownloadSmartphoneNetwork = @"https://cache.earthquakenetwork.it/distquake_count_redis3.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_manual3.php";
static NSString * const EQNServerUrlDownloadUserReports = @"https://cache.earthquakenetwork.it/distquake_download_manual3.php";
// Invio segnalazione
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";
@@ -66,30 +64,12 @@ static NSString * const EQNServerUrlAlertSimulator = @"https://srv.earthquakenet
#pragma mark - UserDefaults Keys
static NSString * const EQNUserDefaultAppGroupSuite = @"group.com.finazzi.distquake";
static NSString * const EQNUserDefaultKeyAlertsShowAllCards = @"EQNetwork.AlertsShowAllCards";
static NSString * const EQNUserDefaultKeySesmicInformations = @"EQNetwork.SeismicInformations";
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 EQNUserDefaultUserReportExpandedView = @"EQNData.UserReportExpandedView";
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
static NSString * const EQNUserDefaultProDiscountExpired = @"PREZZO_SCONTATO_SCADUTO";
/// Token Firebase dell'utente corrente
static NSString * const EQNUserDefaultUserFirebaseToken = @"EQNToken_User";
/// Server user ID dell'utente corrente
static NSString * const EQNUserDefaultUserId = @"EQNUSER_ID";
/// Token delle notifiche push
static NSString * const EQNUserDefaultPushToken = @"EQNetwork.PushToken";
#pragma mark - NSNotification
/// Notifica di fallimento registrazione al server (user_id non ricavato)
@@ -110,12 +90,10 @@ static NSNotificationName const EQNDebugLogWillUpdateNotification = @"EQNDebugLo
#pragma mark - Other constants
static NSTimeInterval const EQNSeismicDataRefreshInterval = 120.0;
/// Tempo di attesa (minuti) tra l'invio di due segnalazioni
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;
/// Tempo di attesa (secondi) tra l'invio di due segnalazioni
static NSTimeInterval const EQNSendReportDelayBetweenMessages = 300.0; // 5 minuti
/// Tempo di attesa (secondi) per l'invio di due commenti
static NSTimeInterval const EQNSendReportDelayBetweenComments = 900.0; // 30 minuti
#ifdef DEBUG
static NSString * const EQNAdMobAppIdAdaptiveBanner = @"ca-app-pub-3940256099942544/2934735716"; // test
@@ -192,40 +170,9 @@ typedef enum : NSInteger {
nonCalibrato
} EQNStatoCal;
//////////////////////////////////////// SEGNALAZIONE MANUALE TERREMOTI ////////////////////////////////////////
#define CODE_MESSAGE_EQN @"CODE_MESSAGE_EQN"
#define DATA_MESSAGE_EQN @"DATA_MESSAGE_EQN"
/////////////////// Segnalazioni Utente ////////////////////////////
#define NOTIFICHE_SU_DISTANZA_POSIZIONE @"NOTIFICHE_SU_DISTANZA_POSIZIONE"
#define NOTIFICHE_SU_ATTIVA_SEGNALAZIONE_UTENTE @"NOTIFICHE_SU_ATTIVA_SEGNALAZIONE_UTENTE"
/////////////////// Reti sismiche ////////////////////////////
#define NOTIFICHE_DISTANZA_POSIZIONE_RETI_SISMICHE @"NOTIFICHE_DISTANZA_POSIZIONE_RETI_SISMICHE"
#define NOTIFICHE_ATTIVA_RETI_SISMICHE @"NOTIFICHE_ATTIVA_RETI_SISMICHE"
#define NOTIFICHE_ATTIVA_RETI_SISMICHE_VICINE @"NOTIFICHE_ATTIVA_RETI_SISMICHE_VICINE"
#define NOTIFICHE_ATTIVA_RETI_TERREMOTI_FORTI @"NOTIFICHE_ATTIVA_RETI_TERREMOTI_FORTI"
#define NOTIFICHE_ATTIVA_RETI_ENERGIA_SISMI @"NOTIFICHE_ATTIVA_RETI_ENERGIA_SISMI"
#define NOTIFICHE_ATTIVA_RETI_ENERGIA_FORTI @"NOTIFICHE_ATTIVA_RETI_ENERGIA_FORTI"
#define NOTIFICHE_ATTIVA_RETI_LISTA_ENTI @"NOTIFICHE_ATTIVA_RETI_LISTA_ENTI"
// Sigla della rete sismica selezionata
#define IMPOSTAZIONE_NAZIONE_RETI_SISMICHE @"IMPOSTAIONE_NAZIONE_RETI_SISMICHE"
#define IMPOSTAZIONE_ENTI_RETI_SISMICHEI @"IMPOSTAZIONE_ENTI_RETI_SISMICHEI"
/////////////////// Allera sismica ////////////////////////////
#define NOTIFICHE_ALLERA_SISMICA_ABILITATO @"NOTIFICHE_ALLERA_SISMICA_ABILITATO"
#define NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS @"NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
#define NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE @"NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE"
#define NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI @"NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI"
#define NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI @"NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI"
#define NOTIFICHE_ALLERA_SISMICA_IMPOSTA_VOLUME @"NOTIFICHE_ALLERA_SISMICA_IMPOSTA_VOLUME"
#define NOTIFICHE_ALLERA_SISMICA_TESTA_ALLARME @"NOTIFICHE_ALLERA_SISMICA_TESTA_ALLARME"
#define NOTIFICHE_ALLERA_SISMICA_ABILITA_INTERVALLO @"NOTIFICHE_ALLERA_SISMICA_ABILITA_INTERVALLO"
#define NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
#define NOTIFICHE_ALLERA_SISMICA_ORA_FINE @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
// FILTRO ENTI
#define EQN_MAGNITUDO_MINIMA @"EQN_MAGNITUDO_MINIMA"
@@ -8,6 +8,6 @@
#ifdef __OBJC__
#import "Earthquake_Network-Swift.h"
#import <Earthquake_Network-Swift.h>
#endif
+26
View File
@@ -78,5 +78,31 @@
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb1444404982546319</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>1444404982546319</string>
<key>FacebookClientToken</key>
<string>46c7a338b2bbd2186b2f1c12865b4004</string>
<key>FacebookDisplayName</key>
<string>Earthquake Network</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-share-api</string>
</array>
<key>FacebookAutoLogAppEventsEnabled</key>
<true/>
<key>FacebookAdvertiserIDCollectionEnabled</key>
<true/>
<key>NSUserTrackingUsageDescription</key>
<string>Il tracciamento serve a capire se la pubblicità dell'app è efficace</string>
</dict>
</plist>
@@ -0,0 +1,28 @@
//
// Foundation+Extensions.swift
// Earthquake Network
//
// Created by Andrea Busi on 14/07/23.
// Copyright © 2023 Earthquake Network. All rights reserved.
//
import Foundation
extension Date {
func isBeforeInterval(
_ interval: TimeInterval
) -> Bool {
let now = Date()
return self.addingTimeInterval(interval) >= now
}
}
@objc
extension NSDate {
func isBeforeInterval(
_ interval: TimeInterval
) -> Bool {
return (self as Date).isBeforeInterval(interval)
}
}
@@ -21,6 +21,7 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
saveMissingValues()
migrationV5_3()
migrationV5_4()
}
// MARK: - Private
@@ -36,28 +37,45 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
private func saveMissingValues() {
// `raggio sismi forti` was not saved before v2.3
if UserDefaults.standard.object(forKey: NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI) == nil {
UserDefaults.standard.set("600", forKey: NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI)
if UserDefaults.standard.object(forKey: UserDefaults.AllertaSismicaRaggioSismiForti) == nil {
UserDefaults.standard.set("600", forKey: UserDefaults.AllertaSismicaRaggioSismiForti)
}
}
private func migrationV5_3() {
let migrationPerformed = UserDefaults.standard.bool(forKey: EQNUserDefaultMigrationV5_3)
let migrationPerformed = UserDefaults.standard.bool(forKey: UserDefaults.AppMigrationV5_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]
let lastLocations = EQNUtility.loadArray(of: CLLocation.self, fromUserDefaultsForKey: UserDefaults.UserDataLastLocation) as? [CLLocation]
if let lastLocation = lastLocations?.last {
UserDefaults.standard.removeObject(forKey: EQNUserDefaultLastLocation)
UserDefaults.standard.removeObject(forKey: UserDefaults.UserDataLastLocation)
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)
UserDefaults.standard.set(true, forKey: UserDefaults.AppMigrationV5_3)
}
private func migrationV5_4() {
let migrationPerformed = UserDefaults.standard.bool(forKey: UserDefaults.AppMigrationV5_4)
if migrationPerformed {
print("[EQNUserDefaultsCommand] Migration v5.4 already performed")
return
}
// migriamo l'ultima posizione negli user defaults condivisi
let userDefaults = UserDefaults.standard
let groupUserDefaults = UserDefaults.appGroup
if let encodedLocation = userDefaults.object(forKey: UserDefaults.UserDataLastLocation) as? Data {
groupUserDefaults?.set(encodedLocation, forKey: UserDefaults.UserDataLastLocation)
}
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_4)
}
}
@@ -14,9 +14,6 @@ import Foundation
@objc public static let DefaultRaggioSisma = EQNGenericValue(value:MaxRaggioSisma, display:"radius_any_distance")
@objc public static let DefaultMagitudoDebole = EQNGenericValue(value:"2.0", display:"official_magnitude_value_20")
@objc public static let DefaultMagitudoForte = EQNGenericValue(value:"5.5", display:"official_magnitude_value_55")
@objc public static let DefaultSeismicToNotify = EQNGenericValue(value: "0", display: "eqn_intensity_any")
@objc public static let DefaultDoNotDisturbStartTime = 8
@objc public static let DefaultDoNotDisturbEndTime = 22
@objc public static let DefaultPeriodoTemporale = EQNGenericValue(value: "1440", display: "report_timeframe_one_day")
// MARK: - Public
@@ -100,7 +97,7 @@ import Foundation
EQNSeismicNetwork(acronym: "USGS", country: NSLocalizedString("configuration_countries_united_states", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "INGV", country: NSLocalizedString("configuration_countries_italy", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "IGN", country: NSLocalizedString("configuration_countries_spain", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "EMSC", country: NSLocalizedString("configuration_countries_greece", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "UOA", country: NSLocalizedString("configuration_countries_greece", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "EMSC", country: NSLocalizedString("configuration_countries_france", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "EMSC", country: NSLocalizedString("configuration_countries_croatia", comment: ""), extended: ""),
EQNSeismicNetwork(acronym: "CSI", country: NSLocalizedString("configuration_countries_china", comment: ""), extended: ""),
@@ -136,49 +133,6 @@ import Foundation
return Self.seismicNetworks().first(where: { $0.acronym == acronym })
}
@objc class func seismicToNotify() -> [EQNGenericValue] {
[
EQNGenericValue(value:"0", display:"eqn_intensity_any"),
EQNGenericValue(value:"1", display:"eqn_intensity_strong")
]
}
@objc class func seismicToNotify(for value: String?) -> EQNGenericValue {
if let value = value, let genericValue = Self.seismicToNotify().first(where: { $0.value == value }) {
return genericValue
}
return Self.DefaultSeismicToNotify
}
@objc class func doNotDisturbStartDate(from date: Date?) -> Date {
if let date = date {
return date
}
// return default
let calendar = Calendar(identifier: .gregorian)
let units: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute]
var components = calendar.dateComponents(units, from: Date())
components.hour = Self.DefaultDoNotDisturbStartTime
components.minute = 00
return calendar.date(from: components)!
}
@objc class func doNotDisturbEndDate(from date: Date?) -> Date {
if let date = date {
return date
}
// return default
let calendar = Calendar(identifier: .gregorian)
let units: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute]
var components = calendar.dateComponents(units, from: Date())
components.hour = Self.DefaultDoNotDisturbEndTime
components.minute = 00
return calendar.date(from: components)!
}
@objc class func periodiTemporali() -> [EQNGenericValue] {
[
EQNGenericValue(value: "10", display: "10 minuti"),
@@ -0,0 +1,36 @@
//
// EQNDebugHelper.swift
// Earthquake Network
//
// Created by Andrea Busi on 14/07/23.
// Copyright © 2023 Earthquake Network. All rights reserved.
//
import Foundation
@objc
class EQNDebugHelper: NSObject {
@objc
static let shared = EQNDebugHelper()
private var timers: [String: Timer] = [:]
// MARK: - Public
@objc
func printPositions(
interval: TimeInterval = 2.0,
repeats: Bool = true
) {
let timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in
let current = EQNUserData.shared.lastLocation?.coordinate
print("[EQNDebugHelper] Current | lat: \(current?.latitude ?? 0) - lon: \(current?.longitude ?? 0)")
let saved = EQNUser.default().lastPosition?.coordinate
print("[EQNDebugHelper] Saved | lat: \(saved?.latitude ?? 0) - lon: \(saved?.longitude ?? 0)")
}
timers["positions"] = timer
}
}
+12 -19
View File
@@ -120,28 +120,21 @@
- (void)scaricaReteSismica
{
// Per ridurre i dati trasferiti tra app e server, ci sono degli endpoint dedicati
// in base alla magnitudo impostata dall'utente (per valori inferiori a 2.0).
// Se l'opzione `Mostra sismi di qualsiasi magnitudo se a meno di 50km` è attiva,
// dobbiamo utilizzare l'endpoint `_M0_0` perchè dobbiamo scaricare tutti i dati
NSString *queryString = @"";
double filterMagnitude = [[EQNSeismic shared].magnitudoMinima doubleValue];
bool filterAnyNearEarthquake = [EQNSeismic shared].sismiQualsiasiAbilitati;
if (filterMagnitude < 0.5 || filterAnyNearEarthquake) {
queryString = @"_M0_0";
} else if (filterMagnitude < 1.0) {
queryString = @"_M0_5";
} else if (filterMagnitude < 1.5) {
queryString = @"_M1_0";
} else if (filterMagnitude < 2.0) {
queryString = @"_M1_5";
// L'endpoint per lo scaricamento dei dati prende due parametri: pro per il provider selezionato, mag per la
// magnitudo minima. Se l'utente ha selezionato più di un provider, inviamo ALL. Mentre la magnitudo
// deve avere sempre una cifra decimale (es 2.0).
NSString *filterProvider = @"";
NSArray<NSString *> *networks = [EQNUserData.sharedData seismicNetworksSelected];
if (networks.count == 1) {
filterProvider = [networks firstObject];
} else {
// verrà usato l'url base
queryString = @"";
filterProvider = @"ALL";
}
NSString *filterMagnitude = [EQNSeismic shared].magnitudoMinima;
NSString *queryString = [NSString stringWithFormat:@"?pro=%@&mag=%@", filterProvider, filterMagnitude];
NSString *urlString = [NSString stringWithFormat:EQNServerUrlDownloadRetiSismiche, queryString];
NSURL *url = [NSURL URLWithString:urlString];
NSLog(@"[EQNManager] Url utilizzato per download reti sismiche: %@", url.absoluteURL);
@@ -15,6 +15,14 @@ struct EQNPurchaseAvailability {
// MARK: - Init
init(
top10kAvailable: Int,
top100kAvailable: Int
) {
self.top10kAvailable = top10kAvailable
self.top100kAvailable = top100kAvailable
}
init(data: Data) {
guard let availabilities = try? JSONSerialization.jsonObject(with: data, options: []) as? [[String: String]] else {
return
@@ -20,13 +20,13 @@ public class EQNPurchaseUtility: NSObject {
/// If zero, no discounted price is available
/// - Parameter completion: Completion
static func offerTimeRemaining(completion: @escaping (_ timeRemaining: Int) -> Void) {
let appOpenCounter = UserDefaults.standard.integer(forKey:EQNUserDefaultProDiscountOpenCounter)
let appOpenCounter = UserDefaults.standard.integer(forKey: UserDefaults.UserDataProDiscountOpenCounter)
if appOpenCounter < Self.AppOpenCountForDiscount {
completion(0)
return
}
let discountExpired = UserDefaults.standard.bool(forKey: EQNUserDefaultProDiscountExpired)
let discountExpired = UserDefaults.standard.bool(forKey: UserDefaults.UserDataProDiscountExpired)
if discountExpired {
completion(0)
return
@@ -34,7 +34,7 @@ public class EQNPurchaseUtility: NSObject {
EQNUser.default().downloadOfferTimeRemaining { (timeOffer) in
if timeOffer == 0 {
UserDefaults.standard.set(true, forKey: EQNUserDefaultProDiscountExpired)
UserDefaults.standard.set(true, forKey: UserDefaults.UserDataProDiscountExpired)
}
let timeInHours = timeOffer / 60
@@ -45,21 +45,13 @@ public class EQNPurchaseUtility: NSObject {
/// Returns availabilities for active subscriptions
/// - Parameter completion: Completion
static func availableSubscriptions(completion: @escaping (_ availability: EQNPurchaseAvailability?) -> Void) {
guard let url = URL(string: EQNServerUrlAvailableSubscriptionsCounter) else {
completion(nil)
return
}
// previously, to get this data a separated call was required
// starting from March 2023, the values are available from the EQNServerUrlDownloadSmartphoneNetwork request
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
completion(nil)
return
}
let availability = EQNPurchaseAvailability(data: data)
completion(availability)
}
task.resume()
let reteSmartPhone = EQNManager.manager().rete_smartphone
let availability = EQNPurchaseAvailability(top10kAvailable: reteSmartPhone?.top10kAvailable ?? 0,
top100kAvailable: reteSmartPhone?.top100kAvailable ?? 0)
completion(availability)
}
/// Check if user has bought pro app version
@@ -1,92 +0,0 @@
//
// 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)
}
}
@@ -0,0 +1,264 @@
//
// EQNRealtimePushNotification.swift
// Earthquake Network
//
// Created by Andrea Busi on 13/07/23.
// Copyright © 2023 Earthquake Network. All rights reserved.
//
import Foundation
import UIKit
import CoreLocation
import Shogun
@objc
class EQNRealtimePushNotification: NSObject, Codable {
/// Tempo (in secondi) entro cui vengono mostrate allerte in tempo reale ricevute
private static let RealtimeAlertExpiration: TimeInterval = 28_800 // 8 ore
private enum CodingKeys: String, CodingKey {
case type
case intensity
case latitude
case longitude
case counter
case dateTime
case waveSpeed
case impactTimestamp
case peak
case title
case displayTitle
case displayBody
}
let type: String
/// Earthquake intensity
let intensity: Int
/// Earthquake coordinate
let latitude: Double
let longitude: Double
/// Number of smartphones that report the earthquake
let counter: Int
let dateTime: Date?
/// Earthquake wave speed
let waveSpeed: Double
/// Calculated timestamp for earthquake on user position
let impactTimestamp: Date?
let peak: Double?
// Title received inside `aps.alert`
let title: String
// Title and body elaborated in NotificationService
let displayTitle: String
let displayBody: String
var coordinate: CLLocation {
.init(latitude: latitude, longitude: longitude)
}
// MARK: - Init
init(
type: String,
intensity: Int,
latitude: Double,
longitude: Double,
counter: Int,
dateTime: Date?,
waveSpeed: Double,
impactTimestamp: Date?,
peak: Double?,
title: String,
displayTitle: String,
displayBody: String
) {
self.type = type
self.intensity = intensity
self.latitude = latitude
self.longitude = longitude
self.counter = counter
self.dateTime = dateTime
self.waveSpeed = waveSpeed
self.impactTimestamp = impactTimestamp
self.peak = peak
self.title = title
self.displayTitle = displayTitle
self.displayBody = displayBody
}
func distanceFromUser() -> CLLocationDistance {
// Usiamo la posizione salvata, che coincide con quella presnete in EQNUser.
// In questo modo non abbiamo dipendenze e possiamo includere questa classe
// anche nel target NotificationService
EQNUserData.shared.lastLocation?.distance(from: coordinate) ?? 0.0
}
/// Remaining time before earthquake gets user position
func currentCountdown() -> Int {
guard let impactTimestamp else { return 0 }
let now = Date()
let difference = lround(max(impactTimestamp.timeIntervalSince(now), 0))
return difference
}
@objc
func isCountdownExpired() -> Bool {
currentCountdown() <= 0
}
/// Intensity on user location
func relativeIntensity() -> Double {
guard distanceFromUser() > 0, let peak else { return 0 }
let distanceKm = distanceFromUser() / 1_000 // get in km
let relativeIntensity = peak * exp(-distanceKm/peak/250)
return relativeIntensity
}
// MARK: - Class
/// Remove any saved notification
@objc(removeStoredNotification)
static func removeStored() {
UserDefaults.standard.removeObject(forKey: UserDefaults.RealTimeAlertPayload)
UserDefaults.standard.removeObject(forKey: UserDefaults.RealTimeAlertDate)
}
@objc(storedNotification)
static func stored() -> EQNRealtimePushNotification? {
guard let date = UserDefaults.standard.object(forKey: UserDefaults.RealTimeAlertDate) as? Date else {
return nil
}
guard date.isBeforeInterval(Self.RealtimeAlertExpiration) else {
print("[EQNRealtimePushNotification] Saved notification expired")
return nil
}
guard let data = UserDefaults.standard.object(forKey: UserDefaults.RealTimeAlertPayload) as? Data else {
print("[EQNRealtimePushNotification] No notification saved for key '\(UserDefaults.RealTimeAlertPayload)'")
return nil
}
guard let notification = try? JSONDecoder().decode(EQNRealtimePushNotification.self, from: data) else {
print("[EQNRealtimePushNotification] Unable to decode given notification")
return nil
}
return notification
}
/// Convert and store a push notification payload.
/// Expected payload has the following structure:
/// ```
/// {
/// "title": "Allerta sismica in tempo reale",
/// "body": "Previsto uno scuotimento forte",
/// "userInfo": {
/// "datetime" : "2023-07-13 12:24:04",
/// ...
/// "aps": {
/// "alert" : {
/// "loc-key" : "Rilevato sisma forte a",
/// "title-loc-key" : "Allerta sismica in tempo reale",
/// "loc-args" : [
/// "150 km (Test)"
/// ]
/// },
/// }
/// }
/// }
/// ```
/// - Parameter payload: Notification payload
/// - Returns: `true` if save succeed, `false` otherwise
@objc(storeNotificationWithPayload:)
@discardableResult
static func store(payload: [String: Any]) -> Bool {
guard let notification = from(payload: payload) else {
print("[EQNRealtimePushNotification] Unable to convert received notification")
return false
}
guard let data = try? JSONEncoder().encode(notification) else {
print("[EQNRealtimePushNotification] Unable to encode given notification")
return false
}
UserDefaults.standard.set(data, forKey: UserDefaults.RealTimeAlertPayload)
UserDefaults.standard.set(Date(), forKey: UserDefaults.RealTimeAlertDate)
return true
}
@objc
private static func from(payload: [String: Any]) -> EQNRealtimePushNotification? {
guard let userInfo = payload["userInfo"] as? [String: Any],
let aps = userInfo["aps"] as? [String: Any],
let alert = aps["alert"] as? [String: Any] else {
print("[EQNRealtimePushNotification] Missing required info to parse push notification")
return nil
}
guard let latitude = userInfo.double(forKey: "latitude"),
let longitude = userInfo.double(forKey: "longitude") else {
print("[EQNRealtimePushNotification] Unable to get coordinate from push notification")
return nil
}
let type = userInfo.string(forKey: "type", orDefault: "")
let intensity = userInfo.integer(forKey: "intensity", orDefault: 0)
let counter = userInfo.integer(forKey: "counter", orDefault: 0)
var dateTime: Date?
if let dateString = userInfo.string(forKey: "datetime"), let date = EQNUtility.getDateFrom(dateString) {
dateTime = date
}
let waveSpeed = userInfo.double(forKey: "wave_speed", orDefault: 0.0) * 1000 // m/s
var impactTimestamp: Date?
if let timestamp = EQNUtility.calculateUserSeismicTimestamp(fromUserInfo: userInfo) {
impactTimestamp = timestamp
}
let peak = userInfo.double(forKey: "peak")
var title: String = ""
if let titleKey = alert["loc-key"] as? String, let args = alert["loc-args"] as? [String], let arg = args.first {
title = String(format: NSLocalizedString(titleKey, comment: ""), arg)
}
let displayTitle = payload.string(forKey: "title", orDefault: "")
let displayBody = payload.string(forKey: "body", orDefault: "")
return .init(
type: type,
intensity: intensity,
latitude: latitude,
longitude: longitude,
counter: counter,
dateTime: dateTime,
waveSpeed: waveSpeed,
impactTimestamp: impactTimestamp,
peak: peak,
title: title,
displayTitle: displayTitle,
displayBody: displayBody
)
}
}
extension EQNRealtimePushNotification {
/// Returns the color based on relative intensity
var relativeIntensityColor: UIColor {
let intensity = relativeIntensity()
switch intensity {
case _ where intensity < 0.004:
return UIColor(red: 90.0/255.0, green: 90.0/255.0, blue: 90.0/255.0, alpha: 1.0)
case _ where intensity < 0.30:
return UIColor(red: 38.0/255.0, green: 100.0/255.0, blue: 38.0/255.0, alpha: 1.0)
case _ where intensity < 0.70:
return UIColor(red: 255.0/255.0, green: 140.0/255.0, blue: 0.0, alpha: 1.0)
default:
return UIColor(red: 215.0/255.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
}
}
@@ -18,6 +18,8 @@ class EQNReteSmartphone: NSObject {
@objc let manual: Int
@objc let lastSubscriptionDiff: Int
@objc let subscriptionsDiscounted: Bool
let top10kAvailable: Int
let top100kAvailable: Int
// MARK: - Init
@@ -34,6 +36,8 @@ class EQNReteSmartphone: NSObject {
self.lastSubscriptionDiff = allValues.integer(forKey: "diff", orDefault: 0)
let subscriptionsDiscounted = allValues.integer(forKey: "st", orDefault: 0)
self.subscriptionsDiscounted = subscriptionsDiscounted == 1
self.top10kAvailable = allValues.integer(forKey: "t10k")
self.top100kAvailable = allValues.integer(forKey: "t100k")
super.init()
}
@@ -109,10 +109,8 @@ import Foundation
@objc func filterSeismicList(_ list: [EQNSisma]) -> [EQNSisma] {
// enti abilitati
var networks: [String]
if let savedNetworks = UserDefaults.standard.object(forKey: IMPOSTAZIONE_ENTI_RETI_SISMICHEI) as? [String] {
networks = savedNetworks
} else {
var networks = EQNUserData.shared.seismicNetworksSelected()
if networks.isEmpty {
networks = EQNData.seismicNetworkAcronyms()
}
networks = networks.map { $0.lowercased() }
@@ -33,14 +33,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) NSNumber *preliminary;
@property (nonatomic, strong) NSNumber *smartphoneNumber;
@property (nonatomic, strong) NSNumber *userNumber;
@property (nonatomic, strong, nullable) NSString *weatherCode;
@property (nonatomic, strong) NSString *weatherIcon;
@property (nonatomic, strong) NSNumber *weatherCloud;
@property (nonatomic, strong) NSNumber *weatherWindSpeed;
@property (nonatomic, strong) NSNumber *weatherPressure;
@property (nonatomic, strong) NSNumber *weatherHumidity;
@property (nonatomic, strong) NSNumber *weatherTemperature;
@property (nonatomic, strong) NSNumber *pictureCount;
- (instancetype)initWithInfo:(NSDictionary *)info;
@@ -42,15 +42,6 @@
self.preliminary = info[@"py"];
self.smartphoneNumber = info[@"sm"];
self.userNumber = info[@"rp"];
self.weatherCode = [info eqn_safeObjectForKey:@"wc"];
self.weatherIcon = info[@"ic"];
self.weatherCloud = info[@"cl"];
self.weatherWindSpeed = info[@"ws"];
self.weatherPressure = info[@"pe"];
self.weatherHumidity = info[@"hu"];
self.weatherTemperature = info[@"te"];
self.pictureCount = info[@"pc"];
}
return self;
}
@@ -74,14 +65,6 @@
[encoder encodeObject:self.preliminary forKey:@"preliminary"];
[encoder encodeObject:self.smartphoneNumber forKey:@"smartphoneNumber"];
[encoder encodeObject:self.userNumber forKey:@"userNumber"];
[encoder encodeObject:self.weatherCode forKey:@"weatherCode"];
[encoder encodeObject:self.weatherIcon forKey:@"weatherIcon"];
[encoder encodeObject:self.weatherCloud forKey:@"weatherCloud"];
[encoder encodeObject:self.weatherWindSpeed forKey:@"weatherWindSpeed"];
[encoder encodeObject:self.weatherPressure forKey:@"weatherPressure"];
[encoder encodeObject:self.weatherHumidity forKey:@"weatherHumidity"];
[encoder encodeObject:self.weatherTemperature forKey:@"weatherTemperature"];
[encoder encodeObject:self.pictureCount forKey:@"pictureCount"];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
@@ -103,14 +86,6 @@
self.preliminary = [decoder decodeObjectForKey:@"preliminary"];
self.smartphoneNumber = [decoder decodeObjectForKey:@"smartphoneNumber"];
self.userNumber = [decoder decodeObjectForKey:@"userNumber"];
self.weatherCode = [decoder decodeObjectForKey:@"weatherCode"];
self.weatherIcon = [decoder decodeObjectForKey:@"weatherIcon"];
self.weatherCloud = [decoder decodeObjectForKey:@"weatherCloud"];
self.weatherWindSpeed = [decoder decodeObjectForKey:@"weatherWindSpeed"];
self.weatherPressure = [decoder decodeObjectForKey:@"weatherPressure"];
self.weatherHumidity = [decoder decodeObjectForKey:@"weatherHumidity"];
self.weatherTemperature = [decoder decodeObjectForKey:@"weatherTemperature"];
self.pictureCount = [decoder decodeObjectForKey:@"pictureCount"];
}
return self;
}
@@ -26,15 +26,15 @@ import CoreLocation
@objc
var firebaseToken: String? {
UserDefaults.standard.object(forKey: EQNUserDefaultUserFirebaseToken) as? String
UserDefaults.standard.object(forKey: UserDefaults.UserDataFirebaseToken) as? String
}
@objc
func saveFirebaseToken(_ token: String?) {
if let token = token {
UserDefaults.standard.set(token, forKey: EQNUserDefaultUserFirebaseToken)
UserDefaults.standard.set(token, forKey: UserDefaults.UserDataFirebaseToken)
} else {
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserFirebaseToken)
UserDefaults.standard.removeObject(forKey: UserDefaults.UserDataFirebaseToken)
}
}
@@ -42,7 +42,7 @@ import CoreLocation
@objc
var userId: String? {
let userId = UserDefaults.standard.object(forKey: EQNUserDefaultUserId)
let userId = UserDefaults.standard.object(forKey: UserDefaults.UserDataUserId)
// nel corso delle versioni l'id è stato salvato in diversi modi
// per evitare problemi, cerchiamo di convertirlo in modi diveri
@@ -59,14 +59,14 @@ import CoreLocation
@objc
func saveUserId(_ userId: String) {
UserDefaults.standard.set(userId, forKey: EQNUserDefaultUserId)
UserDefaults.standard.set(userId, forKey: UserDefaults.UserDataUserId)
}
// MARK: - Last location
@objc
var lastLocation: CLLocation? {
guard let encodedLocation = UserDefaults.standard.object(forKey: EQNUserDefaultLastLocation) as? Data else {
guard let encodedLocation = UserDefaults.appGroup?.object(forKey: UserDefaults.UserDataLastLocation) as? Data else {
return nil
}
@@ -79,15 +79,29 @@ import CoreLocation
guard let encodedLocation = try? NSKeyedArchiver.archivedData(withRootObject: location, requiringSecureCoding: false) else {
return
}
UserDefaults.standard.set(encodedLocation, forKey: EQNUserDefaultLastLocation)
UserDefaults.appGroup?.set(encodedLocation, forKey: UserDefaults.UserDataLastLocation)
}
// MARK: - Seismic Networks
@objc
func seismicNetworksSelected() -> [String] {
if let savedNetworks = UserDefaults.standard.object(forKey: UserDefaults.UserDataSelectedSeismicNetworks) as? [String] {
return savedNetworks
}
return []
}
func saveSelectedSeismicNetworks(_ networks: [String]) {
UserDefaults.standard.set(networks, forKey: UserDefaults.UserDataSelectedSeismicNetworks)
}
// MARK: - Public
@objc
func removeAllData() {
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserFirebaseToken)
UserDefaults.standard.removeObject(forKey: EQNUserDefaultUserId)
UserDefaults.standard.removeObject(forKey: EQNUserDefaultLastLocation)
UserDefaults.standard.removeObject(forKey: UserDefaults.UserDataFirebaseToken)
UserDefaults.standard.removeObject(forKey: UserDefaults.UserDataUserId)
UserDefaults.appGroup?.removeObject(forKey: UserDefaults.UserDataLastLocation)
}
}
+1 -14
View File
@@ -25,17 +25,13 @@ NS_ASSUME_NONNULL_BEGIN
/// Creates a string for a given time interval.
/// Some examples: 1 hour ago, 25 minutes ago, 2 days ago
/// @param timeDifference Time differnce
/// @param timeDifference Time difference, in minutes
+ (NSString *)formattedStringForTimeDifference:(NSInteger)timeDifference;
/// Clear a given string from unwanted characters
/// @param messaggio Cleaned string
+ (NSString *)clearStringMessaggi:(NSString *)messaggio;
/// Calculate time difference (in minutes) between the given date and the current timestamp
/// @param date Difference (in minutes)
+ (NSInteger)getDifferenceMinute:(NSDate *)date;
/// Store an array of custom objects to NSUserDefaults
/// @param array Array to store
/// @param keyName Key of NSUserDefault to use
@@ -46,15 +42,6 @@ NS_ASSUME_NONNULL_BEGIN
/// @param keyName Key of NSUserDefault to retrieve
+ (nullable NSArray *)loadArrayOfClass:(Class)class fromUserDefaultsForKey:(NSString* )keyName;
/// Store a dictionary to NSUserDefaults
/// @param dictionary Dictionary to store
/// @param keyName Key of NSUserDefault to use
+ (void)storeDictionary:(NSDictionary *)dictionary toUserDefaultForKey:(NSString *)keyName;
/// Retrieve a saved dictionary from NSUserDefaults.
/// @param keyName Key of NSUserDefault to retrieve
+ (nullable NSDictionary *)loadDictionaryFromUserDefaultsForKey:(NSString *)keyName;
/// Calculate impact time from a received push notification
/// @param info Payload of a received notification
/// @return Impact time
+8 -54
View File
@@ -8,7 +8,6 @@
#import "EQNUtility.h"
#import "EQNSegnalazione.h"
#import "EQNSegnalazione.h"
#import "EQNPastquakes.h"
#import "EQNSisma.h"
@@ -27,25 +26,18 @@
NSString *format = @"";
NSInteger finalValue = timeDifference;
if (timeDifference == 1) {
format = NSLocalizedString(@"minutes_one", comment: nil);
} else if (timeDifference < 60) {
format = NSLocalizedString(@"minutes_other", comment: nil);
} else if (timeDifference > 60 && timeDifference < 120) {
// check for minutes, hours or days
if (timeDifference < 60) {
format = NSLocalizedString(@"manual_minutes_ago", nil);
} else if (timeDifference < 1440) {
finalValue = timeDifference / 60.0;
format = NSLocalizedString(@"hours_one", comment: nil);
} else if (timeDifference > 60 && timeDifference < 1440) {
finalValue = timeDifference / 60.0;
format = NSLocalizedString(@"hours_other", comment: nil);
} else if (timeDifference > 1400 && timeDifference < 2800) {
finalValue = timeDifference / 1400.0;
format = NSLocalizedString(@"days_one", comment: nil);
format = NSLocalizedString(@"manual_hours_ago", nil);
} else {
finalValue = timeDifference / 1400.0;
format = NSLocalizedString(@"days_other", comment: nil);
finalValue = timeDifference / 1440.0;
format = NSLocalizedString(@"manual_days_ago", nil);
}
return [NSString stringWithFormat:format, (long)finalValue];
return [NSString localizedStringWithFormat:format, finalValue];
}
+ (NSString *)clearStringMessaggi:(NSString *)messaggio
@@ -61,18 +53,6 @@
return clearString;
}
+ (NSInteger)getDifferenceMinute:(NSDate *)date
{
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitMinute
fromDate:date
toDate:now
options:0];
return components.minute;
}
#pragma mark - Store/load data
+ (void)storeArray:(NSArray *)array toUserDefaultForKey:(NSString *)keyName
@@ -80,11 +60,6 @@
[self storeRootObject:array toUserDefaultForKey:keyName];
}
+ (void)storeDictionary:(NSDictionary *)dictionary toUserDefaultForKey:(NSString *)keyName
{
[self storeRootObject:dictionary toUserDefaultForKey:keyName];
}
+ (void)storeRootObject:(id)rootObject toUserDefaultForKey:(NSString *)keyName
{
NSError *error;
@@ -119,27 +94,6 @@
return array;
}
+ (NSDictionary *)loadDictionaryFromUserDefaultsForKey:(NSString *)keyName
{
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];
unarchiver.requiresSecureCoding = NO;
NSDictionary *dictionary = [unarchiver decodeObjectOfClass:[NSDictionary class] forKey:NSKeyedArchiveRootObjectKey];
if (error) {
NSLog(@"[EQNUtility] Unable to unarchive object for key '%@' (error: %@)", keyName, error.localizedDescription);
return nil;
}
return dictionary;
}
#pragma mark - Notifications
+ (nullable NSDate *)calculateUserSeismicTimestampFromUserInfo:(NSDictionary *)info
@@ -70,6 +70,7 @@ class EQNMapAnnotationSeismic: NSObject, MKAnnotation {
case "IGN": icon = "square"
case "UASD", "BDTIM", "NCS": icon = "thick_star"
case "RSPR": icon = "star6f"
case "UOA": icon = "triangle"
default: icon = ""
}
@@ -31,16 +31,16 @@
self = [super init];
if (self) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.isAbilitato = [userDefaults boolForKey:NOTIFICHE_ALLERA_SISMICA_ABILITATO];
self.sismiDaNotificare = [userDefaults objectForKey:NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE];
self.raggioSismiLievi = [userDefaults objectForKey:NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI];
self.raggioSismiForti = [userDefaults objectForKey:NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI];
self.isintervalloAllarme = [userDefaults boolForKey:NOTIFICHE_ALLERA_SISMICA_ABILITA_INTERVALLO];
self.oraioInizio = [userDefaults objectForKey:NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO];
self.orarioFine = [userDefaults objectForKey:NOTIFICHE_ALLERA_SISMICA_ORA_FINE];
self.isAbilitato = [userDefaults boolForKey:NSUserDefaults.AllertaSismicaAbilitato];
self.sismiDaNotificare = [userDefaults objectForKey:NSUserDefaults.AllertaSismicaSismiDaNotificare];
self.raggioSismiLievi = [userDefaults objectForKey:NSUserDefaults.AllertaSismicaRaggioSismiLievi];
self.raggioSismiForti = [userDefaults objectForKey:NSUserDefaults.AllertaSismicaRaggioSismiForti];
self.isintervalloAllarme = [userDefaults boolForKey:NSUserDefaults.AllertaSismicaAbilitaIntervallo];
self.oraioInizio = [userDefaults objectForKey:NSUserDefaults.AllertaSismicaOraInizio];
self.orarioFine = [userDefaults objectForKey:NSUserDefaults.AllertaSismicaOraFine];
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:EQNUserDefaultAppGroupSuite];
self.isCriticalAlertsEnabled = [sharedDefaults boolForKey:NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS];
NSUserDefaults *sharedDefaults = [NSUserDefaults appGroupUserDefaults];
self.isCriticalAlertsEnabled = [sharedDefaults boolForKey:NSUserDefaults.AllertaSismicaCriticalAlerts];
}
return self;
}
@@ -50,16 +50,16 @@
- (void)saveUserInfo
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:self.isAbilitato forKey:NOTIFICHE_ALLERA_SISMICA_ABILITATO];
[userDefaults setObject:self.sismiDaNotificare forKey:NOTIFICHE_ALLERA_SISMICA_SISMI_DA_NOTIFICARE];
[userDefaults setObject:self.raggioSismiLievi forKey:NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_LIEVI];
[userDefaults setObject:self.raggioSismiForti forKey:NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI];
[userDefaults setBool:self.isintervalloAllarme forKey:NOTIFICHE_ALLERA_SISMICA_ABILITA_INTERVALLO];
[userDefaults setObject:self.oraioInizio forKey:NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO];
[userDefaults setObject:self.orarioFine forKey:NOTIFICHE_ALLERA_SISMICA_ORA_FINE];
[userDefaults setBool:self.isAbilitato forKey:NSUserDefaults.AllertaSismicaAbilitato];
[userDefaults setObject:self.sismiDaNotificare forKey:NSUserDefaults.AllertaSismicaSismiDaNotificare];
[userDefaults setObject:self.raggioSismiLievi forKey:NSUserDefaults.AllertaSismicaRaggioSismiLievi];
[userDefaults setObject:self.raggioSismiForti forKey:NSUserDefaults.AllertaSismicaRaggioSismiForti];
[userDefaults setBool:self.isintervalloAllarme forKey:NSUserDefaults.AllertaSismicaAbilitaIntervallo];
[userDefaults setObject:self.oraioInizio forKey:NSUserDefaults.AllertaSismicaOraInizio];
[userDefaults setObject:self.orarioFine forKey:NSUserDefaults.AllertaSismicaOraFine];
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:EQNUserDefaultAppGroupSuite];
[sharedDefaults setBool:self.isCriticalAlertsEnabled forKey:NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS];
NSUserDefaults *sharedDefaults = [NSUserDefaults appGroupUserDefaults];
[sharedDefaults setBool:self.isCriticalAlertsEnabled forKey:NSUserDefaults.AllertaSismicaCriticalAlerts];
}
#pragma mark - Class
@@ -31,13 +31,13 @@
{
self = [super init];
if (self) {
self.isAbilitato = [[NSUserDefaults standardUserDefaults] boolForKey:NOTIFICHE_ATTIVA_RETI_SISMICHE];
self.isAbilitaVicini = [[NSUserDefaults standardUserDefaults] boolForKey:NOTIFICHE_ATTIVA_RETI_SISMICHE_VICINE];
self.isTerremortiForti = [[NSUserDefaults standardUserDefaults] boolForKey:NOTIFICHE_ATTIVA_RETI_TERREMOTI_FORTI];
self.distanzaPosizione = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_DISTANZA_POSIZIONE_RETI_SISMICHE];
self.energiaSisma = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_ATTIVA_RETI_ENERGIA_SISMI];
self.energiaTerremotiForti = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_ATTIVA_RETI_ENERGIA_FORTI];
self.listaEnti = [EQNUtility loadArrayOfClass:[NSString class] fromUserDefaultsForKey:NOTIFICHE_ATTIVA_RETI_LISTA_ENTI];
self.isAbilitato = [[NSUserDefaults standardUserDefaults] boolForKey:NSUserDefaults.NotificheRetiSismicheAbilitato];
self.isAbilitaVicini = [[NSUserDefaults standardUserDefaults] boolForKey:NSUserDefaults.NotificheRetiSismicheViciniAbilitato];
self.isTerremortiForti = [[NSUserDefaults standardUserDefaults] boolForKey:NSUserDefaults.NotificheRetiSismicheTerremotiFortiAbilitato];
self.distanzaPosizione = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaults.NotificheRetiSismicheDistanzaPosizione];
self.energiaSisma = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaults.NotificheRetiSismicheEnergiaSisma];
self.energiaTerremotiForti = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaults.NotificheRetiSismicheEnergiaTerremotiForti];
self.listaEnti = [EQNUtility loadArrayOfClass:[NSString class] fromUserDefaultsForKey:NSUserDefaults.NotificheRetiSismicheListaEnti];
}
return self;
}
@@ -46,13 +46,13 @@
- (void)saveUserInfo
{
[[NSUserDefaults standardUserDefaults] setObject:self.distanzaPosizione forKey:NOTIFICHE_DISTANZA_POSIZIONE_RETI_SISMICHE];
[[NSUserDefaults standardUserDefaults] setObject:self.energiaSisma forKey:NOTIFICHE_ATTIVA_RETI_ENERGIA_SISMI];
[[NSUserDefaults standardUserDefaults] setObject:self.energiaTerremotiForti forKey:NOTIFICHE_ATTIVA_RETI_ENERGIA_FORTI];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitato forKey:NOTIFICHE_ATTIVA_RETI_SISMICHE];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitaVicini forKey:NOTIFICHE_ATTIVA_RETI_SISMICHE_VICINE];
[[NSUserDefaults standardUserDefaults] setBool:self.isTerremortiForti forKey:NOTIFICHE_ATTIVA_RETI_TERREMOTI_FORTI];
[EQNUtility storeArray:self.listaEnti toUserDefaultForKey:NOTIFICHE_ATTIVA_RETI_LISTA_ENTI];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitato forKey:NSUserDefaults.NotificheRetiSismicheAbilitato];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitaVicini forKey:NSUserDefaults.NotificheRetiSismicheViciniAbilitato];
[[NSUserDefaults standardUserDefaults] setBool:self.isTerremortiForti forKey:NSUserDefaults.NotificheRetiSismicheTerremotiFortiAbilitato];
[[NSUserDefaults standardUserDefaults] setObject:self.distanzaPosizione forKey:NSUserDefaults.NotificheRetiSismicheDistanzaPosizione];
[[NSUserDefaults standardUserDefaults] setObject:self.energiaSisma forKey:NSUserDefaults.NotificheRetiSismicheEnergiaSisma];
[[NSUserDefaults standardUserDefaults] setObject:self.energiaTerremotiForti forKey:NSUserDefaults.NotificheRetiSismicheEnergiaTerremotiForti];
[EQNUtility storeArray:self.listaEnti toUserDefaultForKey:NSUserDefaults.NotificheRetiSismicheListaEnti];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@@ -29,8 +29,8 @@
{
self = [super init];
if (self) {
self.isAbilitato = [[NSUserDefaults standardUserDefaults] boolForKey:NOTIFICHE_SU_ATTIVA_SEGNALAZIONE_UTENTE];
self.distanzaPosizione = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_SU_DISTANZA_POSIZIONE];
self.isAbilitato = [[NSUserDefaults standardUserDefaults] boolForKey:NSUserDefaults.NotificheSegnalazioniUtenteAbilitato];
self.distanzaPosizione = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaults.NotificheSegnalazioniUtenteDistanzaPosizione];
}
return self;
}
@@ -39,8 +39,8 @@
- (void)saveUserInfo
{
[[NSUserDefaults standardUserDefaults] setObject:self.distanzaPosizione forKey:NOTIFICHE_SU_DISTANZA_POSIZIONE];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitato forKey:NOTIFICHE_SU_ATTIVA_SEGNALAZIONE_UTENTE];
[[NSUserDefaults standardUserDefaults] setBool:self.isAbilitato forKey:NSUserDefaults.NotificheSegnalazioniUtenteAbilitato];
[[NSUserDefaults standardUserDefaults] setObject:self.distanzaPosizione forKey:NSUserDefaults.NotificheSegnalazioniUtenteDistanzaPosizione];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "194",
"green" : "194",
"red" : "194"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "130",
"green" : "212",
"red" : "148"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "173",
"green" : "160",
"red" : "254"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "177",
"green" : "231",
"red" : "255"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -149,6 +149,7 @@
NSString *n_o_rspr = @"&n_o_rspr=0";
NSString *n_o_bdtim = @"&n_o_bdtim=0";
NSString *n_o_ncs = @"&n_o_ncs=0";
NSString *n_o_uao = @"&n_o_uao=0";
for (NSString *ente in [EQNNotificheReteSismiche sharedInstance].listaEnti) {
if ([ente isEqualToString:@"USGS"]) {
@@ -193,9 +194,11 @@
n_o_bdtim = @"&n_o_bdtim=1";
} else if ([ente isEqualToString:@"NCS"]) {
n_o_ncs = @"&n_o_ncs=1";
} else if ([ente isEqualToString:@"XXX"]) {
n_o_uao = @"&n_o_uao=1";
}
}
NSString *enti = [NSString stringWithFormat:@"%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@", n_o_usgs, n_o_emsc, n_o_ingv, n_o_ign, n_o_csi, n_o_jma, n_o_ineter, n_o_ssn, n_o_sgc, n_o_rsn, n_o_csn, n_o_funvisis, n_o_geonet, n_o_inpres, n_o_igepn, n_o_phivolcs, n_o_igp, n_o_uasd, n_o_rspr, n_o_bdtim, n_o_ncs];
NSString *enti = [NSString stringWithFormat:@"%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@", n_o_usgs, n_o_emsc, n_o_ingv, n_o_ign, n_o_csi, n_o_jma, n_o_ineter, n_o_ssn, n_o_sgc, n_o_rsn, n_o_csn, n_o_funvisis, n_o_geonet, n_o_inpres, n_o_igepn, n_o_phivolcs, n_o_igp, n_o_uasd, n_o_rspr, n_o_bdtim, n_o_ncs, n_o_uao];
NSString *n_o_strong = [NSString stringWithFormat:@"&n_o_strong=%i",[EQNNotificheReteSismiche sharedInstance].isTerremortiForti];
@@ -204,19 +207,11 @@
// per sicurezza, però, teniamo i controlli
NSString *n_o_strmag = [NSString stringWithFormat:@"&n_o_strmag=%@", [EQNNotificheReteSismiche sharedInstance].energiaTerremotiForti];
if ([[EQNAllertaSismica sharedInstance].sismiDaNotificare isEqualToString:NSLocalizedString(@"eqn_intensity_any", @"")]) {
n_o_strmag = @"&n_o_strmag=0";
}
NSString *r_e_mild = [NSString stringWithFormat:@"&r_e_mild=%@", [EQNAllertaSismica sharedInstance].raggioSismiLievi];
if ([[EQNAllertaSismica sharedInstance].raggioSismiLievi isEqualToString:NSLocalizedString(@"radius_any_distance", @"")]) {
r_e_mild = @"&r_e_mild=100000";
}
NSString *r_e_strong = [NSString stringWithFormat:@"&r_e_strong=%@", [EQNAllertaSismica sharedInstance].raggioSismiForti];
if ([[EQNAllertaSismica sharedInstance].raggioSismiForti isEqualToString:NSLocalizedString(@"radius_any_distance", @"")]) {
r_e_strong = @"&r_e_strong=100000";
}
// andrea.busi - 18/05/2023: filtri rimossi, inviamo al WS dei valori fissi
NSString *r_e_mild = @"&r_e_mild=100000";
NSString *r_e_strong = @"&r_e_strong=100000";
NSString *n_e_type = @"&n_e_type=0";
NSString *r_m = [NSString stringWithFormat:@"&r_m=%@", [EQNNotificheSegnalazioniUtente sharedInstance].distanzaPosizione];
if ([[EQNNotificheSegnalazioniUtente sharedInstance].distanzaPosizione isEqualToString:NSLocalizedString(@"radius_any_distance", @"")]) {
@@ -227,9 +222,7 @@
if ([[EQNNotificheReteSismiche sharedInstance].distanzaPosizione isEqualToString:NSLocalizedString(@"radius_any_distance", @"")]) {
r_o = @"&r_o=100000";
}
NSString *n_e_type = [NSString stringWithFormat:@"&n_e_type=%@", [EQNAllertaSismica sharedInstance].sismiDaNotificare];
NSString *stringUrl = [NSString stringWithFormat:@"%@?u_id=%@&lat=%f&lon=%f%@%@%@%@%@%@%@%@%@%@%@%@%@", EQNServerUrlUploadSettings, [EQNUser defaultUser].user_ID, [EQNUser defaultUser].lastPosition.coordinate.latitude, [EQNUser defaultUser].lastPosition.coordinate.longitude, n_e, n_m, n_o, n_o_near,n_o_mag, enti, n_o_strong, n_e_type, n_o_strmag, r_e_mild, r_e_strong, r_m, r_o];
@@ -1,166 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CWo-PE-Dqp">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CWo-PE-Dqp">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Purchase Pro Version View Controller-->
<scene sceneID="7DV-6S-8ro">
<objects>
<viewController modalPresentationStyle="fullScreen" id="rRh-R0-bas" customClass="PurchaseProVersionViewController" customModule="Earthquake_Network" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="LIA-2s-RvE">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aTr-Vm-6rY">
<rect key="frame" x="0.0" y="96" width="414" height="504"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aeL-82-LFr">
<rect key="frame" x="8" y="8" width="393.5" height="571"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PRO Version" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="x3N-F9-QOy" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="97" height="26"/>
<color key="backgroundColor" name="Light blue"/>
<constraints>
<constraint firstAttribute="height" constant="26" id="26b-eK-dL6"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="22" translatesAutoresizingMaskIntoConstraints="NO" id="WHR-BN-hfJ">
<rect key="frame" x="8" y="34" width="377.5" height="700"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="You are buying the PRO version, advertisement will be removed" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6z8-bz-exh">
<rect key="frame" x="0.0" y="0.0" width="377.5" height="41"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ywi-cF-AR3">
<rect key="frame" x="0.0" y="63" width="377.5" height="103.5"/>
<string key="text">This is an offer just for you. If you convert the app to PRO within the next 48 hours, you have a 20%% discount. You will have only this chance. After, the PRO version will cost the full price. You still have %lu hours :-)</string>
<fontDescription key="fontDescription" style="UICTFontTextStyleCallout"/>
<color key="textColor" name="Red"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1Wb-RN-Qxg">
<rect key="frame" x="0.0" y="188.5" width="377.5" height="166.5"/>
<string key="text">La versione PRO non ha alcuna pubblicità ed in futuro includerà funzionalità aggiuntive.
In più sostieni il progetto di ricerca il quale non riceve finanziamenti esterni. Grazie per considerare l'acquisto! In alternativa, il passaggio alla versione PRO è GRATUITO sottoscrivendo uno degli abbonamenti annuali del servizio priorità.</string>
<fontDescription key="fontDescription" style="UICTFontTextStyleCallout"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="exx-jC-Bsi">
<rect key="frame" x="0.0" y="377" width="377.5" height="169.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xkb-Nt-Fiw">
<rect key="frame" x="0.0" y="0.0" width="377.5" height="84.5"/>
<state key="normal" title="Privacy disclaimer"/>
<connections>
<action selector="openExternalLinkTapped:" destination="rRh-R0-bas" eventType="touchUpInside" id="7I2-2c-6U4"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dnA-Yy-Ado">
<rect key="frame" x="0.0" y="84.5" width="377.5" height="85"/>
<state key="normal" title="Terms and conditions"/>
<connections>
<action selector="openExternalLinkTapped:" destination="rRh-R0-bas" eventType="touchUpInside" id="eaH-Et-bch"/>
</connections>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="5e5-N9-PcO">
<rect key="frame" x="0.0" y="568.5" width="377.5" height="131.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="You are paying:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gGN-X8-wUL">
<rect key="frame" x="0.0" y="0.0" width="377.5" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="-" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Z3v-8b-VXq">
<rect key="frame" x="0.0" y="30.5" width="377.5" height="41"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle0"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xwb-Pw-WFu">
<rect key="frame" x="0.0" y="81.5" width="377.5" height="50"/>
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="CnX-Fe-MJJ"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
<state key="normal" title="START CONVERSION"/>
<connections>
<action selector="purchaseTapped:" destination="rRh-R0-bas" eventType="touchUpInside" id="C1o-op-E60"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="x3N-F9-QOy" firstAttribute="leading" secondItem="aeL-82-LFr" secondAttribute="leading" id="7RL-bU-e58"/>
<constraint firstItem="x3N-F9-QOy" firstAttribute="top" secondItem="aeL-82-LFr" secondAttribute="top" id="TtX-gW-2xL"/>
<constraint firstAttribute="trailing" secondItem="WHR-BN-hfJ" secondAttribute="trailing" constant="8" id="V0n-wm-gqR"/>
<constraint firstAttribute="trailing" secondItem="x3N-F9-QOy" secondAttribute="trailing" priority="250" id="mm0-dL-soS"/>
<constraint firstItem="WHR-BN-hfJ" firstAttribute="top" secondItem="x3N-F9-QOy" secondAttribute="bottom" constant="8" id="tH2-HA-l9h"/>
<constraint firstAttribute="bottom" secondItem="WHR-BN-hfJ" secondAttribute="bottom" constant="30" id="tsV-7E-9UU"/>
<constraint firstItem="WHR-BN-hfJ" firstAttribute="leading" secondItem="aeL-82-LFr" secondAttribute="leading" constant="8" id="vgy-04-8MR"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="aeL-82-LFr" secondAttribute="bottom" constant="8" id="6WC-CD-c4P"/>
<constraint firstItem="aeL-82-LFr" firstAttribute="leading" secondItem="aTr-Vm-6rY" secondAttribute="leading" constant="8" id="HcF-Zg-8Cz"/>
<constraint firstItem="aeL-82-LFr" firstAttribute="width" secondItem="aTr-Vm-6rY" secondAttribute="width" multiplier="0.95" id="Lxc-o6-DlX"/>
<constraint firstItem="aeL-82-LFr" firstAttribute="top" secondItem="aTr-Vm-6rY" secondAttribute="top" constant="8" id="dML-yb-tD6"/>
<constraint firstItem="aeL-82-LFr" firstAttribute="height" secondItem="aTr-Vm-6rY" secondAttribute="height" multiplier="0.95" priority="250" id="hat-KF-nTV"/>
<constraint firstAttribute="trailing" secondItem="aeL-82-LFr" secondAttribute="trailing" constant="8" id="vZq-Fz-6j0"/>
</constraints>
<viewLayoutGuide key="contentLayoutGuide" id="JcU-2C-NY5"/>
<viewLayoutGuide key="frameLayoutGuide" id="bmL-Em-YCg"/>
</scrollView>
</subviews>
<viewLayoutGuide key="safeArea" id="WPH-3T-daB"/>
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
<constraints>
<constraint firstItem="aTr-Vm-6rY" firstAttribute="trailing" secondItem="WPH-3T-daB" secondAttribute="trailing" id="4rZ-6y-E1k"/>
<constraint firstItem="aTr-Vm-6rY" firstAttribute="top" secondItem="WPH-3T-daB" secondAttribute="top" id="Bz8-iZ-NnM"/>
<constraint firstItem="aTr-Vm-6rY" firstAttribute="leading" secondItem="WPH-3T-daB" secondAttribute="leading" id="iJD-Pb-UYf"/>
<constraint firstItem="aTr-Vm-6rY" firstAttribute="bottom" secondItem="LIA-2s-RvE" secondAttribute="bottom" id="yW8-WZ-Ncl"/>
</constraints>
</view>
<navigationItem key="navigationItem" largeTitleDisplayMode="never" id="DOH-gv-btw"/>
<connections>
<outlet property="containerView" destination="aeL-82-LFr" id="q7p-FM-mfN"/>
<outlet property="descriptionTextLabel" destination="1Wb-RN-Qxg" id="yaP-xh-l6b"/>
<outlet property="discountTextLabel" destination="Ywi-cF-AR3" id="SoR-jd-nic"/>
<outlet property="openPrivacyButton" destination="Xkb-Nt-Fiw" id="WkY-zF-a7Q"/>
<outlet property="openTermsButton" destination="dnA-Yy-Ado" id="sSC-zA-oN3"/>
<outlet property="payingLabel" destination="gGN-X8-wUL" id="fwS-vm-CJ2"/>
<outlet property="priceLabel" destination="Z3v-8b-VXq" id="UGJ-O7-GyN"/>
<outlet property="purchaseButton" destination="xwb-Pw-WFu" id="2NS-RB-d9h"/>
<outlet property="subtitleLabel" destination="6z8-bz-exh" id="6ed-t2-QOE"/>
<outlet property="titleLabel" destination="x3N-F9-QOy" id="Ubq-Qo-I4B"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Uos-pR-6Y7" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-6853" y="-8737"/>
</scene>
<!--Subscription Detail View Controller-->
<scene sceneID="KcG-m4-Pc9">
<objects>
@@ -308,7 +157,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="tMI-5n-taJ" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-5085" y="-8358"/>
<point key="canvasLocation" x="-4962" y="-7442"/>
</scene>
<!--Seismic Networks View Controller-->
<scene sceneID="eh7-nk-hxX">
@@ -385,14 +234,14 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="Last24HCell" id="gCd-P1-ZLD" customClass="SegnalazioniLast24HoursCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="50" width="414" height="172.5"/>
<rect key="frame" x="0.0" y="50" width="414" height="187"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="gCd-P1-ZLD" id="R8c-1D-IWG">
<rect key="frame" x="0.0" y="0.0" width="414" height="172.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="187"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="E79-AU-OmF">
<rect key="frame" x="8" y="8" width="398" height="156.5"/>
<rect key="frame" x="8" y="8" width="398" height="171"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Reports" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A3b-4E-9kc" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="61.5" height="26"/>
@@ -405,7 +254,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="uGH-T6-e5M">
<rect key="frame" x="8" y="108.5" width="382" height="40"/>
<rect key="frame" x="8" y="123" width="382" height="40"/>
<subviews>
<button opaque="NO" tag="4" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K8a-lu-weO" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="118" height="40"/>
@@ -441,13 +290,13 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
</constraints>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1307" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h9p-Vt-6LT">
<rect key="frame" x="166" y="36" width="66.5" height="33.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="28"/>
<rect key="frame" x="155" y="36" width="88.5" height="48"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<color key="textColor" name="Red"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="reports in the last 24h" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JTH-0J-HIU">
<rect key="frame" x="10" y="78" width="378" height="20.5"/>
<rect key="frame" x="10" y="92.5" width="378" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
@@ -489,7 +338,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="ReportEarthquakeCell" id="Vrl-pa-Wbl" customClass="SegnalazioniSendReportCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="222.5" width="414" height="736.5"/>
<rect key="frame" x="0.0" y="237" width="414" height="736.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Vrl-pa-Wbl" id="Jec-Wo-woH">
<rect key="frame" x="0.0" y="0.0" width="414" height="736.5"/>
@@ -931,7 +780,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<objects>
<tableViewController id="pmz-iO-KAJ" customClass="SeismicSettingsNetworksViewController" customModule="Earthquake_Network" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="rap-tS-Jjb">
<rect key="frame" x="0.0" y="0.0" width="414" height="838"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="886"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
<connections>
@@ -1472,7 +1321,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="PGf-04-LJ4" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-5876" y="-8357"/>
<point key="canvasLocation" x="-5754" y="-7441"/>
</scene>
<!--Main Tab Bar Controller-->
<scene sceneID="ZSH-pu-BI9">
@@ -1501,17 +1350,17 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<objects>
<viewController storyboardIdentifier="EQNLogViewController" id="noK-2F-IZE" customClass="EQNLogViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="6P7-SV-yrd">
<rect key="frame" x="0.0" y="0.0" width="414" height="838"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="886"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="ija-iK-2hE">
<rect key="frame" x="0.0" y="20" width="414" height="760"/>
<rect key="frame" x="0.0" y="20" width="414" height="808"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g5C-Wg-DEu">
<rect key="frame" x="16" y="788" width="382" height="30"/>
<rect key="frame" x="16" y="836" width="382" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="CFr-4Z-X1A"/>
</constraints>
@@ -1831,7 +1680,7 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="200" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="a35-sg-TCr">
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="200" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="a35-sg-TCr">
<rect key="frame" x="0.0" y="92" width="414" height="666"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
@@ -1891,38 +1740,38 @@ In più sostieni il progetto di ricerca il quale non riceve finanziamenti estern
<outlet property="messageLabel" destination="SuO-hV-kUz" id="NaR-eN-Dko"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="SeismicNotificationExpandedCell" rowHeight="610" id="C7v-rs-1fb" customClass="AlertsSeismicNotificationExpandedTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="208" width="414" height="610"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="SeismicNotificationExpandedCell" rowHeight="700" id="C7v-rs-1fb" customClass="AlertsSeismicNotificationExpandedTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="208" width="414" height="700"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="C7v-rs-1fb" id="aEH-vE-u7m">
<rect key="frame" x="0.0" y="0.0" width="414" height="610"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="700"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TfA-6E-CQc">
<rect key="frame" x="8" y="8" width="398" height="594"/>
<rect key="frame" x="8" y="8" width="398" height="684"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Rilevato un sisma debole a 150 km (Test)" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="M7i-e5-N6v">
<rect key="frame" x="8" y="8" width="382" height="61"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Rilevato un sisma debole a 150 km (Test)" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="M7i-e5-N6v">
<rect key="frame" x="8" y="8" width="382" height="67.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<color key="textColor" name="Red"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DyB-fs-sPo">
<rect key="frame" x="8" y="81" width="382" height="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DyB-fs-sPo">
<rect key="frame" x="8" y="87.5" width="382" height="42.5"/>
<string key="text">Distanza 149 km - 0 minuti fa
Sisma rilevato da 10 smartphone</string>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="tqM-QH-LJ3">
<rect key="frame" x="0.0" y="125" width="398" height="254"/>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="tqM-QH-LJ3">
<rect key="frame" x="0.0" y="172.5" width="398" height="287"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="240" id="w6M-Ao-KHo"/>
</constraints>
</mapView>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Q2V-3p-DUh">
<rect key="frame" x="8" y="387" width="382" height="40"/>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Q2V-3p-DUh">
<rect key="frame" x="8" y="467.5" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="V2G-UH-Ibe" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
@@ -1949,8 +1798,8 @@ Sisma rilevato da 10 smartphone</string>
<constraint firstAttribute="height" constant="40" id="Qe8-J8-tY6"/>
</constraints>
</stackView>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Jwx-kf-che" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="8" y="435" width="382" height="40"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Jwx-kf-che" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="8" y="515.5" width="382" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="VIEW ON TWITTER">
<color key="titleColor" name="Gray (dark)"/>
@@ -1959,14 +1808,14 @@ Sisma rilevato da 10 smartphone</string>
<action selector="viewInTwitterTapped:" destination="C7v-rs-1fb" eventType="touchUpInside" id="djx-1X-bbD"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="The magnitude will be estimated by the national seismic network and it will appear in the Seismic Networks tab of the app" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GIh-sK-KX1">
<rect key="frame" x="8" y="483" width="382" height="55"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="The magnitude will be estimated by the national seismic network and it will appear in the Seismic Networks tab of the app" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GIh-sK-KX1">
<rect key="frame" x="8" y="563.5" width="382" height="64.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3Ga-UF-Cr7" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="8" y="546" width="382" height="40"/>
<rect key="frame" x="8" y="636" width="382" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="CLOSE">
<color key="titleColor" name="Gray (dark)"/>
@@ -1975,14 +1824,23 @@ Sisma rilevato da 10 smartphone</string>
<action selector="closeTapped:" destination="C7v-rs-1fb" eventType="touchUpInside" id="y39-44-3gS"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Rilevato scuotimento forte" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xb4-4c-oEd">
<rect key="frame" x="8" y="138" width="382" height="26.5"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="22"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="3Ga-UF-Cr7" firstAttribute="trailing" secondItem="GIh-sK-KX1" secondAttribute="trailing" id="1qg-dS-vGZ"/>
<constraint firstItem="DyB-fs-sPo" firstAttribute="top" secondItem="M7i-e5-N6v" secondAttribute="bottom" constant="12" id="7gG-Y2-tda"/>
<constraint firstAttribute="trailing" secondItem="GIh-sK-KX1" secondAttribute="trailing" constant="8" id="8TC-4t-7fC"/>
<constraint firstItem="tqM-QH-LJ3" firstAttribute="top" secondItem="Xb4-4c-oEd" secondAttribute="bottom" constant="8" id="9Nv-Zb-mlE"/>
<constraint firstItem="Xb4-4c-oEd" firstAttribute="trailing" secondItem="DyB-fs-sPo" secondAttribute="trailing" id="F4e-yh-mKB"/>
<constraint firstAttribute="trailing" secondItem="tqM-QH-LJ3" secondAttribute="trailing" id="Gf0-a2-jaj"/>
<constraint firstItem="3Ga-UF-Cr7" firstAttribute="height" secondItem="Q2V-3p-DUh" secondAttribute="height" id="N2x-vd-6D6"/>
<constraint firstItem="Xb4-4c-oEd" firstAttribute="leading" secondItem="DyB-fs-sPo" secondAttribute="leading" id="QAk-d3-ZOG"/>
<constraint firstItem="Jwx-kf-che" firstAttribute="trailing" secondItem="Q2V-3p-DUh" secondAttribute="trailing" id="Qie-q3-No5"/>
<constraint firstItem="Q2V-3p-DUh" firstAttribute="top" secondItem="tqM-QH-LJ3" secondAttribute="bottom" constant="8" id="TM2-ig-acw"/>
<constraint firstItem="Jwx-kf-che" firstAttribute="top" secondItem="Q2V-3p-DUh" secondAttribute="bottom" constant="8" id="Wjc-dF-bMj"/>
@@ -1991,12 +1849,12 @@ Sisma rilevato da 10 smartphone</string>
<constraint firstItem="DyB-fs-sPo" firstAttribute="leading" secondItem="M7i-e5-N6v" secondAttribute="leading" id="ZHJ-oa-DjC"/>
<constraint firstItem="Jwx-kf-che" firstAttribute="height" secondItem="Q2V-3p-DUh" secondAttribute="height" id="Zp0-Q0-p0q"/>
<constraint firstItem="Q2V-3p-DUh" firstAttribute="leading" secondItem="TfA-6E-CQc" secondAttribute="leading" constant="8" id="ZsU-Ec-9Bc"/>
<constraint firstItem="tqM-QH-LJ3" firstAttribute="top" secondItem="DyB-fs-sPo" secondAttribute="bottom" constant="8" id="aMh-uU-aG8"/>
<constraint firstAttribute="trailing" secondItem="Q2V-3p-DUh" secondAttribute="trailing" constant="8" id="bmi-oa-9ss"/>
<constraint firstItem="tqM-QH-LJ3" firstAttribute="leading" secondItem="TfA-6E-CQc" secondAttribute="leading" id="gUO-ka-XvB"/>
<constraint firstAttribute="bottom" secondItem="3Ga-UF-Cr7" secondAttribute="bottom" constant="8" id="gWA-6h-HmJ"/>
<constraint firstItem="DyB-fs-sPo" firstAttribute="trailing" secondItem="M7i-e5-N6v" secondAttribute="trailing" id="jD7-QV-p8s"/>
<constraint firstItem="GIh-sK-KX1" firstAttribute="top" secondItem="Jwx-kf-che" secondAttribute="bottom" constant="8" id="nJj-g4-TSs"/>
<constraint firstItem="Xb4-4c-oEd" firstAttribute="top" secondItem="DyB-fs-sPo" secondAttribute="bottom" constant="8" symbolic="YES" id="pct-jg-eJW"/>
<constraint firstItem="3Ga-UF-Cr7" firstAttribute="top" secondItem="GIh-sK-KX1" secondAttribute="bottom" constant="8" id="qaQ-zK-ael"/>
<constraint firstItem="M7i-e5-N6v" firstAttribute="leading" secondItem="TfA-6E-CQc" secondAttribute="leading" constant="8" id="rsV-dp-eqa"/>
<constraint firstItem="M7i-e5-N6v" firstAttribute="top" secondItem="TfA-6E-CQc" secondAttribute="top" constant="8" id="seX-2q-JVM"/>
@@ -2019,6 +1877,7 @@ Sisma rilevato da 10 smartphone</string>
<outlet property="descriptionLabel" destination="GIh-sK-KX1" id="L4X-lK-CVb"/>
<outlet property="mapView" destination="tqM-QH-LJ3" id="Gp4-gu-q8r"/>
<outlet property="notificationDescriptionLabel" destination="DyB-fs-sPo" id="aLr-34-WND"/>
<outlet property="notificationIntensityLabel" destination="Xb4-4c-oEd" id="QFh-Jd-pLP"/>
<outlet property="notificationTitleLabel" destination="M7i-e5-N6v" id="RqD-wo-sXl"/>
<outlet property="rateAppButton" destination="n9y-jx-2xG" id="mvX-2K-I6i"/>
<outlet property="shareButton" destination="V2G-UH-Ibe" id="JT4-jR-d45"/>
@@ -2026,25 +1885,25 @@ Sisma rilevato da 10 smartphone</string>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="SeismicNotificationCell" rowHeight="190" id="vSa-gk-t22" customClass="AlertsSeismicNotificationCompactTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="818" width="414" height="190"/>
<rect key="frame" x="0.0" y="908" width="414" height="190"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="vSa-gk-t22" id="qvZ-sA-Sqc">
<rect key="frame" x="0.0" y="0.0" width="414" height="190"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1qM-9D-X99">
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1qM-9D-X99">
<rect key="frame" x="8" y="8" width="398" height="174"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No real time alert recently received by your smartphone" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqv-yY-TAs">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="No real time alert recently received by your smartphone" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqv-yY-TAs">
<rect key="frame" x="8" y="8" width="382" height="62"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" red="0.047058823529411764" green="0.62745098039215685" blue="0.13725490196078433" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="Green"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="R9F-ba-WMK">
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="R9F-ba-WMK">
<rect key="frame" x="8" y="78" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BjK-4E-Vhw" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BjK-4E-Vhw" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="TEST ALERT 🚨">
@@ -2054,7 +1913,7 @@ Sisma rilevato da 10 smartphone</string>
<action selector="testAlertTapped" destination="vSa-gk-t22" eventType="touchUpInside" id="HNp-eo-vpW"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="195" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="SIMULATOR ⏱">
@@ -2069,10 +1928,10 @@ Sisma rilevato da 10 smartphone</string>
<constraint firstAttribute="height" constant="40" id="EgR-4H-j5l"/>
</constraints>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ETL-qq-Abj">
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ETL-qq-Abj">
<rect key="frame" x="8" y="126" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aAC-Wz-fKA" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aAC-Wz-fKA" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="HOW IT WORKS 💡">
@@ -2082,7 +1941,7 @@ Sisma rilevato da 10 smartphone</string>
<action selector="howItWorksTapped" destination="vSa-gk-t22" eventType="touchUpInside" id="kLj-v8-6JR"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tml-Pn-Faa" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tml-Pn-Faa" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="195" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="SHARE APP 👥">
@@ -2098,7 +1957,7 @@ Sisma rilevato da 10 smartphone</string>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" red="0.78431372549019607" green="0.88627450980392153" blue="0.76862745098039209" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="Green (card background)"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="R9F-ba-WMK" secondAttribute="trailing" constant="8" id="7Lx-oc-69N"/>
<constraint firstAttribute="trailing" secondItem="aqv-yY-TAs" secondAttribute="trailing" constant="8" id="E7n-uW-YVI"/>
@@ -2131,7 +1990,7 @@ Sisma rilevato da 10 smartphone</string>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="PastEarthquakesCell" rowHeight="160" id="R3G-Bh-LLr" customClass="AlertsPastEartquakesTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="1008" width="414" height="160"/>
<rect key="frame" x="0.0" y="952" width="414" height="160"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="R3G-Bh-LLr" id="UH4-vm-Tld">
<rect key="frame" x="0.0" y="0.0" width="414" height="160"/>
@@ -2210,7 +2069,7 @@ Sisma rilevato da 10 smartphone</string>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="SmartphoneNetworkCell" rowHeight="170" id="YUf-dd-IFz" customClass="AlertsSmartphoneNetworkTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="1168" width="414" height="170"/>
<rect key="frame" x="0.0" y="1112" width="414" height="170"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="YUf-dd-IFz" id="BkM-63-VOb">
<rect key="frame" x="0.0" y="0.0" width="414" height="170"/>
@@ -2229,17 +2088,17 @@ Sisma rilevato da 10 smartphone</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillProportionally" translatesAutoresizingMaskIntoConstraints="NO" id="niE-pg-jos">
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="niE-pg-jos">
<rect key="frame" x="8" y="30" width="382" height="72"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" tag="10" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r3y-EB-oyz">
<rect key="frame" x="0.0" y="0.0" width="382" height="37"/>
<label opaque="NO" userInteractionEnabled="NO" tag="10" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r3y-EB-oyz">
<rect key="frame" x="0.0" y="0.0" width="382" height="26.5"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<color key="textColor" red="0.0039215686274509803" green="0.70588235294117641" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="smartphones are monitoring for earthquakes" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dnR-12-9yN">
<rect key="frame" x="0.0" y="37" width="382" height="35"/>
<rect key="frame" x="0.0" y="26.5" width="382" height="45.5"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
@@ -2292,7 +2151,7 @@ Sisma rilevato da 10 smartphone</string>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="PriorityCell" rowHeight="170" id="gXs-mo-UQM" customClass="AlertsPriorityServiceTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="1338" width="414" height="170"/>
<rect key="frame" x="0.0" y="1282" width="414" height="170"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="gXs-mo-UQM" id="ViI-oT-s00">
<rect key="frame" x="0.0" y="0.0" width="414" height="170"/>
@@ -2323,7 +2182,7 @@ Sisma rilevato da 10 smartphone</string>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="A user has subscribed to the service only %d minute ago!" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3dQ-Eh-0Iw">
<rect key="frame" x="0.0" y="69.5" width="284" height="42.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" name="Red"/>
<color key="textColor" red="0.84313725490196079" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -2343,7 +2202,7 @@ Sisma rilevato da 10 smartphone</string>
</constraints>
</button>
</subviews>
<color key="backgroundColor" red="1" green="0.76757928289999999" blue="0.82206648469999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" name="Red (card background)"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="3Hs-fb-4gz" secondAttribute="trailing" constant="4" id="1Eb-F0-Of7"/>
<constraint firstItem="3Hs-fb-4gz" firstAttribute="top" secondItem="GF8-ah-qqT" secondAttribute="top" constant="8" id="ARk-iV-frQ"/>
@@ -2374,80 +2233,17 @@ Sisma rilevato da 10 smartphone</string>
<outlet property="lastSubscriptionLabel" destination="3dQ-Eh-0Iw" id="X5B-rI-e64"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ProVersionCell" rowHeight="140" id="oTE-5k-bAN" customClass="AlertsProVersionTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="1508" width="414" height="140"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="oTE-5k-bAN" id="Axb-Lq-NhB">
<rect key="frame" x="0.0" y="0.0" width="414" height="140"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GwC-Fx-oW5">
<rect key="frame" x="8" y="8" width="398" height="124"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="PRO version" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xzn-UB-fHZ" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="95.5" height="26"/>
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="26" id="VXS-LF-Wav"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Convert your app into the PRO version! Find out how." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FKw-uA-rrj">
<rect key="frame" x="8" y="34" width="274" height="82"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="eq_icon_pro" translatesAutoresizingMaskIntoConstraints="NO" id="FtR-zF-azV">
<rect key="frame" x="290" y="8" width="100" height="108"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="TdU-tN-yRU"/>
<constraint firstAttribute="width" constant="100" id="uf4-y9-X0f"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Xzn-UB-fHZ" secondAttribute="trailing" priority="250" id="1Y1-jb-GeU"/>
<constraint firstAttribute="bottom" secondItem="FKw-uA-rrj" secondAttribute="bottom" constant="8" id="FfF-7o-4II"/>
<constraint firstItem="Xzn-UB-fHZ" firstAttribute="top" secondItem="GwC-Fx-oW5" secondAttribute="top" id="Op3-0f-RlP"/>
<constraint firstItem="FtR-zF-azV" firstAttribute="leading" secondItem="FKw-uA-rrj" secondAttribute="trailing" constant="8" id="UcN-gq-pds"/>
<constraint firstItem="Xzn-UB-fHZ" firstAttribute="leading" secondItem="GwC-Fx-oW5" secondAttribute="leading" id="Wec-Bt-jXu"/>
<constraint firstItem="FKw-uA-rrj" firstAttribute="top" secondItem="Xzn-UB-fHZ" secondAttribute="bottom" constant="8" id="apc-pf-rt6"/>
<constraint firstItem="FKw-uA-rrj" firstAttribute="leading" secondItem="GwC-Fx-oW5" secondAttribute="leading" constant="8" id="qDb-ks-pmZ"/>
<constraint firstAttribute="bottom" secondItem="FtR-zF-azV" secondAttribute="bottom" constant="8" id="tF5-UF-BzX"/>
<constraint firstItem="FtR-zF-azV" firstAttribute="top" secondItem="GwC-Fx-oW5" secondAttribute="top" constant="8" id="tvV-GA-67z"/>
<constraint firstAttribute="trailing" secondItem="FtR-zF-azV" secondAttribute="trailing" constant="8" id="vQ3-t7-ss9"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="GwC-Fx-oW5" firstAttribute="leading" secondItem="Axb-Lq-NhB" secondAttribute="leading" constant="8" id="d76-Ro-N7g"/>
<constraint firstAttribute="bottom" secondItem="GwC-Fx-oW5" secondAttribute="bottom" constant="8" id="gfC-Rd-omx"/>
<constraint firstAttribute="trailing" secondItem="GwC-Fx-oW5" secondAttribute="trailing" constant="8" id="ins-7n-mgr"/>
<constraint firstItem="GwC-Fx-oW5" firstAttribute="top" secondItem="Axb-Lq-NhB" secondAttribute="top" constant="8" id="xic-gi-AVe"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<connections>
<outlet property="containerView" destination="GwC-Fx-oW5" id="WJ0-hI-evI"/>
<outlet property="descriptionLabel" destination="FKw-uA-rrj" id="hmw-oR-m94"/>
<outlet property="headerLabel" destination="Xzn-UB-fHZ" id="sQP-Ye-1xg"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="PositionDataCell" rowHeight="180" id="j9i-Sk-o3g" customClass="AlertsPositionDataTableViewCell" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="1648" width="414" height="180"/>
<rect key="frame" x="0.0" y="1452" width="414" height="180"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="j9i-Sk-o3g" id="sTW-Bj-7Bz">
<rect key="frame" x="0.0" y="0.0" width="414" height="180"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6ZO-bn-4Ts">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6ZO-bn-4Ts">
<rect key="frame" x="8" y="8" width="398" height="164"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Location data" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fad-hA-QMI" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location data" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fad-hA-QMI" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="106" height="26"/>
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
@@ -2457,20 +2253,20 @@ Sisma rilevato da 10 smartphone</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" distribution="equalSpacing" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Da7-5h-Ygg">
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Da7-5h-Ygg">
<rect key="frame" x="8" y="34" width="382" height="122"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="FuC-We-4gX">
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="FuC-We-4gX">
<rect key="frame" x="0.0" y="0.0" width="382" height="30"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="world_old" translatesAutoresizingMaskIntoConstraints="NO" id="bzL-JH-hKh">
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="world_old" translatesAutoresizingMaskIntoConstraints="NO" id="bzL-JH-hKh">
<rect key="frame" x="0.0" y="0.0" width="30" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="jOu-FA-Gwf"/>
<constraint firstAttribute="width" constant="30" id="xV8-FI-pld"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RJa-D0-IZ3">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RJa-D0-IZ3">
<rect key="frame" x="40" y="0.0" width="342" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@@ -2478,17 +2274,17 @@ Sisma rilevato da 10 smartphone</string>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="jet-Ib-N0B">
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="jet-Ib-N0B">
<rect key="frame" x="0.0" y="46" width="382" height="30"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="sunrise" translatesAutoresizingMaskIntoConstraints="NO" id="AvA-JA-qjr">
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sunrise" translatesAutoresizingMaskIntoConstraints="NO" id="AvA-JA-qjr">
<rect key="frame" x="0.0" y="0.0" width="30" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="4cB-mI-Zwn"/>
<constraint firstAttribute="width" constant="30" id="9dN-Zk-aJ6"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AHy-jM-xYy">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AHy-jM-xYy">
<rect key="frame" x="40" y="0.0" width="342" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@@ -2496,17 +2292,17 @@ Sisma rilevato da 10 smartphone</string>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Fw9-DV-pub">
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Fw9-DV-pub">
<rect key="frame" x="0.0" y="92" width="382" height="30"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="sunset" translatesAutoresizingMaskIntoConstraints="NO" id="JSz-gM-Yu0">
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sunset" translatesAutoresizingMaskIntoConstraints="NO" id="JSz-gM-Yu0">
<rect key="frame" x="0.0" y="0.0" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="Kph-Tq-6Ab"/>
<constraint firstAttribute="height" constant="30" id="NQA-Ro-Xoc"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="40V-zE-37M">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="40V-zE-37M">
<rect key="frame" x="40" y="0.0" width="342" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@@ -2592,7 +2388,6 @@ Sisma rilevato da 10 smartphone</string>
<outlet property="bannerContainerView" destination="PyX-yA-DXv" id="KjR-S3-WEU"/>
<outlet property="expandeCollapseButton" destination="pbW-2s-ktg" id="QmE-Nl-SmO"/>
<outlet property="tableView" destination="a35-sg-TCr" id="OhR-Ty-elu"/>
<segue destination="rRh-R0-bas" kind="show" identifier="ShowProVersion" id="phk-Ww-RSV"/>
<segue destination="cXN-cY-DjM" kind="show" identifier="ShowPrioritySubscriptions" id="yhm-9X-yNM"/>
</connections>
</viewController>
@@ -2602,7 +2397,6 @@ Sisma rilevato da 10 smartphone</string>
</scene>
</scenes>
<resources>
<image name="eq_icon_pro" width="166" height="166"/>
<image name="icon-arrow-down" width="83" height="42"/>
<image name="navbar-icon-arrow-collapse" width="24" height="24"/>
<image name="navbar-icon-earth" width="24" height="24"/>
@@ -2623,6 +2417,12 @@ Sisma rilevato da 10 smartphone</string>
<namedColor name="Gray (dark)">
<color red="0.10999999940395355" green="0.13300000131130219" blue="0.14900000393390656" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Green">
<color red="0.0" green="0.56470588235294117" blue="0.31764705882352939" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Green (card background)">
<color red="0.58039215686274515" green="0.83137254901960789" blue="0.50980392156862742" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Light blue">
<color red="0.50599998235702515" green="0.75300002098083496" blue="0.98000001907348633" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
@@ -2662,6 +2462,9 @@ Sisma rilevato da 10 smartphone</string>
<namedColor name="Red">
<color red="1" green="0.14900000393390656" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Red (card background)">
<color red="0.99607843137254903" green="0.62745098039215685" blue="0.67843137254901964" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="groupTableViewBackgroundColor">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Απαιτείται πρόσβαση στη βιβλιοθήκη για να αποθηκεύσετε τις εικόνες που δημιουργούνται από την εφαρμογή";
"NSCalendarsUsageDescription" = "Απαιτείται πρόσβαση στο ημερολόγιο προκειμένου να σωθούν οι πληροφορίες των σεισμών ενδιαφέροντος";
"NSContactsUsageDescription" = "Απαιτείται πρόσβαση στις επαφές για να προσθέσετε άτομα στα δημιουργημένα συμβάντα";
"NSUserTrackingUsageDescription" = "Η παρακολούθηση χρησιμοποιείται για να κατανοήσουμε εάν η διαφήμιση της εφαρμογής είναι αποτελεσματική";
"CFBundleDisplayName" = "Ανιχνευτής Σεισμών";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Ισχυρός σεισμός που αναφέρθηκε από έναν χρήστη στο %@";
"Sisma molto forte segnalato da utente a" = "Πολύ ισχυρός σεισμός που αναφέρθηκε από έναν χρήστη στο %@";
"Sisma rilevato a" = "Ο σεισμός ανιχνεύθηκε στο %@";
"alert_intensity_no_shaking" = "Δεν γίνεται αισθητό στην τοποθεσία σας";
"alert_intensity_mild" = "Να περιμένετε ήπιο ή καθόλου κούνημα";
"alert_intensity_moderate" = "Να περιμένετε μέτριο τίναγμα";
"alert_intensity_strong" = "Να περιμένετε ισχυρό τίναγμα";
// aligned with Android
"drawer_main_settings" = "Ρυθμίσεις";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: %lu εγγραφές είναι ακόμη διαθέσιμες για ειδοποίηση σε λιγότερο από 1 δευτερόλεπτο από την ανίχνευση του σεισμού";
"inapp_available_100k" = "Top 100K: %lu εγγραφή είναι ακόμη διαθέσιμη για ειδοποίηση σε λιγότερο από 5 δευτερόλεπτα από την ανίχνευση του σεισμού";
"filter_magnitude" = "Ελάχιστο μέγεθος";
"filter_distance" = "Μέγιστη απόσταση";
"filter_timeframe" = "Χρονικό πλαίσιο";
"filter_strong" = "Εμφάνιση ισχυρών σεισμών σε οποιαδήποτε απόσταση εάν είναι";
"filter_near" = "Δείξτε σεισμούς οποιουδήποτε μεγέθους σε απόσταση μικρότερη των 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ σε ακτίνα 100χλμ";
"official_smartphones" = "Εντοπίστηκε σεισμός σε πραγματικό χρόνο από %@ smartphone. Η ειδοποίηση ενεργοποιήθηκε.";
"official_reports" = "Αναφέρθηκαν από %@ χρήστες";
"weather_weather" = "Ο καιρός κατά την διάρκεια του σεισμού";
"weather_temperature" = "Θερμοκρασία: %.02f";
"weather_pressure" = "Πίεση: %@";
"weather_windspeed" = "Ταχύτητα ανέμου: %@";
"weather_humidity" = "Υγρασία: %@";
"weather_clouds" = "Κάλυψη νεφών: %@";
"weather_nodata" = "Δεν υπάρχουν διαθέσιμα μετεωρολογικά δεδομένα για τον σεισμό αυτό";
"official_prelimiary" = "ΠΡΟΚΑΤΑΡΚΤΙΚΟ";
"calendar_description_nogeo_km" = "Σεισμός M%@, βάθος %@ km.";
"filter_empty" = "Σύμφωνα με τα φίλτρα και τα ενεργοποιημένα σεισμικά δίκτυα, δεν υπάρχουν σεισμοί τις τελευταίες 24 ώρες. Για την αλλαγή των φίλτρων κάνε κλικ στην γραμμή στο κάτω μέρος. Για να ενεργοποιήσεις άλλα σεισμικά δίκτυα κάνε κλικ στο εικονίδιο κόσμος στο επάνω μέρος.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Επιβεβαίωση χώρας";
"share_hashtag" = "#σεισμός";
"share_notified" = "Έχει αναφερθεί μέσω της εφαρμογής Ανιχνευτής Σεισμών. Κατέβασε την εφαρμογή από το https://sismo.app/download/ για να λαμβάνεις σε πραγματικό χρόνο ειδοποιήσεις #σεισμού @SismoDetector";
"share_felt" = "Αισθητός σε";
"manual_sure" = "Θέλεις πράγματι να κοινοποιήσεις έναν σεισμό;";
"manual_yes" = "Ναι";
"filter_filter" = "Φίλτρα";
"manual_sendmessage" = "Στείλε ένα μήνυμα που μπορούν να διαβάσουν οι άλλοι χρήστες για τον σεισμό που ανέφερες ";
"manual_message_received" = "Το μήνυμα λήφθηκε";
"liveview_unknown_location" = "Η θέση σου είναι άγνωστη. Ενεργοποίησε την τοποθεσία του smartphone από την διαμόρφωση του smartphone";
"map_number" = "Ανιχνεύθηκε δόνηση από %@ smartphone";
"permission_location_no" = "Έχεις επιλέξει να αποτρέπεις την εφαρμογή από την ανάγνωση της τοποθεσίας της συσκευής. ΔΕΝ θα λαμβάνεις κοινοποιήσεις και ειδοποιήσεις σε πραγματικό χρόνο";
"permission_location_no_background" = "Έχεις επιλέξει να αποτρέπεις την εφαρμογή από την ανάγνωση της τοποθεσίας της συσκευής σου όταν η εφαρμογή είναι σε background. Μπορεί να ΜΗΝ λαμβάνονται κοινοποιήσεις και ειδοποιήσεις σε πραγματικό χρόνο ";
"alert_wave" = "Σεισμικό κύμα σε %lu δευτερόλεπτα";
"share_yourtime" = "(Η ώρα σου)";
"official_close" = "Κλείσιμο";
"main_share" = "Mοιράσου";
"widget_mild" = "Ήπιος";
"widget_strong" = "Ισχυρός";
"widget_verystring" = "Πολύ ισχυρός";
"main_simulator" = "Προσομοιωτής";
"globe_simulation_button" = "Υπολόγισε τον χρόνο προειδοποίησης";
"globe_simulation" = "Εάν το επίκεντρο του σεισμού είναι έξω από τον κόκκινο δίσκο και η δόνηση έχει ανιχνευτεί αμέσως από τα smartphone, θα λάβεις την ειδοποίηση πάνω από 5 δευτερόλεπτα νωρίτερα. Επέλεξε στον χάρτη το πιθανό επίκεντρο για να υπολογίσεις τον χρόνο προειδοποίησης.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Με αυτό το επίκεντρο, χάρη στην υπηρεσία προτεραιότητας %@ θα λάβεις την ειδοποίηση %.0f δευτερόλεπτα νωρίτερα. %.0f άνθρωποι θα ειδοποιηθούν πριν από σένα. Για μεγαλύτερο χρόνο προειδοποίησης μπορείς να γραφτείς στην υπηρεσία προτεραιότητας %@";
"globe_simulation_message6" = "Με αυτό το επίκεντρο, χάρη στην υπηρεσία προτεραιότητας %@ θα λάβεις την ειδοποίηση %.0f δευτερόλεπτα νωρίτερα. Θα είσαι ο πρώτος που θα ειδοποιηθεί!";
"globe_simulation_priority" = "Υπηρεσία προτεραιότητας";
"options_cancel" = "Διαγραφή";
"status_cancel" = "Διαγραφή";
"options_near_alert" = "Κοινοποίηση σεισμών οποιουδήποτε μεγέθους εάν η απόσταση είναι κάτω από 50 km";
"options_alarms" = "Ειδοποίηση σε πραγματικό χρόνο";
"options_notification_enable_alarm" = "Να ακούγεται συναγερμός όταν ανιχνεύεται σεισμός σε πραγματικό χρόνο από το δίκτυο smartphone";
"options_notification_eqn_intensity" = "Ένταση σεισμού";
"eqn_intensity_any" = "Οποιαδήποτε ένταση";
"eqn_intensity_strong" = "Μόνο ισχυροί σεισμοί";
"options_radius_mild" = "Ακτίνα ήπιων σεισμών";
"options_radius_strong" = "Ακτίνα ισχυρών δονήσεων";
"options_notification_official" = "Κοινοποιήσεις σεισμικών δικτύων";
"options_notification_enable_official" = "Λήψη κοινοποιήσεων σεισμών που ανιχνεύονται από εθνικά και διεθνή σεισμικά δίκτυα.";
"options_agencies" = "Σεισμικά δίκτυα";
@@ -108,12 +94,7 @@
"main_map" = "αναφορές το τελευταίο 24ωρο";
"official_button_map" = "Χάρτης";
"main_feel" = "Αισθάνθηκα έναν σεισμό!";
"manual_usebutton" = "Πίεσε το παρακάτω κουμπί για να αναφέρεις έναν σεισμό";
"manual_mild" = "ΗΠΙΟΣ\n(Μόνο αισθητός)";
"manual_strong" = "ΙΣΧΥΡΟΣ\n(Πτώση αντικειμένων)";
"manual_verystrong" = "ΠΟΛΥ ΙΣΧΥΡΟΣ\n(Κατάρρευση κτιρίων)";
"network_pro" = "Έκδοση PRO";
"network_topro" = "Μετέτρεψε την εφαρμογή σου στην έκδοση PRO! Ανακάλυψε πώς.";
"network_pro_convert" = "Έναρξη μετατροπής";
"inapp_active" = "Ενεργή εγγραφή";
"inapp_nosub" = "Δεν υπάρχουν ενεργές εγγραφές";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Συντεταγμένες";
"official_card_population" = "Πληθυσμός";
"main_share_text" = "Γεια σου! Σου προτείνω την εφαρμογή του πρότζεκτ Earthquake Network με ειδοποιήσεις σε πραγματικό χρόνο. Κατέβασέ την από το https://sismo.app/download/ #σεισμός @SismoDetector";
"manual_sendmessage_button" = "Αποστολή μηνύματος";
"mercalli_II" = "II - Ελάχιστα αντιληπτό";
"mercalli_III" = "III - Δονήσεις παρόμοιες με φορτηγό που περνάει";
"mercalli_IV" = "IV - Δονήσεις παραθύρων, ελαφρές ταλαντώσεις κρεμαμένων αντικειμένων";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Μία ώρα";
"report_timeframe_ten_minutes" = "Δέκα λεπτά";
"radius_any_distance" = "Οποιαδήποτε απόσταση";
"timer_message2_other" = "%luχλμ από την τοποθεσία σας";
"official_distance" = "%luχλμ από την τοποθεσία σας";
"configuration_countries_united_states" = "Στάτη Ουνίτη";
"configuration_countries_italy" = "Ιταλία";
"configuration_countries_spain" = "Ισπανία";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Γαλλία";
"configuration_countries_croatia" = "Κροατία";
"configuration_countries_other" = "Άλλο";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "Αγοράζετε την έκδοση Pro, η διαφήμιση θα αφαιρεθεί";
"network_pro_privacy_disclaimer" = "Αποποίηση ευθυνών απορρήτου";
"network_pro_terms_conditions" = "Όροι και συνθήκες";
"network_pro_paying" = "Πληρώνετε:";
"inapp_detail_description" = "• Η πληρωμή σας θα χρεωθεί στο λογαριασμό σας στο iTunes κατά την επιβεβαίωση της αγοράς\n• η συνδρομή ανανεώνεται αυτόματα εκτός εάν η αυτόματη ανανέωση απενεργοποιείται τουλάχιστον 24 ώρες πριν από το τέλος της τρέχουσας περιόδου\n• η συνδρομή θα χρεωθεί για ανανέωση εντός 24 Ώρες πριν από το τέλος της τρέχουσας περιόδου και το κόστος ανανέωσης που εντοπίστηκαν\n• Οι συνδρομές μπορούν να διαχειριστούν από τον χρήστη και η αυτόματη ανανέωση μπορεί να απενεργοποιηθεί με την πρόσβαση στις ρυθμίσεις του λογαριασμού του χρήστη μετά την αγορά.";
"inapp_lifetime_detail_description" = "• Η πληρωμή σας θα χρεωθεί στο λογαριασμό σας στο iTunes κατά την επιβεβαίωση της αγοράς";
"inapp_purchase" = "ΕΓΓΡΑΦΕΊΤΕ ΣΤΗΝ ΥΠΗΡΕΣΊΑ";
@@ -235,20 +214,10 @@
"attention" = "Προσοχή";
"official_no_country_selected" = "Δεν έχετε επιλέξει καμία χώρα";
"report" = "Αναφορά";
"purchase_pro_description" = "Η έκδοση Pro δεν έχει καμία διαφημίσεις και θα περιλαμβάνει επιπλέον χαρακτηριστικά. Επιπλέον, συμβάλλετε στην υποστήριξη αυτού του ερευνητικού έργου που δεν λαμβάνει εξωτερικά κεφάλαια. Ευχαριστώ που εξετάζετε! Διαφορετικά, μπορείτε να έχετε την έκδοση PRO δωρεάν με την εγγραφή στην ετήσια υπηρεσία προτεραιότητας.";
"purchase_pro_discount" = "Αυτή είναι μια προσφορά μόνο για εσάς. Εάν μετατρέψετε την εφαρμογή στο Pro μέσα στις επόμενες 48 ώρες, έχετε έκπτωση 20%%. Θα έχετε μόνο αυτή την ευκαιρία. Μετά, η έκδοση Pro θα κοστίσει την πλήρη τιμή. Έχετε ακόμα %lu ώρες :-)";
"purchase_pro_restore" = "Επαναφέρω";
"purchase_pro_restore_alert_title" = "Επαναφέρω ολοκληρώθηκε";
"purchase_pro_restore_alert_message" = "Έχετε αποκαταστήσει το προϊόν που αγοράσατε";
"purchase_pro_no_subscriptions_alert_message" = "Δεν βρέθηκε αγορά αγοράς. Βεβαιωθείτε ότι έχετε συνδεθεί στο λογαριασμό, η αγορά έγινε με.";
"calendar_missing_permission" = "Το ημερολόγιο δεν μπορεί να ανοίξει, βεβαιωθείτε ότι έχετε ρυθμίσει τα σωστά δικαιώματα.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "Ένας χρήστης έχει εγγραφεί στην υπηρεσία μόνο πριν από %@!";
"minutes_one" = "%lu λεπτό";
"minutes_other" = "%lu λεπτά";
"hours_one" = "%lu ώρα";
"hours_other" = "%lu ώρες";
"days_one" = "%lu ημέρα";
"days_other" = "%lu ημέρες";
"error_server_registration" = "Δεν ήταν δυνατό να εγγραφείτε με το διακομιστή. Η εγγραφή υποχρεούται να λαμβάνει ειδοποιήσεις σε πραγματικό χρόνο και ειδοποιήσεις σεισμού.";
"retry" = "Προσπαθησε ξανα";
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Πριν ένα λεπτό</string>
<key>other</key>
<string>Πριν %d λεπτά</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Πριν μία ώρα</string>
<key>other</key>
<string>Πριν %d ώρες</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Πριν μία μέρα</string>
<key>other</key>
<string>Πριν %d ημέρες</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία μόνο πριν %d λεπτό!</string>
<key>other</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία μόνο πριν %d λεπτά!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία μόνο πριν %d ώρα!</string>
<key>other</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία μόνο πριν %d ώρες!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία πριν %d ημέρα.</string>
<key>other</key>
<string>Ένας χρήστης έχει εγγραφεί στην υπηρεσία πριν %d ημέρες!</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Σεισμικό κύμα σε %d δευτερόλεπτο</string>
<key>other</key>
<string>Σεισμικό κύμα σε %d δευτερόλεπτα</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Access to the library is required in order to save the images generated by the app";
"NSCalendarsUsageDescription" = "Access to the calendar is required in order to save the information of the earthquakes of interest";
"NSContactsUsageDescription" = "Access to contacts is required in order to add people to the created events";
"NSUserTrackingUsageDescription" = "Tracking is used to understand if the advertising of the app is effective";
"CFBundleDisplayName" = "Earthquake Network";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Strong quake reported by user at %@";
"Sisma molto forte segnalato da utente a" = "Very strong quake reported by user at %@";
"Sisma rilevato a" = "Quake detected at %@";
"alert_intensity_no_shaking" = "Not felt at your location";
"alert_intensity_mild" = "Expect mild or no shaking";
"alert_intensity_moderate" = "Expect moderate shaking";
"alert_intensity_strong" = "Expect strong shaking";
// aligned with Android
"drawer_main_settings" = "Settings";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: %lu subscriptions still available to be alerted in less than 1 second since the detection of the quake";
"inapp_available_100k" = "Top 100K: %lu subscriptions still available to be alerted in less than 5 seconds since the detection of the quake";
"filter_magnitude" = "Minimum magnitude";
"filter_distance" = "Maximum distance";
"filter_timeframe" = "Time frame";
"filter_strong" = "Show strong quakes at any distance if of";
"filter_near" = "Show quakes of any magnitude if closer than 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ in a radius of 100km";
"official_smartphones" = "Earthquake detected in real time by %@ smartphones. Alert issued.";
"official_reports" = "Reported by %@ users";
"weather_weather" = "Weather at the time of the quake";
"weather_temperature" = "Temperature: %.02f";
"weather_pressure" = "Pressure: %@";
"weather_windspeed" = "Wind speed: %@";
"weather_humidity" = "Humidity: %@";
"weather_clouds" = "Cloud coverage: %@";
"weather_nodata" = "No weather data are available for this quake";
"official_prelimiary" = "PRELIMINARY";
"calendar_description_nogeo_km" = "Earthquake M%@, depth %@ km.";
"filter_empty" = "Based on the filters and enabled seismic networks, there are no earthquakes in the last 24 hours. To change the filters click on the purple bar at the bottom. Use the icons in the top bar to change filters or enable other seismic networks.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Confirm country";
"share_hashtag" = "#earthquake";
"share_notified" = "Reported through the app Earthquake Network. Download the app from https://sismo.app/download/ to receive real time alerts of #earthquake @SismoDetector";
"share_felt" = "Felt in";
"manual_sure" = "Do you really want to notify an earthquake?";
"manual_yes" = "Yes";
"filter_filter" = "Filters";
"manual_sendmessage" = "Send a message that the other users can read about the earthquake that you reported";
"manual_message_received" = "Message received";
"liveview_unknown_location" = "Your position is unknown. Enable smartphone location from smartphone configuration";
"map_number" = "Quake detected by %@ smartphones";
"permission_location_no" = "You have chosen to prevent the app from reading the location of the device. You will NOT receive real-time notifications and alerts";
"permission_location_no_background" = "You have chosen to prevent the app from reading the location of your device when the app is in the background. Notifications and real time alerts may NOT be received";
"alert_wave" = "Seismic wave in %lu seconds";
"share_yourtime" = "(Your time)";
"official_close" = "Close";
"main_share" = "Share";
"widget_mild" = "Mild";
"widget_strong" = "Strong";
"widget_verystring" = "Very strong";
"main_simulator" = "Simulator";
"globe_simulation_button" = "Compute warning time";
"globe_simulation" = "If the earthquake epicentre is outside the red disk and the quake is immediately detected by the smartphones, you will receive the alert more than 5 seconds in advance. Select on map the possible epicentre in order to compute the warning time.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "With this epicentre, thanks to the %@ priority service you should receive the alert %.0f seconds in advance. %.0f people will be alerted before you. To increase the warning time you can subscribe to the %@ priority service";
"globe_simulation_message6" = "With this epicentre, thanks to the %@ priority service you should receive the alert %.0f seconds in advance. You will be the first to be alerted!";
"globe_simulation_priority" = "Priority service";
"options_cancel" = "Cancel";
"status_cancel" = "Cancel";
"options_near_alert" = "Notify earthquakes of any magnitude if the distance is less than 50 km";
"options_alarms" = "Real time alert";
"options_notification_enable_alarm" = "Activate an alarm when a quake is detected in real time by the network of smartphones";
"options_notification_eqn_intensity" = "Earthquake intensity";
"eqn_intensity_any" = "Any intensity";
"eqn_intensity_strong" = "Only strong earthquakes";
"options_radius_mild" = "Radius mild quakes";
"options_radius_strong" = "Radius strong quakes";
"options_notification_official" = "Seismic network notifications";
"options_notification_enable_official" = "Receive notifications for the earthquakes detected by the national and international seismic networks";
"options_agencies" = "Seismic networks";
@@ -108,12 +94,7 @@
"main_map" = "reports in the last 24h";
"official_button_map" = "Map";
"main_feel" = "I felt an earthquake!";
"manual_usebutton" = "Press the appropriate button below to report an earthquake";
"manual_mild" = "MILD\n(Only perceived)";
"manual_strong" = "STRONG\n(Fall of objects)";
"manual_verystrong" = "VERY STRONG\n(Building collapse)";
"network_pro" = "PRO version";
"network_topro" = "Convert your app into the PRO version! Find out how.";
"network_pro_convert" = "Start conversion";
"inapp_active" = "Active subscription";
"inapp_nosub" = "No active subscriptions";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Coordinates";
"official_card_population" = "Population";
"main_share_text" = "Hi! I suggest you the app of the Earthquake Network project with real time alerts. Download from https://sismo.app/download/ #earthquake @SismoDetector";
"manual_sendmessage_button" = "Send the message";
"mercalli_II" = "II - Barely perceived";
"mercalli_III" = "III - Vibrations similar to a truck passing by";
"mercalli_IV" = "IV - Vibrations of windows, slight oscillations of hanging objects";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "One hour";
"report_timeframe_ten_minutes" = "Ten minutes";
"radius_any_distance" = "Any distance";
"timer_message2_other" = "%lu km from your location";
"official_distance" = "%lu km from your location";
"configuration_countries_united_states" = "United States";
"configuration_countries_italy" = "Italy";
"configuration_countries_spain" = "Spain";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "France";
"configuration_countries_croatia" = "Croatia";
"configuration_countries_other" = "Other";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "You are buying the PRO version, advertisement will be removed";
"network_pro_privacy_disclaimer" = "Privacy disclaimer";
"network_pro_terms_conditions" = "Terms and conditions";
"network_pro_paying" = "You are paying:";
"inapp_detail_description" = "• Your payment will be charged to your iTunes account upon confirmation of purchase\n• The subscription is automatically renewed unless the automatic renewal is deactivated at least 24 hours before the end of the current period\n• Subscription will be charged for renewal within 24 hours before the end of the current period and the renewal cost identified\n• Subscriptions can be managed by the user and automatic renewal can be deactivated by accessing the user's account settings after the purchase.";
"inapp_lifetime_detail_description" = "• Your payment will be charged to your iTunes account upon confirmation of purchase";
"inapp_purchase" = "SUBSCRIBE TO SERVICE";
@@ -235,20 +214,10 @@
"attention" = "Attention";
"official_no_country_selected" = "You have not selected any country";
"report" = "Report";
"purchase_pro_description" = "The PRO version hasn't any ads and will include extra features. Plus you help to support this research project which does not receive external funds. Thanks for considering! Otherwise, you can have the PRO version for FREE by subscribing to the annual priority service.";
"purchase_pro_discount" = "This is an offer just for you. If you convert the app to PRO within the next 48 hours, you have a 20%% discount. You will have only this chance. After, the PRO version will cost the full price. You still have %lu hours :-)";
"purchase_pro_restore" = "Restore";
"purchase_pro_restore_alert_title" = "Restore completed";
"purchase_pro_restore_alert_message" = "You have restored the product you purchased";
"purchase_pro_no_subscriptions_alert_message" = "No purchase was found to restore. Make sure you are logged into the account the purchase was made with.";
"calendar_missing_permission" = "The calendar cannot be opened, make sure you have set the correct permissions.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "A user has subscribed to the service only %@!";
"minutes_one" = "%lu minute ago";
"minutes_other" = "%lu minutes ago";
"hours_one" = "%lu hour ago";
"hours_other" = "%lu hours ago";
"days_one" = "%lu day ago";
"days_other" = "%lu days ago";
"error_server_registration" = "It was not possible to register with the Earthquake Network server. Registration is required to receive real-time alerts and earthquake notifications.";
"retry" = "Retry";
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>Now</string>
<key>one</key>
<string>A minute ago</string>
<key>other</key>
<string>%u min. ago</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>An hour ago</string>
<key>other</key>
<string>%d hours ago</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>A day ago</string>
<key>other</key>
<string>%d days ago</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>A user has subscribed to the service only %d minute ago!</string>
<key>other</key>
<string>A user has subscribed to the service only %d minutes ago!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>A user has subscribed to the service only %d hour ago!</string>
<key>other</key>
<string>A user has subscribed to the service only %d hours ago!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>A user has subscribed to the service %d day ago.</string>
<key>other</key>
<string>A user has subscribed to the service %d days ago.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Seismic wave in %d second</string>
<key>other</key>
<string>Seismic wave in %d seconds</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Se requiere acceso a la biblioteca para guardar las imágenes generadas por la aplicación";
"NSCalendarsUsageDescription" = "Se requiere acceso al calendario para guardar la información de los terremotos de interés";
"NSContactsUsageDescription" = "Se requiere acceso a los contactos para agregar personas a los eventos creados";
"NSUserTrackingUsageDescription" = "El seguimiento se utiliza para comprender si la publicidad de la aplicación es efectiva";
"CFBundleDisplayName" = "Sismos Detector";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Fuerte sismo reportado por un usuario en %@";
"Sisma molto forte segnalato da utente a" = "Sismo muy fuerte reportado por un usuario en %@";
"Sisma rilevato a" = "Sismo detectado en %@";
"alert_intensity_no_shaking" = "No se siente en tu ubicación";
"alert_intensity_mild" = "Espera movimiento leve o nulo";
"alert_intensity_moderate" = "Espera movimiento moderado";
"alert_intensity_strong" = "Espera movimiento fuerte";
// aligned with Android
"drawer_main_settings" = "Configuración";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: %lu suscripciones aún disponibles para recibir la alerta en menos de 1 segundo a partir de la detección del sismo";
"inapp_available_100k" = "Top 100K: %lu suscripciones aún disponibles para recibir la alerta en menos de 5 segundos a partir de la detección del sismo";
"filter_magnitude" = "Magnitud mínima";
"filter_distance" = "Distancia máxima";
"filter_timeframe" = "Periodo de tiempo";
"filter_strong" = "Muestra sismos fuertes a cualquier distancia si de";
"filter_near" = "Muestra sismos de cualquier magnitud si están a menos de 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ en un radio de 100km";
"official_smartphones" = "Sismo detectado en tiempo real por %@ smartphones. Alerta emitida.";
"official_reports" = "Reportado por %@ usuarios";
"weather_weather" = "El tiempo en el momento del sismo";
"weather_temperature" = "Temperatura: %.02f";
"weather_pressure" = "Presión: %@";
"weather_windspeed" = "Velocidad viento: %@";
"weather_humidity" = "Humedad: %@";
"weather_clouds" = "Cobertura nubes: %@";
"weather_nodata" = "Los datos del tiempo no están disponible para este sismo";
"official_prelimiary" = "PRELIMINAR";
"calendar_description_nogeo_km" = "Sismo M%@, profundidad %@ km.";
"filter_empty" = "Según los filtros y las redes sísmicas habilitadas, no hay sismos en las últimas 24 horas. Para cambiar los filtros, haga clic en la barra en la parte inferior. Para habilitar otras redes sísmicas, haga clic en el icono en forma de mundo en la parte superior.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Confirmar país";
"share_hashtag" = "#sismo";
"share_notified" = "Reportado a través de la app Sismo Detector. Descarga la app desde https://sismo.app/download/ para recibir alertas de #sismo en tiempo real @SismoDetector";
"share_felt" = "Ocurrido en";
"manual_sure" = "¿Estas seguro de querer reportar un sismo?";
"manual_yes" = "Sí";
"filter_filter" = "Filtros";
"manual_sendmessage" = "Enviar un mensaje que los demás usuarios puedan leer sobre el sismo que has notificado";
"manual_message_received" = "Mensaje recibido";
"liveview_unknown_location" = "Tu posición es desconocida. Habilitar la ubicación del smartphone desde la página de configuración del smartphone";
"map_number" = "Sismo detectado por %@ smartphones";
"permission_location_no" = "Ha elegido evitar que la aplicación lea la ubicación de tu dispositivo. NO recibirá notificaciones y alertas en tiempo real";
"permission_location_no_background" = "Ha elegido evitar que la aplicación lea la ubicación de tu dispositivo cuando la aplicación está en segundo plano. Por lo tanto, NO se garantiza la recepción de notificaciones y alertas en tiempo real";
"alert_wave" = "Onda sísmica en %lu segundos";
"share_yourtime" = "(Tu horario)";
"official_close" = "Cierra";
"main_share" = "Comparte";
"widget_mild" = "Leve";
"widget_strong" = "Fuerte";
"widget_verystring" = "Muy fuerte";
"main_simulator" = "Simulador";
"globe_simulation_button" = "Calcular el tiempo de alerta";
"globe_simulation" = "Si el epicentro del sismo está fuera del disco rojo y los smartphones lo detectan de inmediato, recibirá la alerta con más de 5 segundos de anticipación. Seleccionas en el mapa el posible epicentro para calcular el tiempo de alerta.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. %.0f personas serán alertadas antes que tú. Para aumentar el tiempo de advertencia, puede suscribirse al servicio de prioridad %@";
"globe_simulation_message6" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. ¡Serás la primera persona en ser alertada!";
"globe_simulation_priority" = "Servicio prioritario";
"options_cancel" = "Clara";
"status_cancel" = "Clara";
"options_near_alert" = "Notifica sismos de cualquier magnitud si la distancia es inferior a 50 km";
"options_alarms" = "Alerta en tiempo real";
"options_notification_enable_alarm" = "Suena una alarma cuando se detecta un sismo en tiempo real por la red de los teléfonos inteligentes";
"options_notification_eqn_intensity" = "Intensidad del sismo";
"eqn_intensity_any" = "Cualquier intensidad";
"eqn_intensity_strong" = "Solamente sismos fuertes";
"options_radius_mild" = "Radio sismos leves";
"options_radius_strong" = "Radio sismos fuertes";
"options_notification_official" = "Notificaciones redes sísmicas";
"options_notification_enable_official" = "Recibe las notificaciones de los sismos detectados por las redes sísmicas oficiales nacionales e internacionales";
"options_agencies" = "Redes sísmicas";
@@ -108,12 +94,7 @@
"main_map" = "reportes en las últimas 24h";
"official_button_map" = "Mapa";
"main_feel" = "¡Siento un sismo!";
"manual_usebutton" = "Presionas el botón apropiado para informar de un sismo";
"manual_mild" = "LEVE (Solo percibido)";
"manual_strong" = "FUERTE (Caída de objetos)";
"manual_verystrong" = "MUY FUERTE (Colapso de edificios)";
"network_pro" = "Versión PRO";
"network_topro" = "Convierte tu app a la versión PRO! Descubres cómo.";
"network_pro_convert" = "Comienza la conversión";
"inapp_active" = "Suscripción activa";
"inapp_nosub" = "Ninguna suscripción activa";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Coordenadas";
"official_card_population" = "Población";
"main_share_text" = "Hola! Te sugiero la app del proyecto Sismo Detector con alertas en tiempo real. Descárguela de https://sismo.app/download/ #sismo @SismoDetector";
"manual_sendmessage_button" = "Enviar el mensaje";
"mercalli_II" = "II - Apenas percibido";
"mercalli_III" = "III - Vibraciones similares a un camión que pasa";
"mercalli_IV" = "IV - Vibraciones de ventanas, ligeras oscilaciones de objetos colgantes";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Una hora";
"report_timeframe_ten_minutes" = "Diez minutos";
"radius_any_distance" = "Cualquier distancia";
"timer_message2_other" = "%lu km de tu ubicación";
"official_distance" = "%lu km de tu ubicación";
"configuration_countries_united_states" = "Estados Unidos";
"configuration_countries_italy" = "Italia";
"configuration_countries_spain" = "España";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Francia";
"configuration_countries_croatia" = "Croacia";
"configuration_countries_other" = "Otro";
"youtube_video" = "https://www.youtube.com/watch?v=etsF7arwVdg";
// ios only
"network_pro_subtitle" = "Estás comprando la versión PRO, se eliminará la publicidad";
"network_pro_privacy_disclaimer" = "Descargo de responsabilidad de privacidad";
"network_pro_terms_conditions" = "Términos y condiciones";
"network_pro_paying" = "Estas pagando:";
"inapp_detail_description" = "• Su pago se cargará a su cuenta de iTunes tras la confirmación de la compra\n• La suscripción se renueva automáticamente a menos que la renovación automática se desactive al menos 24 horas antes del final del período actual\n• La suscripción se cobrará por la renovación dentro de las 24 horas antes del final del período actual y el costo de renovación identificado\n• Las suscripciones pueden ser administradas por el usuario y la renovación automática se puede desactivar accediendo a la configuración de la cuenta del usuario después de la compra.";
"inapp_lifetime_detail_description" = "• Su pago se cargará a su cuenta de iTunes tras la confirmación de la compra";
"inapp_purchase" = "SUSCRÍBETE AL SERVICIO";
@@ -235,20 +214,10 @@
"attention" = "Atención";
"official_no_country_selected" = "No has seleccionado ningún país";
"report" = "Informe";
"purchase_pro_description" = "La versión PRO no tiene anuncios e incluirá funciones adicionales. Además, ayudas a apoyar este proyecto de investigación que no recibe fondos externos. ¡Gracias por considerarlo! De lo contrario, puede tener la versión PRO GRATIS suscribiéndose al servicio de prioridad anual.";
"purchase_pro_discount" = "Esta es una oferta solo para ti. Si convierte la aplicación a PRO dentro de las próximas 48 horas, tiene un 20%% de descuento. Solo tendrás esta oportunidad. Después, la versión PRO costará el precio completo. Aún tienes %lu horas :-)";
"purchase_pro_restore" = "Restaurar";
"purchase_pro_restore_alert_title" = "Restauración completada";
"purchase_pro_restore_alert_message" = "Has restaurado el producto que compraste.";
"purchase_pro_no_subscriptions_alert_message" = "No se encontró ninguna compra para restaurar. Asegúrese de haber iniciado sesión en la cuenta con la que se realizó la compra.";
"calendar_missing_permission" = "El calendario no se puede abrir, asegúrese de haber configurado los permisos correctos.";
"youtube_video" = "https://www.youtube.com/watch?v=etsF7arwVdg";
"inapp_adv_time" = "Un usuario se ha suscrito al servicio hace solo %@!";
"minutes_one" = "%lu minuto";
"minutes_other" = "%lu minutos";
"hours_one" = "%lu hora";
"hours_other" = "%lu horas";
"days_one" = "%lu día";
"days_other" = "%lu días";
"error_server_registration" = "No fue posible registrarse en el servidor de Sismo Detector. Es necesario registrarse para recibir alertas y notificaciones de terremotos en tiempo real.";
"retry" = "Reintentar";
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Hace un minuto</string>
<key>other</key>
<string>Hace %d min.</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Hace una hora</string>
<key>other</key>
<string>Hace %d horas</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Hace un día</string>
<key>other</key>
<string>Hace %d días</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un usuario se registró en el servicio hace solo %d minuto!</string>
<key>other</key>
<string>Un usuario se registró en el servicio hace solo %d minutos!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un usuario se registró en el servicio hace solo %d hora!</string>
<key>other</key>
<string>Un utente ha sottoscritto il servizio soltanto %d horas!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un usuario se registró en el servicio hace %d día.</string>
<key>other</key>
<string>Un usuario se registró en el servicio hace %d días.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Onda sísmica en %d segundo</string>
<key>other</key>
<string>Onda sísmica en %d segundos</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "L'accès à la bibliothèque est nécessaire pour enregistrer les images générées par l'application";
"NSCalendarsUsageDescription" = "L'accès au calendrier est nécessaire afin de sauvegarder les informations des tremblements de terre d'intérêt";
"NSContactsUsageDescription" = "L'accès aux contacts est requis pour ajouter des personnes aux événements créés";
"NSUserTrackingUsageDescription" = "Le suivi est utilisé pour comprendre si la publicité de l'application est efficace";
"CFBundleDisplayName" = "Détecteur de Séisme";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Fort séisme signalé par un utilisateur à %@";
"Sisma molto forte segnalato da utente a" = "Très fort séisme signalé par un utilisateur à %@";
"Sisma rilevato a" = "Séisme détecté à %@";
"alert_intensity_no_shaking" = "Pas ressenti à votre emplacement";
"alert_intensity_mild" = "Attendez-vous à des secousses légères ou nulles";
"alert_intensity_moderate" = "Attendez-vous à des secousses modérées";
"alert_intensity_strong" = "Attendez-vous à de fortes secousses";
// aligned with Android
"drawer_main_settings" = "Paramètres";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K : %lu abonnements encore disponibles pour être alerté en moins de 1 seconde à partir de la détection du séisme";
"inapp_available_100k" = "Top 100K : %lu abonnements encore disponibles pour être alerté en moins de 5 secondes à partir de la détection du séisme";
"filter_magnitude" = "Magnitude minimale";
"filter_distance" = "Distance maximale";
"filter_timeframe" = "Plage de temps";
"filter_strong" = "Affichez de forts séismes à n'importe quelle distance si la magnitude est de";
"filter_near" = "Afficher les séismes de toute magnitude s'ils sont à moins de 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ dans un rayon de 100km";
"official_smartphones" = "Tremblement de terre détecté en temps réel par %@ smartphones. Alerte émise.";
"official_reports" = "Signalé par %@ utilisateurs";
"weather_weather" = "Météo au moment du séisme";
"weather_temperature" = "Température : %.02f";
"weather_pressure" = "Pression : %@";
"weather_windspeed" = "Vitesse du vent : %@";
"weather_humidity" = "Humidité : %@";
"weather_clouds" = "Couverture nuageuse : %@";
"weather_nodata" = "Aucune donnée météorologique n'est disponible pour ce séisme";
"official_prelimiary" = "PRÉLIMINAIRE";
"calendar_description_nogeo_km" = "Séisme M%@, profondeur %@ km.";
"filter_empty" = "Sur la base des filtres et des réseaux sismiques activés, il n'y a pas de séismes au cours des 24 dernières heures. Pour changer les filtres, cliquez sur la barre en bas. Pour activer d'autres réseaux sismiques, cliquez sur l'icône en forme de monde en haut.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Confirmez le pays";
"share_hashtag" = "#séisme";
"share_notified" = "Signalé via l'app Détecteur de Séisme. Téléchargez l'app depuis https://sismo.app/download/ pour recevoir des alertes de #séisme en temps réel @SismoDetector";
"share_felt" = "Perçu à";
"manual_sure" = "Voulez-vous vraiment signaler un séisme ?";
"manual_yes" = "Oui";
"filter_filter" = "Filtres";
"manual_sendmessage" = "Envoyez un message que les autres utilisateurs peuvent lire sur le séisme que vous avez signalé";
"manual_message_received" = "Message bien reçu";
"liveview_unknown_location" = "Votre position est inconnue. Activez la localisation à partir de la page de configuration de votre appareil";
"map_number" = "Séisme détecté par %@ smartphones";
"permission_location_no" = "Vous avez choisi d'empêcher l'app de lire la position de votre appareil. Vous ne recevrez PAS de notifications et d'alertes en temps réel";
"permission_location_no_background" = "Vous avez choisi d'empêcher l'app de lire la position de votre appareil lorsque l'app est en arrière-plan. La réception de notifications et d'alertes en temps réel n'est donc PAS garantie";
"alert_wave" = "Onde sismique en %lu secondes";
"share_yourtime" = "(Votre heure)";
"official_close" = "Fermer";
"main_share" = "Partager";
"widget_mild" = "Léger";
"widget_strong" = "Fort";
"widget_verystring" = "Très fort";
"main_simulator" = "Simulateur";
"globe_simulation_button" = "Calculez le temps de pré-alerte.";
"globe_simulation" = "Si l'épicentre du séisme est en dehors du cercle rouge et que le séisme est immédiatement détecté par les smartphones, vous recevrez l'alerte plus de 5 secondes à l'avance. Sélectionnez sur la carte l'épicentre possible afin de calculer le temps de pré-alerte.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Avec cet épicentre, grâce au service prioritaire %@, vous devriez recevoir l'alerte %.0f secondes à l'avance. %.0f personnes seront alertées avant vous. Pour augmenter le temps de pré-alerte, vous pouvez vous inscrire au service prioritaire %@";
"globe_simulation_message6" = "Avec cet épicentre, grâce au service prioritaire %@, vous devriez recevoir l'alerte %.0f secondes à l'avance. Vous serez le premier à être alerté!";
"globe_simulation_priority" = "Service prioritaire";
"options_cancel" = "Supprimer";
"status_cancel" = "Supprimer";
"options_near_alert" = "Notifiez les séismes de toute magnitude si la distance est inférieure à 50 km";
"options_alarms" = "Alerte en temps réel";
"options_notification_enable_alarm" = "Une alarme retentit lorsqu'un séisme est détecté par le réseau des smartphones";
"options_notification_eqn_intensity" = "Intensité du séisme";
"eqn_intensity_any" = "Toute intensité";
"eqn_intensity_strong" = "Séismes forts uniquement ";
"options_radius_mild" = "Rayon des séismes légers";
"options_radius_strong" = "Rayon des séismes forts";
"options_notification_official" = "Notifications de réseaux sismiquex";
"options_notification_enable_official" = "Recevez les notifications des séismes détectés par les réseaux sismiques nationaux et internationaux";
"options_agencies" = "Réseaux sismiques";
@@ -108,12 +94,7 @@
"main_map" = "rapports dans les dernières 24h";
"official_button_map" = "Carte";
"main_feel" = "J'ai ressenti un tremblement de terre !";
"manual_usebutton" = "Appuyez sur le bouton droit ci-dessous pour signaler un séisme";
"manual_mild" = "LÉGER\n(seulement perçu)";
"manual_strong" = "FORT\n(chute d'objets)";
"manual_verystrong" = "TRÈS FORT\n(Effondrement de bâtiments)";
"network_pro" = "Version PRO";
"network_topro" = "Convertissez votre app en version PRO ! Découvrez comment.";
"network_pro_convert" = "Lancer la conversion";
"inapp_active" = "Service actif";
"inapp_nosub" = "Aucun abonnement actif";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Coordonnées";
"official_card_population" = "Population";
"main_share_text" = "Bonjour ! Je vous conseille l'app du projet Earthquake Network avec des alertes en temps réel. La télécharger à partir de https://sismo.app/download/ #séisme @SismoDetector";
"manual_sendmessage_button" = "Envoyez le message";
"mercalli_II" = "II - A peine perçu";
"mercalli_III" = "III - Vibrations similaires au passage d'un camion";
"mercalli_IV" = "IV - Vibrations des vitres, légères oscillations des objets suspendus";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Une heure";
"report_timeframe_ten_minutes" = "Dix minutes";
"radius_any_distance" = "Toute distance";
"timer_message2_other" = "%lu km de votre position";
"official_distance" = "%lu km de votre position";
"configuration_countries_united_states" = "États Unis";
"configuration_countries_italy" = "Italie";
"configuration_countries_spain" = "Espagne";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "France";
"configuration_countries_croatia" = "Croatie";
"configuration_countries_other" = "Autre";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "Vous achetez la version PRO, la publicité sera supprimée";
"network_pro_privacy_disclaimer" = "Avertissement de confidentialité";
"network_pro_terms_conditions" = "Termes et conditions";
"network_pro_paying" = "Vous payez:";
"inapp_detail_description" = "• Votre paiement sera débité de votre compte iTunes lors de la confirmation de l'achat\n• L'abonnement est automatiquement renouvelé sauf si le renouvellement automatique est désactivé au moins 24 heures avant la fin de la période en cours\n• L'abonnement sera facturé pour le renouvellement dans les 24 heures avant la fin de la période en cours et le coût de renouvellement identifié\n• Les abonnements peuvent être gérés par l'utilisateur et le renouvellement automatique peut être désactivé en accédant aux paramètres du compte de l'utilisateur après l'achat.";
"inapp_lifetime_detail_description" = "• Votre paiement sera débité de votre compte iTunes lors de la confirmation de l'achat";
"inapp_purchase" = "ABONNEZ-VOUS AU SERVICE";
@@ -235,20 +214,10 @@
"attention" = "Attention";
"official_no_country_selected" = "Vous n'avez sélectionné aucun pays";
"report" = "Signaler";
"purchase_pro_description" = "La version PRO n'a pas de publicité et comprendra des fonctionnalités supplémentaires. De plus, vous contribuez à soutenir ce projet de recherche qui ne reçoit pas de fonds externes. Merci d'avoir envisagé! Sinon, vous pouvez avoir la version PRO GRATUITEMENT en vous abonnant au service prioritaire annuel.";
"purchase_pro_discount" = "Ceci est une offre juste pour vous. Si vous convertissez l'application en PRO dans les 48 prochaines heures, vous bénéficiez d'une réduction de 20%%. Vous n'aurez que cette chance. Après, la version PRO coûtera le prix total. Vous avez encore %lu heures :-)";
"purchase_pro_restore" = "Restaurer";
"purchase_pro_restore_alert_title" = "Restauration terminée";
"purchase_pro_restore_alert_message" = "Vous avez restauré le produit que vous avez acheté";
"purchase_pro_no_subscriptions_alert_message" = "Aucun achat à restaurer n'a été trouvé. Assurez-vous que vous êtes connecté au compte avec lequel l'achat a été effectué.";
"calendar_missing_permission" = "Le calendrier ne peut pas être ouvert, assurez-vous d'avoir défini les autorisations appropriées.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "Un utilisateur s'est abonné au service il y a seulement %@!";
"minutes_one" = "%lu minute";
"minutes_other" = "%lu minutes";
"hours_one" = "%lu heure";
"hours_other" = "%lu heures";
"days_one" = "%lu jour";
"days_other" = "%lu jours";
"error_server_registration" = "Il n'a pas été possible de s'inscrire auprès du serveur. L'inscription est requise pour recevoir des alertes en temps réel et des notifications de tremblement de terre.";
"retry" = "Réessayez";
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Il y a %d minute</string>
<key>many</key>
<string>Il y a %d min</string>
<key>other</key>
<string>Il y a %d min</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Il y a %d heure</string>
<key>many</key>
<string>Il y a %d heures</string>
<key>other</key>
<string>Il y a %d heures</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Il y a %d jour</string>
<key>many</key>
<string>Il y a %d jours</string>
<key>other</key>
<string>Il y a %d jours</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d minute!</string>
<key>many</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d minutes!</string>
<key>other</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d minutes!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d heure!</string>
<key>many</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d heures!</string>
<key>other</key>
<string>Un utilisateur s'est inscrit au service il y a seulement %d heures!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utilisateur s'est inscrit au service il y a %d jour.</string>
<key>many</key>
<string>Un utilisateur s'est inscrit au service il y a %d jours.</string>
<key>other</key>
<string>Un utilisateur s'est inscrit au service il y a %d jours.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Onde sismique en %d seconde</string>
<key>many</key>
<string>Onde sismique en %d secondes</string>
<key>other</key>
<string>Onde sismique en %d secondes</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Pristup knjižnici potreban je kako biste spremili slike generirane u aplikaciji";
"NSCalendarsUsageDescription" = "Pristup kalendaru potreban je kako bi se sačuvale informacije o potresima od interesa";
"NSContactsUsageDescription" = "Pristup kontaktima potreban je kako biste dodali ljude u stvorene događaje";
"NSUserTrackingUsageDescription" = "Praćenje se koristi kako bi se shvatilo je li oglašavanje aplikacije učinkovito";
"CFBundleDisplayName" = "Detektor Potresa";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Snažan potres prijavio korisnik u %@";
"Sisma molto forte segnalato da utente a" = "Vrlo jak potres prijavio korisnik u %@";
"Sisma rilevato a" = "Potres otkriven u %@";
"alert_intensity_no_shaking" = "Ne osjeća se na vašoj lokaciji";
"alert_intensity_mild" = "Očekujte blago podrhtavanje ili ga nema";
"alert_intensity_moderate" = "Očekujte umjereno podrhtavanje";
"alert_intensity_strong" = "Očekujte snažno podrhtavanje";
// aligned with Android
"drawer_main_settings" = "Postavke";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: Dostupan je sljedeći broj pretplata za primanje upozorenja za manje od 1 sekunde od otkrivanja potresa: %lu";
"inapp_available_100k" = "Top 100K: Dostupan je sljedeći broj pretplata za primanje upozorenja za manje od 1 sekunde od otkrivanja potresa: %lu";
"filter_magnitude" = "Minimalna jačina";
"filter_distance" = "Maksimalna udaljenost";
"filter_timeframe" = "Razdoblje";
"filter_strong" = "Prikaži jake potrese na bilo kojoj udaljenosti ako su jačine";
"filter_near" = "Prikaži potrese bilo koje jačine ako su bliže od 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ u radijusu od 100km";
"official_smartphones" = "Potres je u stvarnom vremenu otkrio sljedeći broj pametnih telefona: %@. Poslano je upozorenje.";
"official_reports" = "Broj korisnika koji su poslali prijavu: %@";
"weather_weather" = "Vremenski uvjeti u vrijeme potresa";
"weather_temperature" = "Temperatura: %.02f";
"weather_pressure" = "Tlak: %@";
"weather_windspeed" = "Brzina vjetra: %@";
"weather_humidity" = "Vlažnost: %@";
"weather_clouds" = "Pokrivenost oblacima: %@";
"weather_nodata" = "Nisu dostupni podaci o vremenskim uvjetima za ovaj potres";
"official_prelimiary" = "PRELIMINARNO";
"calendar_description_nogeo_km" = "Potres M%@, dubine %@ km.";
"filter_empty" = "Na temelju omogućenih filtra i seizmoloških mreža nema potresa u posljednja 24 h. Za promjenu filtra kliknite na ljubičastu traku pri dnu. Za omogućivanje drugih seizmoloških mreža kliknite na ikonu zemaljske kugle pri vrhu.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Potvrdi zemlju";
"share_hashtag" = "#potres";
"share_notified" = "Prijavljen putem aplikacije Detektor Potresa. Preuzmite aplikaciju na https://sismo.app/download/ da biste u stvarnom vremenu primali upozorenja kada se dogodi #potres @DetektorPotresa";
"share_felt" = "Lokacija na kojoj se osjetio:";
"manual_sure" = "Želite li zaista poslati obavijest o potresu?";
"manual_yes" = "Da";
"filter_filter" = "Filteri";
"manual_sendmessage" = "Pošaljite poruku o potresu koji ste prijavili koju drugi korisnici mogu pročitati";
"manual_message_received" = "Poruka je primljena";
"liveview_unknown_location" = "Vaš položaj nije poznat. Omogući lokaciju u konfiguraciji pametnog telefona";
"map_number" = "Potres je otkrio sljedeći broj pametnih telefona: %@";
"permission_location_no" = "Odlučili ste onemogućiti aplikaciji očitavanje lokacije uređaja. NEĆETE primati obavijesti i upozorenja u stvarnom vremenu";
"permission_location_no_background" = "Odlučili ste onemogućiti aplikaciji očitavanje lokacije vašeg uređaja kada radi u pozadini. Možda NEĆETE primiti obavijesti i upozorenja u stvarnom vremenu";
"alert_wave" = "Seizmički val za %lu sekundi";
"share_yourtime" = "(Vaše vrijeme)";
"official_close" = "Zatvori";
"main_share" = "Podijeli";
"widget_mild" = "Blag";
"widget_strong" = "Jak";
"widget_verystring" = "Vrlo jak";
"main_simulator" = "Simulator";
"globe_simulation_button" = "Izračunaj vrijeme primanja upozorenja";
"globe_simulation" = "Ako je epicentar potresa izvan crvenog kruga i pametni telefoni odmah prepoznaju potres, primit ćete upozorenje više od 5 sekundi unaprijed. Odaberite na karti mogući epicentar kako biste izračunali vrijeme primanja upozorenja.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Uz ovaj epicentar, zahvaljujući prioritetnoj usluzi %@, trebali biste primiti upozorenje %.0fsekundi unaprijed. Sljedeći broj osoba bit će upozoren prije vas: %.0f. Za brže vrijeme primanja upozorenja možete se pretplatiti na prioritetnu uslugu %@";
"globe_simulation_message6" = "Uz ovaj epicentar, zahvaljujući prioritetnoj usluzi %@, trebali biste primiti upozorenje %.0f sekundi unaprijed. Vi ćete biti prvi upozoreni!";
"globe_simulation_priority" = "Prioritetna usluga";
"options_cancel" = "Poništi";
"status_cancel" = "Poništi";
"options_near_alert" = "Obavijesti o potresima bilo koje jačine ako je udaljenost manja od 50 km";
"options_alarms" = "Upozorenje u stvarnom vremenu";
"options_notification_enable_alarm" = "Aktiviraj alarm kada mreža pametnih telefona u stvarnom vremenu otkrije potres";
"options_notification_eqn_intensity" = "Intenzitet potresa";
"eqn_intensity_any" = "Bilo koji intenzitet";
"eqn_intensity_strong" = "Samo jaki potresi";
"options_radius_mild" = "Radijus blagog potresa";
"options_radius_strong" = "Radijus jakog potresa";
"options_notification_official" = "Obavijesti o seizmološkim mrežama";
"options_notification_enable_official" = "Primajte obavijesti o potresima koje su otkrile nacionalne i međunarodne seizmološke mreže";
"options_agencies" = "Seizmološke mreže";
@@ -108,12 +94,7 @@
"main_map" = "izvješća u posljednja 24h";
"official_button_map" = "Karta";
"main_feel" = "Osjetio/la sam potres!";
"manual_usebutton" = "Pritisni odgovarajući gumb u nastavku za prijavu potresa";
"manual_mild" = "BLAGI\n(Samo osjetan)";
"manual_strong" = "JAK\n(Padanje predmeta)";
"manual_verystrong" = "VRLO JAK\n(Rušenje zgrada)";
"network_pro" = "Napredna verzija";
"network_topro" = "Prijeđite na naprednu verziju aplikacije! Saznajte kako to učiniti.";
"network_pro_convert" = "Pokreni prijelaz";
"inapp_active" = "Pretplata je aktivna";
"inapp_nosub" = "Nema nijedan aktivni pretplatnik";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Koordinate";
"official_card_population" = "Stanovništvo";
"main_share_text" = "Pozdrav! Preporučam vam aplikaciju projekta Earthquake Network s upozorenjima u stvarnom vremenu. Preuzmite na https://sismo.app/download/ #potres @DetektorPotresa";
"manual_sendmessage_button" = "Pošalji poruku";
"mercalli_II" = "II - Jedva percipiran";
"mercalli_III" = "III - Vibracije slične onima kod kamiona u prolazu";
"mercalli_IV" = "IV - Vibracije prozora, lagane oscilacije visećih predmeta";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "1 sat";
"report_timeframe_ten_minutes" = "10 minuta";
"radius_any_distance" = "Bilo udaljenost";
"timer_message2_other" = "%lu km od vašeg mjesta";
"official_distance" = "%lu km od vašeg mjesta";
"configuration_countries_united_states" = "Ujedinjene države";
"configuration_countries_italy" = "Italija";
"configuration_countries_spain" = "Španjolska";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Francuska";
"configuration_countries_croatia" = "Hrvatska";
"configuration_countries_other" = "Drugo";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "Kupujete PRO verziju, oglas će biti uklonjen";
"network_pro_privacy_disclaimer" = "Izjava o privatnosti";
"network_pro_terms_conditions" = "Uvjeti i odredbe";
"network_pro_paying" = "Plaćate:";
"inapp_detail_description" = "• Vaša će uplata biti naplaćena na vaš iTunes račun nakon potvrde kupnje\n• Pretplata se automatski obnavlja, osim ako se automatska obnova ne deaktivira najmanje 24 sata prije kraja tekućeg razdoblja\n • Pretplata će se naplatiti za obnovu u roku od 24 sati prije kraja tekućeg razdoblja i utvrđenih troškova obnove\n • Korisnikom može upravljati pretplatama, a automatskim obnavljanjem može se deaktivirati pristupom postavkama korisničkog računa nakon kupnje.";
"inapp_lifetime_detail_description" = "• Vaša će uplata biti naplaćena na vaš iTunes račun nakon potvrde kupnje";
"inapp_purchase" = "PRETPLATITE SE NA SERVIS";
@@ -235,20 +214,10 @@
"attention" = "Pažnja";
"official_no_country_selected" = "Niste odabrali nijednu zemlju";
"report" = "Izvješće";
"purchase_pro_description" = "PRO verzija nema oglase i sadržavat će dodatne značajke. Uz to, pomažete u podršci ovom istraživačkom projektu koji ne prima vanjska sredstva. Hvala na razmatranju! Inače, PRO verziju možete dobiti BESPLATNO pretplatom na uslugu godišnjeg prioriteta.";
"purchase_pro_discount" = "Ovo je ponuda samo za vas. Ako pretvorite aplikaciju u PRO u sljedećih 48 sati, imat ćete popust od 20%%. Imat ćete samo ovu priliku. Nakon toga, PRO verzija koštat će punu cijenu. Imate još %lu sati :-)";
"purchase_pro_restore" = "Vratiti";
"purchase_pro_restore_alert_title" = "Vraćanje dovršeno";
"purchase_pro_restore_alert_message" = "Obnovili ste proizvod koji ste kupili";
"purchase_pro_no_subscriptions_alert_message" = "Nije pronađena nijedna kupnja za vraćanje. Obavezno se prijavite na račun s kojim je obavljena kupnja.";
"calendar_missing_permission" = "Kalendar se ne može otvoriti, provjerite jeste li postavili ispravna dopuštenja.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "Korisnik se pretplatio na uslugu prije samo %@!";
"minutes_one" = "%lu minutu";
"minutes_other" = "%lu minute";
"hours_one" = "%lu sat";
"hours_other" = "%lu sati";
"days_one" = "%lu dan";
"days_other" = "%lu dana";
"error_server_registration" = "Nije bilo moguće registrirati se na poslužitelju mreže potresnih mreža. Registracija je potrebna za primanje upozorenja u stvarnom vremenu i obavijesti o potresima.";
"retry" = "Pokušaj ponovo";
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Prije %d min</string>
<key>few</key>
<string>Prije %d min</string>
<key>other</key>
<string>Prije %d min</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Prije %d h</string>
<key>few</key>
<string>Prije %d h</string>
<key>other</key>
<string>Prije %d h</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Prije %d dan(a)</string>
<key>few</key>
<string>Prije %d dan(a)</string>
<key>other</key>
<string>Prije %d dan(a)</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Korisnik se pretplatio na uslugu prije samo %d minutu!</string>
<key>few</key>
<string>Korisnik se pretplatio na uslugu prije samo %d minute!</string>
<key>other</key>
<string>Korisnik se pretplatio na uslugu prije samo %d minute!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Korisnik se pretplatio na uslugu prije samo %d h!</string>
<key>few</key>
<string>Korisnik se pretplatio na uslugu prije samo %d h!</string>
<key>other</key>
<string>Korisnik se pretplatio na uslugu prije samo %d h!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Korisnik se pretplatio na uslugu prije %d dan.</string>
<key>few</key>
<string>Korisnik se pretplatio na uslugu prije %d dana.</string>
<key>other</key>
<string>Korisnik se pretplatio na uslugu prije %d dana.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Seizmički val u %d sekundi</string>
<key>few</key>
<string>Seizmički val u %d sekunde</string>
<key>other</key>
<string>Seizmički val u %d sekundi</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Akses ke perpustakaan diperlukan untuk menyimpan gambar yang dihasilkan oleh aplikasi";
"NSCalendarsUsageDescription" = "Akses ke kalender diperlukan untuk menyimpan informasi gempa yang menarik";
"NSContactsUsageDescription" = "Akses ke kontak diperlukan untuk menambahkan orang ke acara yang dibuat";
"NSUserTrackingUsageDescription" = "Pelacakan digunakan untuk memahami apakah iklan aplikasi efektif";
"CFBundleDisplayName" = "Detektor Gempa";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Gempa kuat dilaporkan oleh pengguna di %@";
"Sisma molto forte segnalato da utente a" = "Gempa sangat kuat dilaporkan oleh pengguna di %@";
"Sisma rilevato a" = "Gempa terdeteksi di %@";
"alert_intensity_no_shaking" = "Tidak terasa di lokasi Anda";
"alert_intensity_mild" = "Harapkan ringan atau tidak ada guncangan";
"alert_intensity_moderate" = "Harapkan guncangan sedang";
"alert_intensity_strong" = "Harapkan goncangan yang kuat";
// aligned with Android
"drawer_main_settings" = "Pengaturan";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: %lu langganan masih tersedia untuk mendapat peringatan dalam waktu kurang dari 1 detik sejak deteksi gempa";
"inapp_available_100k" = "Top 100K: %lu langganan masih tersedia untuk mendapat peringatan dalam waktu kurang dari 5 detik sejak deteksi gempa";
"filter_magnitude" = "Magnitudo minimum";
"filter_distance" = "Jarak maksimum";
"filter_timeframe" = "Jangka waktu";
"filter_strong" = "Tampilkan gempa kuat pada jarak berapa pun jika";
"filter_near" = "Tampilkan gempa dengan kekuatan berapa pun jika lebih dekat dari 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ dalam radius 100km";
"official_smartphones" = "Gempa terdeteksi secara real time oleh %@ smartphone. Peringatan dikeluarkan.";
"official_reports" = "Dilaporkan oleh %@ pengguna";
"weather_weather" = "Cuaca saat gempa";
"weather_temperature" = "Suhu: %.02f ";
"weather_pressure" = "Tekanan: %@ ";
"weather_windspeed" = "Kecepatan angin: %@ ";
"weather_humidity" = "Kelembapan: %@ ";
"weather_clouds" = "Cakupan awan: %@ ";
"weather_nodata" = "Data cuaca tidak tersedia untuk gempa ini";
"official_prelimiary" = "PENDAHULUAN";
"calendar_description_nogeo_km" = "Gempa M %@ SR, kedalaman %@ km.";
"filter_empty" = "Berdasarkan filter dan jaringan seismik yang diaktifkan, tidak ada gempa dalam 24 jam terakhir. Untuk mengubah filter, klik bilah di bawah. Untuk mengaktifkan jaringan seismik lain, klik ikon dunia di bagian atas.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Konfirmasikan negara";
"share_hashtag" = "#gempa";
"share_notified" = "Dilaporkan melalui aplikasi Detektor Gempa. Unduh aplikasi dari https://sismo.app/download/ untuk menerima peringatan real time #gempa @SismoDetector";
"share_felt" = "Terasa di";
"manual_sure" = "Yakin ingin memberitahukan adanya gempa?";
"manual_yes" = "Ya";
"filter_filter" = "Filter";
"manual_sendmessage" = "Kirim pesan yang dapat dibaca pengguna lain tentang gempa yang Anda laporkan";
"manual_message_received" = "Pesan diterima";
"liveview_unknown_location" = "Posisi Anda tidak diketahui. Aktifkan lokasi smartphone dari konfigurasi smartphone";
"map_number" = "Gempa terdeteksi oleh %@ smartphone";
"permission_location_no" = "Anda telah memilih untuk mencegah aplikasi membaca lokasi perangkat. Anda TIDAK akan menerima pemberitahuan dan peringatan secara real time";
"permission_location_no_background" = "Anda telah memilih untuk mencegah aplikasi membaca lokasi perangkat Anda saat aplikasi berjalan di latar belakang. Pemberitahuan dan peringatan real time mungkin TIDAK diterima";
"alert_wave" = "Gelombang gempa dalam %lu detik";
"share_yourtime" = "(Waktu Anda)";
"official_close" = "Tutup";
"main_share" = "Bagikan";
"widget_mild" = "Ringan";
"widget_strong" = "Kuat";
"widget_verystring" = "Sangat kuat";
"main_simulator" = "Simulator";
"globe_simulation_button" = "Hitung waktu peringatan";
"globe_simulation" = "Jika episentrum gempa berada di luar cakram merah dan gempa segera terdeteksi oleh smartphone, Anda akan menerima peringatan lebih dari 5 detik sebelumnya. Pilih kemungkinan episentrum pada peta untuk menghitung waktu peringatan.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Dengan episentrum ini dan layanan prioritas %@, Anda akan menerima peringatan %.0f detik sebelumnya. %.0f orang akan diperingatkan sebelum Anda. Untuk mendapatkan waktu peringatan yang lebih cepat, Anda dapat berlangganan layanan prioritas %@";
"globe_simulation_message6" = "Dengan episentrum ini dan layanan prioritas %@, Anda akan menerima peringatan %.0f detik sebelumnya. Anda akan menjadi orang pertama yang diperingatkan";
"globe_simulation_priority" = "Layanan prioritas";
"options_cancel" = "Batal";
"status_cancel" = "Batal";
"options_near_alert" = "Beri tahukan tentang gempa dengan magnitudo berapa pun jika jaraknya kurang dari 50 km";
"options_alarms" = "Peringatan real time";
"options_notification_enable_alarm" = "Nyalakan alarm saat gempa terdeteksi secara real time oleh jaringan smartphone";
"options_notification_eqn_intensity" = "Intensitas gempa";
"eqn_intensity_any" = "Intensitas apa pun";
"eqn_intensity_strong" = "Hanya gempa kuat";
"options_radius_mild" = "Radius gempa ringan";
"options_radius_strong" = "Radius gempa kuat";
"options_notification_official" = "Pemberitahuan jaringan seismik";
"options_notification_enable_official" = "Terima pemberitahuan untuk gempa yang terdeteksi oleh jaringan seismik nasional dan internasional";
"options_agencies" = "Jaringan seismik";
@@ -108,12 +94,7 @@
"main_map" = "laporan dalam 24 jam terakhir";
"official_button_map" = "Peta";
"main_feel" = "Saya merasakan gempa!";
"manual_usebutton" = "Tekan tombol yang tepat di bawah untuk melaporkan gempa";
"manual_mild" = "RINGAN\n(Terasa)";
"manual_strong" = "KUAT\n(Barang jatuh)";
"manual_verystrong" = "SANGAT KUAT\n(Gedung runtuh)";
"network_pro" = "Versi PRO";
"network_topro" = "Tingkatkan aplikasi Anda menjadi versi PRO! Ketahui caranya.";
"network_pro_convert" = "Mulai tingkatkan";
"inapp_active" = "Langganan aktif";
"inapp_nosub" = "Tidak ada langganan aktif";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Koordinat";
"official_card_population" = "Populasi";
"main_share_text" = "Hai! Saya menyarankan Anda menggunakan aplikasi proyek Earthquake Network untuk mendapatkan peringatan gempa secara real time. Unduh dari https://sismo.app/download/ #gempa @SismoDetector";
"manual_sendmessage_button" = "Kirim pesan";
"mercalli_II" = "II - Hampir tidak dirasakan";
"mercalli_III" = "III - Getaran mirip dengan truk yang lewat";
"mercalli_IV" = "IV - Getaran jendela, sedikit osilasi benda gantung";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Satu jam";
"report_timeframe_ten_minutes" = "Sepuluh menit";
"radius_any_distance" = "Jarak berapa pun";
"timer_message2_other" = "%lu km dari lokasi Anda";
"official_distance" = "%lu km dari lokasi Anda";
"configuration_countries_united_states" = "Amerika Serikat";
"configuration_countries_italy" = "Italia";
"configuration_countries_spain" = "Spanyol";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Perancis";
"configuration_countries_croatia" = "Kroasia";
"configuration_countries_other" = "Lainnya";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "Anda membeli versi PRO, iklan akan dihapus";
"network_pro_privacy_disclaimer" = "Penafian privasi";
"network_pro_terms_conditions" = "Syarat dan ketentuan";
"network_pro_paying" = "Anda membayar:";
"inapp_detail_description" = "• Pembayaran Anda akan dibebankan ke akun iTunes Anda setelah konfirmasi pembelian\n• Langganan diperpanjang secara otomatis kecuali pembaruan otomatis dinonaktifkan setidaknya 24 jam sebelum akhir periode saat ini\n• Langganan akan dikenakan biaya untuk pembaruan dalam waktu 24 jam sebelum akhir periode berjalan dan biaya pembaruan diidentifikasi\n• Langganan dapat dikelola oleh pengguna dan pembaruan otomatis dapat dinonaktifkan dengan mengakses pengaturan akun pengguna setelah pembelian.";
"inapp_lifetime_detail_description" = "• Pembayaran Anda akan dibebankan ke akun iTunes Anda setelah konfirmasi pembelian";
"inapp_purchase" = "BERLANGGANAN LAYANAN";
@@ -235,20 +214,10 @@
"attention" = "Perhatian";
"official_no_country_selected" = "Anda belum memilih negara mana pun";
"report" = "Melaporkan";
"purchase_pro_description" = "Versi PRO tidak memiliki iklan apa pun dan akan menyertakan fitur tambahan. Ditambah Anda membantu mendukung proyek penelitian ini yang tidak menerima dana eksternal. Terima kasih telah mempertimbangkan! Jika tidak, Anda dapat memiliki versi PRO GRATIS dengan berlangganan layanan prioritas tahunan.";
"purchase_pro_discount" = "Ini adalah tawaran khusus untuk Anda. Jika Anda mengonversi aplikasi menjadi PRO dalam 48 jam ke depan, Anda mendapatkan diskon 20%%. Anda hanya akan memiliki kesempatan ini. Setelah itu, versi PRO akan dikenakan harga penuh. Anda masih punya %lu jam :-)";
"purchase_pro_restore" = "Mengembalikan";
"purchase_pro_restore_alert_title" = "Kembalikan selesai";
"purchase_pro_restore_alert_message" = "Anda telah memulihkan produk yang Anda belid";
"purchase_pro_no_subscriptions_alert_message" = "Tidak ada pembelian yang ditemukan untuk dipulihkan. Pastikan Anda masuk ke akun tempat pembelian dilakukan.";
"calendar_missing_permission" = "Kalender tidak dapat dibuka, pastikan Anda telah mengatur izin yang benar.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "Seorang pengguna telah berlangganan layanan hanya %@!";
"minutes_one" = "%lu menit yang lalu";
"minutes_other" = "%lu menit yang lalu";
"hours_one" = "%lu jam yang lalu";
"hours_other" = "%lu jam yang lalu";
"days_one" = "%lu hari yang lalu";
"days_other" = "%lu hari yang lalu";
"error_server_registration" = "Itu tidak mungkin untuk mendaftar dengan server Jaringan Gempa. Pendaftaran diperlukan untuk menerima peringatan waktu nyata dan pemberitahuan gempa bumi.";
"retry" = "Mencoba kembali";
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>%d mnt lalu</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>%d jam lalu</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>%d hari lalu</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>Seorang pengguna telah berlangganan layanan tersebut %d menit lalu!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>Seorang pengguna telah berlangganan layanan tersebut %d jam lalu!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>Seorang pengguna telah berlangganan layanan tersebut %d hari lalu.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>Gelombang seismik dalam %d detik</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "L'accesso alla libreria è richiesto per poter salvare le immagini generate dall'app";
"NSCalendarsUsageDescription" = "L'accesso al calendario è richiesto per poter salvare le informazioni dei sismi di interesse";
"NSContactsUsageDescription" = "L'accesso ai contatti è richiesto per poter aggiungere persone agli eventi creati";
"NSUserTrackingUsageDescription" = "Il tracciamento serve a capire se la pubblicità dell'app è efficace";
"CFBundleDisplayName" = "Rilevatore Terremoto";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "Sisma forte segnalato da un utente a %@";
"Sisma molto forte segnalato da utente a" = "Sisma molto forte segnalato da un utente at %@";
"Sisma rilevato a" = "Sisma rilevato a %@";
"alert_intensity_no_shaking" = "Non percepito dove ti trovi";
"alert_intensity_mild" = "Previsto uno scuotimento leggero o nullo";
"alert_intensity_moderate" = "Previsto uno scuotimento moderato";
"alert_intensity_strong" = "Previsto uno scuotimento forte";
// aligned with Android
"drawer_main_settings" = "Impostazioni";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: %lu sottoscrizioni ancora disponibili per essere allertato in meno di 1 secondo dal rilevamento del sisma";
"inapp_available_100k" = "Top 100K: %lu sottoscrizioni ancora disponibili per essere allertato in meno di 5 secondi dal rilevamento del sisma";
"filter_magnitude" = "Magnitudo minima";
"filter_distance" = "Distanza massima";
"filter_timeframe" = "Periodo temporale";
"filter_strong" = "Mostra sismi forti a qualsiasi distanza se di";
"filter_near" = "Mostra sismi di qualsiasi magnitudo se a meno di 50 km";
@@ -34,13 +39,6 @@
"share_radius100" = "%@ in un raggio di 100km";
"official_smartphones" = "Sisma rilevato in tempo reale da %@ smartphones. Allerta inviata.";
"official_reports" = "Segnalato da %@ utenti";
"weather_weather" = "Meteo al momento del sisma";
"weather_temperature" = "Temperatura: %.02f";
"weather_pressure" = "Pressione: %@";
"weather_windspeed" = "Velocità vento: %@";
"weather_humidity" = "Umidità: %@";
"weather_clouds" = "Copertura nuvolosa: %@";
"weather_nodata" = "I dati meteo non sono disponibili per questo sisma";
"official_prelimiary" = "PRELIMINARE";
"calendar_description_nogeo_km" = "Sisma M%@, profondità %@ km.";
"filter_empty" = "In base ai filtri ed alle reti sismiche abilitate, non ci sono sismi nelle ultime 24 ore. Per modificare i filtri clicca sulla barra in basso. Per abilitare altre reti sismiche clicca sull'icona a forma di mondo in alto.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Conferma nazione";
"share_hashtag" = "#terremoto";
"share_notified" = "Segnalato tramite la app Rilevatore Terremoto. Scarica la app da https://sismo.app/download/ per ricevere allerte #terremoto in tempo reale @SismoDetector";
"share_felt" = "Percepito a";
"manual_sure" = "Vuoi davvero segnalare un sisma?";
"manual_yes" = "Sì";
"filter_filter" = "Filtri";
"manual_sendmessage" = "Invia un messaggio che gli altri utenti possono leggere sul sisma che hai segnalato";
"manual_message_received" = "Messaggio ricevuto";
"liveview_unknown_location" = "La tua posizione è sconosciuta. Abilita la localizzazione dalla pagina di configurazione del tuo dispositivo";
"map_number" = "Sisma rilevato da %@ smartphone";
"permission_location_no" = "Hai scelto di impedire alla app di leggere la posizione del tuo dispositivo. NON riceverai notifiche ed allerte in tempo reale.";
"permission_location_no_background" = "Hai scelto di impedire alla app di leggere la posizione del tuo dispositivo quando la app è in background. NON è quindi garantita la ricezione di notifiche ed allerte in tempo reale.";
"alert_wave" = "Onda sismica in %lu secondi";
"share_yourtime" = "(Ora tua)";
"official_close" = "Chiudi";
"main_share" = "Condividi";
"widget_mild" = "Leggero";
"widget_strong" = "Forte";
"widget_verystring" = "Molto forte";
"main_simulator" = "Simulatore";
"globe_simulation_button" = "Calcola pre-allerta";
"globe_simulation" = "Se l'epicentro del sisma è al di fuori del cerchio rosso ed è rilevato immediatamente dagli smartphone, potrai ricevere l'allerta con più di 5 secondi di anticipo. Seleziona su mappa il possibile epicentro del sisma per calcolare il tempo di pre-allerta.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Con epicentro nella posizione scelta, grazie al servizio prioritario %@ dovresti ricevere l'allerta con %.0f secondi di anticipo. Prima di te devono essere allertate %.0f persone. Puoi aumentare il tempo di pre-allerta iscrivendoti al servizio di priorità %@";
"globe_simulation_message6" = "Con epicentro nella posizione scelta, grazie al servizio prioritario %@ dovresti ricevere l'allerta con %.0f secondi di anticipo. Sarai il primo ad essere allertato!";
"globe_simulation_priority" = "Servizio priorità";
"options_cancel" = "Cancella";
"status_cancel" = "Cancella";
"options_near_alert" = "Notifica sismi di qualsiasi magnitudo se la distanza è inferiore a 50 km";
"options_alarms" = "Allerta in tempo reale";
"options_notification_enable_alarm" = "Attiva un allarme quando un sisma è rilevato dalla rete smartphone";
"options_notification_eqn_intensity" = "Intensità sisma";
"eqn_intensity_any" = "Qualsiasi intensità";
"eqn_intensity_strong" = "Solo sismi forti";
"options_radius_mild" = "Raggio sismi lievi";
"options_radius_strong" = "Raggio sismi forti";
"options_notification_official" = "Notifiche da reti sismiche";
"options_notification_enable_official" = "Ricevi le notifiche dei sismi rilevati dalle agenzie nazionali e internazionali";
"options_agencies" = "Reti sismiche";
@@ -108,12 +94,7 @@
"main_map" = "segnalazioni nelle ultime 24h";
"official_button_map" = "Mappa";
"main_feel" = "Ho sentito un sisma!";
"manual_usebutton" = "Premi il pulsante appropriato per segnalare un sisma";
"manual_mild" = "LEGGERO\n(Solo percepito)";
"manual_strong" = "FORTE\n(Caduta di oggetti)";
"manual_verystrong" = "MOLTO FORTE\n(Crollo di edifici)";
"network_pro" = "Versione PRO";
"network_topro" = "Converti la tua app nella versione PRO! Scopri come.";
"network_pro_convert" = "Inizia la conversione";
"inapp_active" = "Servizi attivi";
"inapp_nosub" = "Nessun servizio attivo";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Coordinate";
"official_card_population" = "Popolazione";
"main_share_text" = "Ciao! Ti suggerisco la app del progetto Earthquake Network con allerte in tempo reale. Scaricala da https://sismo.app/download/ #terremoto @SismoDetector";
"manual_sendmessage_button" = "Invia messaggio";
"mercalli_II" = "II - Appena percepito";
"mercalli_III" = "III - Vibrazioni simili al passaggio di un camion";
"mercalli_IV" = "IV - Vibrazione di infissi e vetri, leggere oscillazioni di oggetti appesi";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Un\'ora";
"report_timeframe_ten_minutes" = "Dieci minuti";
"radius_any_distance" = "Qualsiasi distanza";
"timer_message2_other" = "%lu km dalla tua posizione";
"official_distance" = "%lu km dalla tua posizione";
"configuration_countries_united_states" = "Stati Uniti";
"configuration_countries_italy" = "Italia";
"configuration_countries_spain" = "Spagna";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Francia";
"configuration_countries_croatia" = "Croazia";
"configuration_countries_other" = "Altro";
"youtube_video" = "https://www.youtube.com/watch?v=ExvvPyEJglQ";
// ios only
"network_pro_subtitle" = "Stai acquistato la versione PRO, la pubblicità verrà rimossa";
"network_pro_privacy_disclaimer" = "Dichiarazioni sulla privacy";
"network_pro_terms_conditions" = "Termini e condizioni";
"network_pro_paying" = "Stai pagando:";
"inapp_detail_description" = "• Il pagamento verrà addebitato sul tuo account iTunes alla conferma dell'acquisto\n• L'abbonamento si rinnova automaticamente a meno che il rinnovo automatico non venga disattivato almeno 24 ore prima della fine del periodo corrente\n• L'abbonamento verrà addebitato per il rinnovo entro 24 ore prima della fine del periodo corrente e al costo di rinnovo indicato\n• Gli abbonamenti possono essere gestiti dall'utente e il rinnovo automatico può essere disattivato accedendo alle impostazioni dell'account dell'utente dopo l'acquisto.";
"inapp_lifetime_detail_description" = "• Il pagamento verrà addebitato sul tuo account iTunes alla conferma dell'acquisto";
"inapp_purchase" = "ISCRIVITI AL SERVIZIO";
@@ -235,20 +214,10 @@
"attention" = "Attenzione";
"official_no_country_selected" = "Non hai selezionato alcuna nazione";
"report" = "Report";
"purchase_pro_description" = "La versione PRO non ha pubblicità ed includerà nel tempo funzionalità maggiori. Inoltre supporti il progetto di ricerca che non riceve finanziamenti pubblici o privati. Grazie per considerare l'acquisto! Oppure, puoi avere la versione PRO GRATUITAMENTE sottoscrivendo uno dei servizi di priorità annuali.";
"purchase_pro_discount" = "Questa offerta è solo per te! Se converti l'app nella versione PRO entro le prossime 48 ore, avrai uno sconto del 20%%. Hai solo questa opportunità. Successivamente, potrai convertire l'app alla versione PRO a prezzo pieno. Hai ancora %lu ore per la conversione con sconto :-)";
"purchase_pro_restore" = "Ripristina";
"purchase_pro_restore_alert_title" = "Ripristino completato";
"purchase_pro_restore_alert_message" = "Hai ripristinato il prodotto che avevi acquistato";
"purchase_pro_no_subscriptions_alert_message" = "Non è stato trovato alcun prodotto da ripristinare. Assicurati di essere registrato con l'account dal quale avevi fatto l'acquisto.";
"calendar_missing_permission" = "Il calendario non può essere aperto, assicurati di aver dato il permesso alla app";
"youtube_video" = "https://www.youtube.com/watch?v=ExvvPyEJglQ";
"inapp_adv_time" = "Un utente si è iscritto al servizio solamente %@!";
"minutes_one" = "%lu minuto fa";
"minutes_other" = "%lu minuti fa";
"hours_one" = "%lu ora fa";
"hours_other" = "%lu ore fa";
"days_one" = "%lu giorno fa";
"days_other" = "%lu giorni fa";
"error_server_registration" = "Non è stato possibile registrarsi al server di Rilevatore Terremoto. La registrazione è necessaria per poter ricevere allerte in tempo reale e notifiche.";
"retry" = "Ritenta";
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un minuto fa</string>
<key>other</key>
<string>%d minuti fa</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un'ora fa</string>
<key>other</key>
<string>%d ore fa</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un giorno fa</string>
<key>other</key>
<string>%d giorni fa</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utente ha sottoscritto il servizio soltanto %d minuto fa!</string>
<key>other</key>
<string>Un utente ha sottoscritto il servizio soltanto %d minuti fa!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utente ha sottoscritto il servizio soltanto %d ora fa!</string>
<key>other</key>
<string>Un utente ha sottoscritto il servizio soltanto %d ore fa!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Un utente ha sottoscritto il servizio %d giorno fa.</string>
<key>other</key>
<string>Un utente ha sottoscritto il servizio %d giorni fa.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Onda sismica in %d secondo</string>
<key>other</key>
<string>Onda sismica in %d secondi</string>
</dict>
</dict>
</dict>
</plist>
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Uygulama tarafından oluşturulan görüntüleri kaydetmek için kitaplığa erişim gereklidir";
"NSCalendarsUsageDescription" = "İlgili depremlere ait bilgilerin kaydedilebilmesi için takvime erişim gereklidir.";
"NSContactsUsageDescription" = "Kişileri oluşturulan etkinliklere eklemek için kişilere erişim gereklidir";
"NSUserTrackingUsageDescription" = "İzleme, uygulamanın reklamının etkili olup olmadığını anlamak için kullanılır";
"CFBundleDisplayName" = "Deprem Ağı";
@@ -9,6 +9,10 @@
"Sisma forte segnalato da utente a" = "%@'da kullanıcı tarafından bildirilen şiddetli deprem";
"Sisma molto forte segnalato da utente a" = "@'da kullanıcı tarafından bildirilen çok şiddetli deprem";
"Sisma rilevato a" = "%@'da deprem tespit edildi";
"alert_intensity_no_shaking" = "Bulunduğunuz yerde hissedilmiyor";
"alert_intensity_mild" = "Hafif veya hiç titreme beklemeyin";
"alert_intensity_moderate" = "Orta derecede sallanma bekliyoruz";
"alert_intensity_strong" = "Güçlü sallama bekliyoruz";
// aligned with Android
"drawer_main_settings" = "Ayarlar";
@@ -25,6 +29,7 @@
"inapp_available_10k" = "Top 10K: Hala depremin tespitinden itibaren 1 saniyeden daha kısa süre içinde uyarı alacak %lu abonelik mevcut";
"inapp_available_100k" = "Top 100K: Hala depremin tespitinden itibaren 5 saniyeden daha kısa süre içinde uyarı alacak %lu abonelik mevcut";
"filter_magnitude" = "Minimum büyüklük";
"filter_distance" = "Maksimum mesafe";
"filter_timeframe" = "Zaman aralığı";
"filter_strong" = "Aşağıdaki durumlarda herhangi bir mesafede gerçekleşen şiddetli depremleri göster";
"filter_near" = "50 km'den daha yakınsa herhangi bir büyüklükteki sarsıntıyı gösterin";
@@ -34,13 +39,6 @@
"share_radius100" = "100km yarıçapında %@";
"official_smartphones" = "Deprem %@ akıllı telefonları tarafından gerçek zamanlı olarak tespit edildi. Uyarı verildi.";
"official_reports" = "%@ kullanıcı tarafından bildirildi";
"weather_weather" = "Deprem zamanında hava durumu";
"weather_temperature" = "Sıcaklık: %.02f";
"weather_pressure" = "Basınç: %@";
"weather_windspeed" = "Rüzgar hızı: %@";
"weather_humidity" = "Nem: %@";
"weather_clouds" = "Bulut örtüsü: %@";
"weather_nodata" = "Bu deprem için hava durumu verisi yok";
"official_prelimiary" = "İLK";
"calendar_description_nogeo_km" = "Deprem M%@, derinlik %@ km.";
"filter_empty" = "Etkinleştirilmiş filtrelere ve sismik şebekelere bağlı olarak, son 24 saatte deprem olmamıştır. Filtreleri değiştirmek için alttaki çubuğu tıklayın. Diğer sismik ağları etkinleştirmek için üstteki dünya simgesini tıklayın.";
@@ -48,23 +46,16 @@
"official_select_confirm" = "Ülkeyi onaylayın";
"share_hashtag" = "#deprem";
"share_notified" = "Deprem Ağı uygulaması aracılığıyla bildirildi. @SismoDetector gerçek zamanlı #deprem uyarılarını almak için uygulamayı https://sismo.app/download/ adresinden indirin.";
"share_felt" = "Hissedilen";
"manual_sure" = "Gerçekten bir depremi bildirmek ister misiniz?";
"manual_yes" = "Evet";
"filter_filter" = "Filtreler";
"manual_sendmessage" = "Diğer kullanıcıların bildirdiğiniz deprem hakkında okuyabilecekleri bir mesaj gönderin";
"manual_message_received" = "Mesaj alındı";
"liveview_unknown_location" = "Konumunuz bilinmiyor. Akıllı telefon yapılandırmasından akıllı telefon konumunu etkinleştirin";
"map_number" = "%@ akıllı telefon tarafından tespit edilen deprem";
"permission_location_no" = "Uygulamanın cihazın konumunu okumasını engellemeyi seçtiniz. Gerçek zamanlı bildirim ve uyarılar ALMAYACAKSINIZ";
"permission_location_no_background" = "Uygulama arka planda olduğunda uygulamanın cihazınızın konumunu okumasını engellemeyi seçtiniz. Bildirimler ve gerçek zamanlı uyarılar ALINAMAZ";
"alert_wave" = "%lu saniyede sismik dalga";
"share_yourtime" = "(Sizin saat)";
"official_close" = "Kapat";
"main_share" = "Paylaş";
"widget_mild" = "Hafif";
"widget_strong" = "Şiddetli";
"widget_verystring" = "Çok şiddetli";
"main_simulator" = "Simülatör";
"globe_simulation_button" = "Uyarı süresini hesapla";
"globe_simulation" = "Deprem merkez üssü kırmızı diskin dışındaysa ve deprem akıllı telefonlar tarafından hemen tespit edilirse, uyarıyı 5 saniyeden daha uzun süre önce alırsınız. Uyarı zamanını hesaplamak için haritada olası merkez üssünü seçin.";
@@ -77,15 +68,10 @@
"globe_simulation_message5" = "Bu merkez üssüyle, %@ öncelikli servis sayesinde %.0f saniye öncesinden uyarı almalısınız. %.0f kişi sizden önce uyarı alacaktır. Uyarı süresini artırmak için %@ öncelikli servise abone olabilirsiniz";
"globe_simulation_message6" = "Bu merkez üssüyle, %@ öncelikli servis sayesinde %.0f saniye öncesinden uyarı almalısınız. İlk uyarılan siz olacaksınız!";
"globe_simulation_priority" = "Öncelikli hizmet";
"options_cancel" = "İptal et";
"status_cancel" = "İptal et";
"options_near_alert" = "Mesafe den azsa her büyüklükteki depremi bildir 50 km";
"options_alarms" = "Gerçek zamanlı uyarı";
"options_notification_enable_alarm" = "Bir deprem akıllı telefon ağı tarafından gerçek zamanlı olarak tespit edildiğinde bir alarm çal";
"options_notification_eqn_intensity" = "Deprem şiddeti";
"eqn_intensity_any" = "Herhangi bir şiddet";
"eqn_intensity_strong" = "Sadece şiddetli depremler";
"options_radius_mild" = "Yarıçap içindeki hafif depremler";
"options_radius_strong" = "Yarıçap içinde şiddetli depremler";
"options_notification_official" = "Sismik ağ bildirimleri";
"options_notification_enable_official" = "Ulusal ve uluslararası sismik şebekeler tarafından tespit edilen depremler için bildirim alın";
"options_agencies" = "Sismik ağlar";
@@ -108,12 +94,7 @@
"main_map" = "son 24 saatteki raporlar";
"official_button_map" = "Harita";
"main_feel" = "Bir deprem hissettim!";
"manual_usebutton" = "Bir deprem bildirmek için aşağıdaki uygun düğmeye basın";
"manual_mild" = "HAFİF\n(Sadece hissedilen)";
"manual_strong" = "ŞİDDETLİ\n(Nesnelerin düştüğü)";
"manual_verystrong" = "ÇOK ŞİDDETLİ\n(Bina yıkılması)";
"network_pro" = "PRO sürüm";
"network_topro" = "Uygulamanızı PRO sürüme dönüştürün! Nasıl olduğunu öğrenin.";
"network_pro_convert" = "Dönüştürmeyi başlat";
"inapp_active" = "Aktif abonelik";
"inapp_nosub" = "Aktif abonelik yok";
@@ -147,7 +128,6 @@
"official_card_coordinates" = "Koordinatlar";
"official_card_population" = "Toplum";
"main_share_text" = "Merhaba! Gerçek zamanlı uyarıları içeren Earthquake Network projesi uygulamasını size öneriyorum. https://sismo.app/download/ #deprem @SismoDetector adresinden indirin";
"manual_sendmessage_button" = "Mesajı gönder";
"mercalli_II" = "II - Zar zor algılanan";
"mercalli_III" = "III - Geçen bir kamyona benzer titreşimler";
"mercalli_IV" = "IV - Pencerelerin titreşimleri, asılı nesnelerin hafif salınımları";
@@ -189,7 +169,7 @@
"report_timeframe_one_hour" = "Bir saat";
"report_timeframe_ten_minutes" = "On dakika";
"radius_any_distance" = "Herhangi bir mesafe";
"timer_message2_other" = "Bulunduğunuz yere %lu km";
"official_distance" = "Bulunduğunuz yere %lu km";
"configuration_countries_united_states" = "Amerika Birleşik Devletleri";
"configuration_countries_italy" = "İtalya";
"configuration_countries_spain" = "ispanya";
@@ -214,12 +194,11 @@
"configuration_countries_france" = "Fransa";
"configuration_countries_croatia" = "Hırvatistan";
"configuration_countries_other" = "Diğer";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
// ios only
"network_pro_subtitle" = "PRO sürümünü satın alıyorsunuz, reklam kaldırılacak";
"network_pro_privacy_disclaimer" = "Gizlilikle ilgili sorumluluk reddi";
"network_pro_terms_conditions" = "Şartlar ve koşullar";
"network_pro_paying" = "Ödüyorsunuz:";
"inapp_detail_description" = "• Satın alma onayının ardından ödemeniz iTunes hesabınızdan tahsil edilecektir\n• Otomatik yenileme, cari dönemin bitiminden en az 24 saat önce devre dışı bırakılmadığı sürece abonelik otomatik olarak yenilenir\n• Abonelik, 24 saat içinde yenileme için ücretlendirilir cari dönemin bitiminden saatler önce ve belirlenen yenileme maliyeti\n• Satın alma işleminden sonra kullanıcının hesap ayarlarına girilerek abonelikler kullanıcı tarafından yönetilebilir ve otomatik yenileme devre dışı bırakılabilir.";
"inapp_lifetime_detail_description" = "• Satın alma onayının ardından ödemeniz iTunes hesabınızdan tahsil edilecektir";
"inapp_purchase" = "HİZMETE ABONE OL";
@@ -235,20 +214,10 @@
"attention" = "Dikkat";
"official_no_country_selected" = "Herhangi bir ülke seçmediniz";
"report" = "Bildiri";
"purchase_pro_description" = "PRO sürümü herhangi bir reklam içermez ve ekstra özellikler içerir. Ayrıca, dışarıdan fon almayan bu araştırma projesini desteklemeye yardımcı oluyorsunuz. Düşündüğünüz için teşekkürler! Aksi takdirde yıllık öncelikli hizmete abone olarak PRO sürümüne ÜCRETSİZ sahip olabilirsiniz.";
"purchase_pro_discount" = "Bu size özel bir tekliftir. Önümüzdeki 48 saat içinde uygulamayı PRO'ya dönüştürürseniz %%20 indiriminiz olur. Sadece bu şansa sahip olacaksın. Ardından PRO sürümü tam fiyatına mal olacak. Hala %lu saatin var :-)";
"purchase_pro_restore" = "Geri yükle";
"purchase_pro_restore_alert_title" = "Geri yükleme tamamlandı";
"purchase_pro_restore_alert_message" = "Satın aldığınız ürünü geri yüklediniz";
"purchase_pro_no_subscriptions_alert_message" = "Geri yüklenecek satın alma bulunamadı. Satın alma işleminin yapıldığı hesapta oturum açtığınızdan emin olun.";
"calendar_missing_permission" = "Takvim açılamıyor, doğru izinleri ayarladığınızdan emin olun.";
"youtube_video" = "https://www.youtube.com/watch?v=BqaW97fJFZc";
"inapp_adv_time" = "Bir kullanıcı hizmete yalnızca %@ önce abone oldu!";
"minutes_one" = "%lu dakika";
"minutes_other" = "%lu dakika";
"hours_one" = "%lu saat";
"hours_other" = "%lu saat";
"days_one" = "%lu gün";
"days_other" = "%lu gün";
"error_server_registration" = "Deprem Ağı sunucusuna kayıt olmak mümkün olmadı. Gerçek zamanlı uyarılar ve deprem bildirimleri almak için kayıt yaptırmanız gerekir.";
"retry" = "Yeniden dene";
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>manual_minutes_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir dakika önce</string>
<key>other</key>
<string>%d dakika önce</string>
</dict>
</dict>
<key>manual_hours_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir saat önce</string>
<key>other</key>
<string>%d saat önce</string>
</dict>
</dict>
<key>manual_days_ago</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir gün önce</string>
<key>other</key>
<string>%d gün önce</string>
</dict>
</dict>
<key>inapp_adv_minutes</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir kullanıcı sadece %d dakika önce servise abone oldu!</string>
<key>other</key>
<string>Bir kullanıcı sadece %d dakika önce servise abone oldu!</string>
</dict>
</dict>
<key>inapp_adv_hours</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir kullanıcı sadece %d saat önce servise abone oldu!</string>
<key>other</key>
<string>Bir kullanıcı sadece %d saat önce servise abone oldu!</string>
</dict>
</dict>
<key>inapp_adv_days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>Bir kullanıcı %d gün önce servise abone oldu.</string>
<key>other</key>
<string>Bir kullanıcı %d gün önce servise abone oldu.</string>
</dict>
</dict>
<key>alert_wave</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d saniyede sismik dalga</string>
<key>other</key>
<string>%d saniyede sismik dalga</string>
</dict>
</dict>
</dict>
</plist>
+3 -3
View File
@@ -4,10 +4,10 @@ platform :ios, '12.0'
use_frameworks!
target 'Earthquake Network' do
pod 'Firebase/Core'
pod 'Firebase/Messaging'
pod 'Firebase/Crashlytics'
pod 'FirebaseMessaging'
pod 'FirebaseCrashlytics'
pod 'Google-Mobile-Ads-SDK'
pod 'FBSDKCoreKit'
pod 'DZNEmptyDataSet'
pod 'Solar'
end
+80 -82
View File
@@ -1,53 +1,33 @@
PODS:
- DZNEmptyDataSet (1.8.1)
- Firebase/Core (10.1.0):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 10.1.0)
- Firebase/CoreOnly (10.1.0):
- FirebaseCore (= 10.1.0)
- Firebase/Crashlytics (10.1.0):
- Firebase/CoreOnly
- FirebaseCrashlytics (~> 10.1.0)
- Firebase/Messaging (10.1.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 10.1.0)
- FirebaseAnalytics (10.1.0):
- FirebaseAnalytics/AdIdSupport (= 10.1.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.1.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.1.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseCore (10.1.0):
- FBAEMKit (16.1.3):
- FBSDKCoreKit_Basics (= 16.1.3)
- FBSDKCoreKit (16.1.3):
- FBAEMKit (= 16.1.3)
- FBSDKCoreKit_Basics (= 16.1.3)
- FBSDKCoreKit_Basics (16.1.3)
- FirebaseCore (10.12.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.1.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseCrashlytics (10.1.0):
- FirebaseCoreExtension (10.12.0):
- FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.12.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseCrashlytics (10.12.0):
- FirebaseCore (~> 10.5)
- FirebaseInstallations (~> 10.0)
- FirebaseSessions (~> 10.5)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/Environment (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (~> 2.1)
- FirebaseInstallations (10.1.0):
- FirebaseInstallations (10.12.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.1.0):
- FirebaseMessaging (10.12.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
@@ -56,79 +36,92 @@ PODS:
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- Google-Mobile-Ads-SDK (9.12.0):
- FirebaseSessions (10.12.0):
- FirebaseCore (~> 10.5)
- FirebaseCoreExtension (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/Environment (~> 7.10)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesSwift (~> 2.1)
- Google-Mobile-Ads-SDK (10.8.0):
- GoogleAppMeasurement (< 11.0, >= 7.0)
- GoogleUserMessagingPlatform (>= 1.1)
- GoogleAppMeasurement (10.1.0):
- GoogleAppMeasurement/AdIdSupport (= 10.1.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- GoogleAppMeasurement (10.12.0):
- GoogleAppMeasurement/AdIdSupport (= 10.12.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.1.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.1.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- GoogleAppMeasurement/AdIdSupport (10.12.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.12.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.1.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- GoogleAppMeasurement/WithoutAdIdSupport (10.12.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleDataTransport (9.2.0):
- GoogleDataTransport (9.2.3):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUserMessagingPlatform (2.0.1)
- GoogleUtilities/AppDelegateSwizzler (7.8.0):
- GoogleUtilities/AppDelegateSwizzler (7.11.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.8.0):
- GoogleUtilities/Environment (7.11.1):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.8.0):
- GoogleUtilities/Logger (7.11.1):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (7.8.0):
- GoogleUtilities/MethodSwizzler (7.11.1):
- GoogleUtilities/Logger
- GoogleUtilities/Network (7.8.0):
- GoogleUtilities/Network (7.11.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.8.0)"
- GoogleUtilities/Reachability (7.8.0):
- "GoogleUtilities/NSData+zlib (7.11.1)"
- GoogleUtilities/Reachability (7.11.1):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.8.0):
- GoogleUtilities/UserDefaults (7.11.1):
- GoogleUtilities/Logger
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
- nanopb/decode (2.30909.0)
- nanopb/encode (2.30909.0)
- PromisesObjC (2.1.1)
- PromisesObjC (2.2.0)
- PromisesSwift (2.2.0):
- PromisesObjC (= 2.2.0)
- Solar (2.1.0)
DEPENDENCIES:
- DZNEmptyDataSet
- Firebase/Core
- Firebase/Crashlytics
- Firebase/Messaging
- FBSDKCoreKit
- FirebaseCrashlytics
- FirebaseMessaging
- Google-Mobile-Ads-SDK
- Solar
SPEC REPOS:
trunk:
- DZNEmptyDataSet
- Firebase
- FirebaseAnalytics
- FBAEMKit
- FBSDKCoreKit
- FBSDKCoreKit_Basics
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- FirebaseCrashlytics
- FirebaseInstallations
- FirebaseMessaging
- FirebaseSessions
- Google-Mobile-Ads-SDK
- GoogleAppMeasurement
- GoogleDataTransport
@@ -136,26 +129,31 @@ SPEC REPOS:
- GoogleUtilities
- nanopb
- PromisesObjC
- PromisesSwift
- Solar
SPEC CHECKSUMS:
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
Firebase: 444b35a9c568a516666213c2f6cccd10cb12559f
FirebaseAnalytics: 24cb27b52b2e11ad5013528195b4ca0755dec960
FirebaseCore: 55e7ae35991ccca4db03ff8d8df6ed5f17a3e4c7
FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5
FirebaseCrashlytics: 93906d7085eb3e4dd90d08fe42a15d4f0406b6ab
FirebaseInstallations: 99d24bac0243cf8b0e96cf5426340d211f0bcc80
FirebaseMessaging: 4487bbff9b9b927ba1dd3ea40d1ceb58e4ee3cb5
Google-Mobile-Ads-SDK: b4e9efb765ef1693ae9dd94c527b6c1d91ee5052
GoogleAppMeasurement: e490e248af3da95afe8fa8e7baac232dc8d020b7
GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f
FBAEMKit: af2972f39bb0f3f7c45998f435b007833c32ffb2
FBSDKCoreKit: 19e2e18b3be578d7a51fed8fdd8c152bef0b9511
FBSDKCoreKit_Basics: dd9826ce3c9fd9f8cdf8dbbd0ef0a53e6c0c9e7e
FirebaseCore: f86a1394906b97ac445ae49c92552a9425831bed
FirebaseCoreExtension: 0ce5ac36042001cfa233ce7bfa28e5c313cf80f4
FirebaseCoreInternal: 950500ad8a08963657f6d8c67b579740c06d6aa1
FirebaseCrashlytics: c4d111b7430c49744c74bcc6346ea00868661ac8
FirebaseInstallations: 7b99ef103f013624444c614397038219c45f8e63
FirebaseMessaging: bb2c4f6422a753038fe137d90ae7c1af57251316
FirebaseSessions: a4ee211eeb31a2224cd8d9d4e30a0fccde9aa00c
Google-Mobile-Ads-SDK: 69daa7fb42061b425340706e382e87fab3e666a3
GoogleAppMeasurement: 2d800fab85e7848b1e66a6f8ce5bca06c5aad892
GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd
GoogleUserMessagingPlatform: 5f8b30daf181805317b6b985bb51c1ff3beca054
GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959
Solar: 2dc6e7cc39186cb0c8228fa08df76fb50c7d8f24
PODFILE CHECKSUM: dd5131b6d7a83fb7c22ecc161ed4fc143eda0ac1
PODFILE CHECKSUM: d1702281e78deff520792b6eb9ce54ffd0e034c5
COCOAPODS: 1.11.3
COCOAPODS: 1.12.1