Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73caf9647c | |||
| 8700e200f9 | |||
| e99845ff1b | |||
| a0161e8f4c | |||
| 1b9944a7ca | |||
| 4c00e4ef6a | |||
| 63592e6cfb | |||
| 2877dff23c | |||
| f2386a1abb | |||
| 5e4a500f03 | |||
| 2b8f2db7c5 | |||
| 11d994696d | |||
| cd6e20c1b2 | |||
| af5371571c | |||
| 6291b22df0 | |||
| 2a7cfd3079 | |||
| cae5fee992 | |||
| 53b8c0fab4 | |||
| 8751d3c8f2 | |||
| 2d333f993b | |||
| 22d421f1cc | |||
| cec8b39fc7 | |||
| 5ceaa4a8be | |||
| 94bdb9dbe1 | |||
| ee1b762032 | |||
| 5a6c5a5cfc | |||
| d55b2ec98f | |||
| 761ebc1d17 | |||
| dd5e8862ed | |||
| ceca3ed50d | |||
| 6cce448acf | |||
| 5ddb8da902 | |||
| 644002a792 | |||
| e902969c9a | |||
| 57c2ca5ae9 | |||
| 107d4c7600 | |||
| 6a41f4558a | |||
| 995a6011d5 | |||
| fcb3ab5be1 | |||
| f8c7edf588 | |||
| 4bb77e2921 | |||
| d399e0b37b | |||
| a85fbe56be | |||
| cf97c3cb61 | |||
| 7611e3eb15 | |||
| 4369284fb7 | |||
| 0e4fadd666 | |||
| 6622256339 |
@@ -1,5 +1,55 @@
|
||||
# Changelog
|
||||
|
||||
## Versione 5.2
|
||||
|
||||
- Nuova schermata per allerta in tempo reale
|
||||
|
||||
## Versione 5.1
|
||||
|
||||
### Build (91)
|
||||
- Corretto problema con selezioni reti EMSC
|
||||
|
||||
### Build (90)
|
||||
- Rimozione notifiche dello stesso tipo
|
||||
|
||||
## Versione 5.0.3
|
||||
|
||||
### Build (89)
|
||||
- Corretto problema con ultima posizione non salvata in app
|
||||
- Forzato aggiornamento Firebase
|
||||
- Corretti metodi deprecati in salvataggio dati
|
||||
- Corretti comportamento filtri con iOS 15
|
||||
- Slider con valori a step
|
||||
|
||||
## Versione 5.0.2
|
||||
|
||||
### Build (88)
|
||||
- Corretto errato salvataggio raggio sismi forti in allerte tempo reale
|
||||
|
||||
## Versione 5.0.1
|
||||
|
||||
### Build (87)
|
||||
- Corretto problema con slider in impostazioni
|
||||
|
||||
## Versione 5.0
|
||||
|
||||
### Build (86)
|
||||
- Corretto problema layout in schede sismi
|
||||
|
||||
### Build (85)
|
||||
- Nuova icona
|
||||
- Nascosta sezione 'pro'
|
||||
- Aggiornamento ad Xcode 13
|
||||
- Disabilitati ads
|
||||
|
||||
## Versione 4.2
|
||||
### Build (84)
|
||||
- Corretti errori in nuovi sviluppi
|
||||
|
||||
### Build (83)
|
||||
- Aggiunto supporto per abbonamenti a vita
|
||||
- Allineata UI in sezione abbonamenti e versione pro
|
||||
|
||||
## Versione 4.1.1
|
||||
### Build (82)
|
||||
- Corretti placeholder in stringhe
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:34:50",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "37.983810",
|
||||
"detection_longitude": "23.727539",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "37.683810",
|
||||
"latitude": "38.19",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "23.327539",
|
||||
"longitude": "22.26",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-16 12:41:20",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "37.3229978",
|
||||
"detection_longitude": "-122.0321823",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "37.9229978",
|
||||
"latitude": "35.15",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-121.0321823",
|
||||
"longitude": "-117.78",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 20:39:00",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "-34.603722",
|
||||
"detection_longitude": "-58.381592",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "-34.103722",
|
||||
"latitude": "-32.57",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-58.781592",
|
||||
"longitude": "-71.46",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:37:40",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "48.856614",
|
||||
"detection_longitude": "2.8522219",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "48.456614",
|
||||
"latitude": "49.77",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "2.3522219",
|
||||
"longitude": "1.05",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:39:50",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "45.813177",
|
||||
"detection_longitude": "15.977048",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "45.413177",
|
||||
"latitude": "45.09",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "15.677048",
|
||||
"longitude": "14.87",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:42:40",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "-2.548926",
|
||||
"detection_longitude": "118.0148634",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "-2.948926",
|
||||
"latitude": "-7.38",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "118.6148634",
|
||||
"longitude": "106.83",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 20:32:20",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "45.64664",
|
||||
"detection_longitude": "9.188540",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "45.164664",
|
||||
"latitude": "42.958",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "9.788540",
|
||||
"longitude": "12.702",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-16 12:39:40",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "19.432608",
|
||||
"detection_longitude": "-99.133209",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "19.932608",
|
||||
"latitude": "18.72",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "-98.033209",
|
||||
"longitude": "-97.90",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"sound": "alert_star_trek.wav"
|
||||
},
|
||||
"counter": 10,
|
||||
"datetime": "2021-04-15 21:44:30",
|
||||
"datetime": "2022-06-22 16:15:00",
|
||||
"detection_latitude": "41.008238",
|
||||
"detection_longitude": "28.978359",
|
||||
"gcm.message_id": "1614708857742608",
|
||||
"google.c.a.e": 1,
|
||||
"google.c.sender.id": "899482329945",
|
||||
"intensity": 2,
|
||||
"latitude": "41.608238",
|
||||
"latitude": "40.33",
|
||||
"location": "150 km (Test)",
|
||||
"longitude": "28.678359",
|
||||
"longitude": "27.66",
|
||||
"peak": "-1",
|
||||
"randcode": 0,
|
||||
"test": 1,
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "NotificationService.h"
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// NotificationService+Extension.swift
|
||||
// EQNNotificationService
|
||||
//
|
||||
// Created by Andrea Busi on 28/05/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
|
||||
extension NotificationService {
|
||||
|
||||
@objc(removeNotificationsForType:completion:)
|
||||
func removeNotifications(
|
||||
for type: String?,
|
||||
completion: @escaping() -> Void
|
||||
) {
|
||||
guard let type = type else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
let notificationCenter = UNUserNotificationCenter.current()
|
||||
|
||||
notificationCenter.getDeliveredNotifications { notifications in
|
||||
let sameTypeNotifications = notifications.filter { notification in
|
||||
let payload = notification.request.content.userInfo
|
||||
if let notificationType = payload["type"] as? String {
|
||||
return notificationType == type
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
let identifiers = sameTypeNotifications.map { $0.request.identifier }
|
||||
notificationCenter.removeDeliveredNotifications(withIdentifiers: identifiers)
|
||||
|
||||
// !! Note: this is a known issue/bug
|
||||
// we need to add a delay before invoking the completion, otherwise the notification will not be remved
|
||||
// ref: https://stackoverflow.com/questions/53697279/why-are-notifications-not-removed-with-removedeliverednotifications
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
#import "NotificationService.h"
|
||||
#import "EQNAllertaSismica.h"
|
||||
#import "Costanti.h"
|
||||
#import "EQNNotificationService-Swift.h"
|
||||
|
||||
|
||||
@interface NotificationService ()
|
||||
|
||||
@@ -158,7 +160,10 @@ static NSString * const EQNSoundNotificationEQN = @"alert_sound.wav";
|
||||
}
|
||||
}
|
||||
|
||||
[self contentComplete];
|
||||
// remove same type posted notification
|
||||
[self removeNotificationsForType:notificationType completion:^{
|
||||
[self contentComplete];
|
||||
}];;
|
||||
}
|
||||
|
||||
- (void)serviceExtensionTimeWillExpire
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
652C37BD26092B3C0068EC3B /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652C37BC26092B3C0068EC3B /* FiltersViewModel.swift */; };
|
||||
6531185928425B89006CBC29 /* NotificationService+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6531185828425B89006CBC29 /* NotificationService+Extension.swift */; };
|
||||
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */; };
|
||||
6535600425F398CD00BB57D2 /* Costanti+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6535600325F398CD00BB57D2 /* Costanti+Extensions.swift */; };
|
||||
653604E9262348FA00B2B651 /* EQNBaseMapFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */; };
|
||||
@@ -129,6 +131,8 @@
|
||||
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */; };
|
||||
6586971125F44C26009C0182 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
||||
658BAB7B25FE67930015C454 /* EQNBaseMapRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */; };
|
||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */; };
|
||||
658BC02B2859A4D3009EECAA /* RealtimeAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */; };
|
||||
65AD23CE261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AD23CD261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift */; };
|
||||
65BBB22C26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65BBB22B26064BE6005D6CDF /* SegnalazioniLast24HoursCell.swift */; };
|
||||
65D409942619BA34008CF356 /* SegnalazioniSendReportCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65D409932619BA34008CF356 /* SegnalazioniSendReportCell.swift */; };
|
||||
@@ -136,6 +140,7 @@
|
||||
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 */; };
|
||||
65E1B19B260F980600A0ACBA /* Dictionary+EQNExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */; };
|
||||
8C10B0B92281FE7F00125C9F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
|
||||
8C10B0BA2281FE7F00125C9F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C10B0BD2281FE7F00125C9F /* Localizable.strings */; };
|
||||
@@ -225,7 +230,6 @@
|
||||
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */; };
|
||||
DCB6FBEC24D0B40600ED23B8 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */; };
|
||||
DCBB267A24D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */; };
|
||||
DCBB267C24D1E98300F04559 /* EQNInsetTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267B24D1E98300F04559 /* EQNInsetTableViewCell.swift */; };
|
||||
DCBB267E24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267D24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift */; };
|
||||
DCBB268024D1ECE200F04559 /* SubscriptionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267F24D1ECE200F04559 /* SubscriptionDetailViewController.swift */; };
|
||||
DCBB84F0252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB84EF252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift */; };
|
||||
@@ -284,9 +288,11 @@
|
||||
/* 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>"; };
|
||||
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>"; };
|
||||
652C37BC26092B3C0068EC3B /* FiltersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewModel.swift; sourceTree = "<group>"; };
|
||||
6531185828425B89006CBC29 /* NotificationService+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationService+Extension.swift"; sourceTree = "<group>"; };
|
||||
65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniMapViewController.swift; sourceTree = "<group>"; };
|
||||
6535600325F398CD00BB57D2 /* Costanti+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Costanti+Extensions.swift"; sourceTree = "<group>"; };
|
||||
653604E8262348FA00B2B651 /* EQNBaseMapFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapFilter.swift; sourceTree = "<group>"; };
|
||||
@@ -404,6 +410,8 @@
|
||||
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkViewModel.swift; sourceTree = "<group>"; };
|
||||
6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBlurredCloseButton.swift; sourceTree = "<group>"; };
|
||||
658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapRepresentable.swift; sourceTree = "<group>"; };
|
||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertViewController.swift; sourceTree = "<group>"; };
|
||||
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertView.swift; sourceTree = "<group>"; };
|
||||
65A4D5AA26280A24003918E0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
65A4D5AB26280A24003918E0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
65A4D5AC26280A56003918E0 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "el-GR"; path = "el-GR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
@@ -423,6 +431,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>"; };
|
||||
65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+EQNExtensions.swift"; sourceTree = "<group>"; };
|
||||
8C10B0BC2281FE7F00125C9F /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8C10B0BE2281FE9E00125C9F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -547,7 +556,6 @@
|
||||
DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertSimulatorViewController.swift; sourceTree = "<group>"; };
|
||||
DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
|
||||
DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsHeaderTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCBB267B24D1E98300F04559 /* EQNInsetTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNInsetTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCBB267D24D1EA2000F04559 /* SubscriptionProductTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionProductTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCBB267F24D1ECE200F04559 /* SubscriptionDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionDetailViewController.swift; sourceTree = "<group>"; };
|
||||
DCBB84EF252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsNoLocationTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@@ -615,6 +623,15 @@
|
||||
path = Debug;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
658BC0272859A43C009EECAA /* Realtime Alert */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */,
|
||||
658BC02A2859A4D3009EECAA /* RealtimeAlertView.swift */,
|
||||
);
|
||||
path = "Realtime Alert";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
65DBFB5225E2A2580041CBA6 /* Map annotation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -660,6 +677,7 @@
|
||||
8C483CB521FDACD100259FD2 /* EQNNotificationService-Bridging-Header.h */,
|
||||
8C4B0B7C21CACE3F00AED489 /* NotificationService.h */,
|
||||
8C4B0B7D21CACE3F00AED489 /* NotificationService.m */,
|
||||
6531185828425B89006CBC29 /* NotificationService+Extension.swift */,
|
||||
DC30BC862534DBB30041B23B /* Icons */,
|
||||
8C4B0B7F21CACE3F00AED489 /* Info.plist */,
|
||||
);
|
||||
@@ -752,6 +770,7 @@
|
||||
8C7A3B64225A5EA30045B266 /* NSDictionary+EQNExtensions.m */,
|
||||
65E1B19A260F980600A0ACBA /* Dictionary+EQNExtensions.swift */,
|
||||
65583A04261B83BE00ECA9F9 /* UIKit+Extensions.swift */,
|
||||
650B23AA2632CCD3007AE752 /* UIView+EQNExtensions.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@@ -1067,6 +1086,7 @@
|
||||
8C593E89217BA2470008B260 /* EQNSegnalazione.m */,
|
||||
8CF4F4D9216D44930057110B /* EQNPastquakes.h */,
|
||||
8CF4F4DA216D44930057110B /* EQNPastquakes.m */,
|
||||
65E1226B285C92AA000E294A /* EQNRealtimeAlert.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@@ -1086,6 +1106,7 @@
|
||||
DCEFF21024F57163009D3FE1 /* Settings */,
|
||||
DC141968250E769B0059E060 /* Seismic Networks */,
|
||||
DCB5281F256015EB005288E5 /* Simulator */,
|
||||
658BC0272859A43C009EECAA /* Realtime Alert */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
@@ -1097,7 +1118,6 @@
|
||||
DC03BEAA250BC0A60084769B /* EQNRoundedButton.swift */,
|
||||
DC52B8A424FCCD6900ABEBA6 /* AppTheme.swift */,
|
||||
DCA5B6E6252E4BD8002AEC96 /* EQNBaseTableViewCell.swift */,
|
||||
DCBB267B24D1E98300F04559 /* EQNInsetTableViewCell.swift */,
|
||||
653C67E125F3CC2E00FE52AC /* EQNCustomAnnotationView.swift */,
|
||||
6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */,
|
||||
);
|
||||
@@ -1451,9 +1471,9 @@
|
||||
"${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics/FirebaseCrashlytics.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
|
||||
@@ -1466,9 +1486,9 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstanceID.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
|
||||
@@ -1526,6 +1546,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DCDAB31925188BB3001AE40D /* EQNAllertaSismica.m in Sources */,
|
||||
6531185928425B89006CBC29 /* NotificationService+Extension.swift in Sources */,
|
||||
8C4B0B7E21CACE3F00AED489 /* NotificationService.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1574,13 +1595,14 @@
|
||||
DCA5B6E7252E4BD8002AEC96 /* EQNBaseTableViewCell.swift in Sources */,
|
||||
8CF66058214C566B009F4314 /* ServerRequest.m in Sources */,
|
||||
DCF9E14D24F6D1AA002B6B1D /* EQNData.swift in Sources */,
|
||||
65E1226C285C92AA000E294A /* EQNRealtimeAlert.swift in Sources */,
|
||||
DC52B8A524FCCD6900ABEBA6 /* AppTheme.swift in Sources */,
|
||||
653C680425F3DF8A00FE52AC /* EQNBaseMapViewController.swift in Sources */,
|
||||
658BC02B2859A4D3009EECAA /* RealtimeAlertView.swift in Sources */,
|
||||
DC27EB2F24F6EBE000ACBFE0 /* SettingsSeismicNetworksViewController.swift in Sources */,
|
||||
8CF66059214C566B009F4314 /* Reachability.m in Sources */,
|
||||
DC886A5D24E92D5500F7A5D3 /* EQNBaseViewController.m in Sources */,
|
||||
8C593E8A217BA2470008B260 /* EQNSegnalazione.m in Sources */,
|
||||
DCBB267C24D1E98300F04559 /* EQNInsetTableViewCell.swift in Sources */,
|
||||
8CBD3DCA2149B9AD0070C963 /* AllerteViewController.m in Sources */,
|
||||
DC646F32252B698B000AA5FD /* AlertsSeismicNotificationCompactTableViewCell.swift in Sources */,
|
||||
DCF10DCD24D2C935009F34C3 /* EQNPurchaseAvailability.swift in Sources */,
|
||||
@@ -1608,6 +1630,7 @@
|
||||
DC65B391250F243E00251693 /* SeismicSettingsNetworksViewController.swift in Sources */,
|
||||
65DBFB4B25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift in Sources */,
|
||||
DC08804124F5B41400186D97 /* SettingSliderTableViewCell.swift in Sources */,
|
||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */,
|
||||
8CBD3DD82149B9AD0070C963 /* main.m in Sources */,
|
||||
8CF05B57218C93BA0055012B /* EQNUtility.m in Sources */,
|
||||
8C4E34422152B5E8008B0D2A /* EQNRilevamento.m in Sources */,
|
||||
@@ -1631,6 +1654,7 @@
|
||||
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */,
|
||||
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */,
|
||||
DCC76BD8251F56050005C4DC /* SeismicCardSettingsViewController.swift in Sources */,
|
||||
650B23AB2632CCD3007AE752 /* UIView+EQNExtensions.swift in Sources */,
|
||||
653C67FC25F3D63500FE52AC /* EQNMapAnnotationUserReport.swift in Sources */,
|
||||
DC3CE50A250EB7A8005A7DD5 /* EQNGenericPickerViewController.swift in Sources */,
|
||||
DCEFF21A24F587E3009D3FE1 /* SettingItem.swift in Sources */,
|
||||
@@ -1738,12 +1762,12 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationService/EQNNotificationService.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Service - Development";
|
||||
@@ -1762,12 +1786,12 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationService/EQNNotificationService.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Service - AppStore";
|
||||
@@ -1811,9 +1835,11 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -1823,6 +1849,7 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
"ADS_ENABLED=0",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
@@ -1870,13 +1897,16 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "ADS_ENABLED=0";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -1899,16 +1929,16 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1944,8 +1974,6 @@
|
||||
"-framework",
|
||||
"\"FirebaseInstallations\"",
|
||||
"-framework",
|
||||
"\"FirebaseInstanceID\"",
|
||||
"-framework",
|
||||
"\"FirebaseMessaging\"",
|
||||
"-framework",
|
||||
"\"Foundation\"",
|
||||
@@ -2011,15 +2039,15 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution";
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -2055,8 +2083,6 @@
|
||||
"-framework",
|
||||
"\"FirebaseInstallations\"",
|
||||
"-framework",
|
||||
"\"FirebaseInstanceID\"",
|
||||
"-framework",
|
||||
"\"FirebaseMessaging\"",
|
||||
"-framework",
|
||||
"\"Foundation\"",
|
||||
@@ -2120,12 +2146,12 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
|
||||
@@ -2144,12 +2170,12 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
INFOPLIST_FILE = EQNNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.1.1;
|
||||
MARKETING_VERSION = 5.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
|
||||
|
||||
@@ -36,10 +36,12 @@
|
||||
// Test ads on specific devices
|
||||
GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"81392581e1790d4fbc6eff919815088d" ];
|
||||
#endif
|
||||
#if ADS_ENABLED
|
||||
// start 3rd party SDKs and custom managers
|
||||
[GADMobileAds.sharedInstance startWithCompletionHandler:^(GADInitializationStatus *status) {
|
||||
NSLog(@"[AppDelegate] GADMobileAds started with status: %@", status);
|
||||
}];
|
||||
#endif
|
||||
|
||||
[EQNUser defaultUser];
|
||||
[EQNManager defaultManager];
|
||||
@@ -122,7 +124,10 @@
|
||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||
{
|
||||
NSString *token = [self stringWithDeviceToken:deviceToken];
|
||||
NSLog(@"[DEBUG] push token: %@", token);
|
||||
[[NSUserDefaults standardUserDefaults] setObject:token forKey:EQNUserDefaultPushToken];
|
||||
|
||||
FIRMessaging.messaging.APNSToken = deviceToken;
|
||||
}
|
||||
|
||||
- (NSString *)stringWithDeviceToken:(NSData *)deviceToken
|
||||
@@ -178,9 +183,9 @@
|
||||
EQNTabBarSection section = EQNTabBarSectionAllerte;
|
||||
if ([userInfo[@"type"] isEqualToString:@"eqn"]) {
|
||||
NSDate *dataRicezione = [NSDate date];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:dataRicezione forKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:dataRicezione forKey:EQNUserDefaultRealTimeAlertDate];
|
||||
|
||||
[EQNUtility storeDictionary:userInfo toUserDefaultForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
[EQNUtility storeDictionary:userInfo toUserDefaultForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
section = EQNTabBarSectionAllerte;
|
||||
} else if([userInfo[@"type"] isEqualToString:@"manual"]) {
|
||||
section = EQNTabBarSectionSegnalazioni;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -24,12 +24,12 @@
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="Dzo-29-2FJ" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="LUF-7j-Kmc"/>
|
||||
<constraint firstItem="Dzo-29-2FJ" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="MuU-xU-Ic2"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@@ -38,6 +38,6 @@
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="eq_icon" width="166" height="166"/>
|
||||
<image name="eq_icon" width="200" height="200"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
@import StoreKit;
|
||||
@import SafariServices;
|
||||
@import CoreLocation;
|
||||
@import GoogleMobileAds;
|
||||
|
||||
@interface AllerteViewController () <UITableViewDelegate, UITableViewDataSource>
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *expandeCollapseButton;
|
||||
@property (weak, nonatomic) IBOutlet UITableView *tableView;
|
||||
@property (strong, nonatomic) NSMutableArray *tableItems;
|
||||
@property (nonatomic) BOOL isNotificaAttiva;
|
||||
@@ -36,7 +36,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
AllerteTableRowAllertePassate,
|
||||
AllerteTableRowReteSmartphone,
|
||||
AllerteTableRowServizioPriorita,
|
||||
AllerteTableRowVersionePro,
|
||||
AllerteTableRowVersionePro, // non più visualizzata con passaggio dell'app a pagamento
|
||||
AllerteTableRowDatiPosizione
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
- (void)setupUI
|
||||
{
|
||||
self.title = [NSLocalizedString(@"tab_network", nil) capitalizedString];
|
||||
self.tableView.estimatedRowHeight = 200.0;
|
||||
self.tableView.estimatedRowHeight = 600.0;
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
}
|
||||
|
||||
@@ -112,37 +112,61 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
{
|
||||
[super refreshUI];
|
||||
|
||||
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
if (date) {
|
||||
if ([EQNUtility getDifferenceMinute:date] < TEMPO_VISUALIZZAZIONE_NOTIFICA)
|
||||
self.isNotificaAttiva = YES;
|
||||
else{
|
||||
self.isNotificaAttiva = NO;
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
// `AllerteTableRowReteSmartphone` and `AllerteTableRowDatiPosizione` are hidden bu default, user can show them
|
||||
BOOL showAllCards = [[NSUserDefaults standardUserDefaults] boolForKey:EQNUserDefaultKeyAlertsShowAllCards];
|
||||
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) {
|
||||
self.isNotificaAttiva = YES;
|
||||
|
||||
// mostriamo la schermata solo se il countdown non è a zero
|
||||
EQNRealtimeAlert *alert = [[EQNRealtimeAlert alloc] initWithNotification:info];
|
||||
if (alert != nil && ![alert isCountdownExpired]) {
|
||||
RealtimeAlertViewController *controller = [[RealtimeAlertViewController alloc] initWithAlert:alert];
|
||||
if (@available(iOS 13.0, *)) {
|
||||
controller.modalInPresentation = YES;
|
||||
}
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
}
|
||||
} else {
|
||||
[self resetRealtimeAlert];
|
||||
}
|
||||
|
||||
[self.tableItems removeAllObjects];
|
||||
|
||||
// rows always visible
|
||||
[self.tableItems addObjectsFromArray:@[ @(AllerteTableRowSismiRilevati), @(AllerteTableRowAllertePassate), @(AllerteTableRowServizioPriorita)]];
|
||||
|
||||
if (showAllCards) {
|
||||
[self.tableItems addObject:@(AllerteTableRowReteSmartphone)];
|
||||
}
|
||||
// check if locations is enabled
|
||||
if (CLLocationManager.authorizationStatus != kCLAuthorizationStatusAuthorizedAlways) {
|
||||
[self.tableItems addObject:@(AllerteTableRowLocationPermission)];
|
||||
}
|
||||
// always visible rows
|
||||
[self.tableItems addObjectsFromArray:@[ @(AllerteTableRowSismiRilevati), @(AllerteTableRowAllertePassate), @(AllerteTableRowReteSmartphone), @(AllerteTableRowServizioPriorita)]];
|
||||
// pro cell visible only if user hasn't already bought the app
|
||||
if ([EQNPurchaseUtility isProVersionEnabled] == NO) {
|
||||
[self.tableItems addObject:@(AllerteTableRowVersionePro)];
|
||||
}
|
||||
|
||||
// location data visible only if last position is known
|
||||
if ([EQNUser defaultUser].lastPosition != nil) {
|
||||
if ([EQNUser defaultUser].lastPosition != nil && showAllCards) {
|
||||
[self.tableItems addObject:@(AllerteTableRowDatiPosizione)];
|
||||
}
|
||||
|
||||
// sort items based on enum position
|
||||
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
|
||||
[self.tableItems sortUsingDescriptors:@[sorter]];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)resetRealtimeAlert
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertDate];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
self.isNotificaAttiva = NO;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)refreshDataTapped:(id)sender
|
||||
@@ -150,13 +174,19 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
[[EQNManager defaultManager] sincronizza];
|
||||
}
|
||||
|
||||
- (IBAction)collapseExpandTapped:(id)sender
|
||||
{
|
||||
// toggle saved value
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
BOOL showAll = [defaults boolForKey:EQNUserDefaultKeyAlertsShowAllCards];
|
||||
[defaults setBool:!showAll forKey:EQNUserDefaultKeyAlertsShowAllCards];
|
||||
|
||||
[self refreshUI];
|
||||
}
|
||||
|
||||
- (void)actionCloseNotification
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
self.isNotificaAttiva = NO;
|
||||
|
||||
[self resetRealtimeAlert];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
@@ -239,7 +269,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
|
||||
} else if (tableRow == AllerteTableRowSismiRilevati) {
|
||||
if (self.isNotificaAttiva) {
|
||||
AlertsSeismicNotificationExpandedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SeismicNotificationExpandedCell" forIndexPath:indexPath];
|
||||
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA];
|
||||
NSDictionary *info = [EQNUtility loadDictionaryFromUserDefaultsForKey:EQNUserDefaultRealTimeAlertPayload];
|
||||
cell.notification = info;
|
||||
|
||||
__weak AllerteViewController *weakSelf = self;
|
||||
|
||||
@@ -15,7 +15,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
|
||||
@objc var notification: [String: Any]? {
|
||||
didSet {
|
||||
startCountdown()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
@@ -64,17 +63,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
descriptionLabel.text = NSLocalizedString("map_smartphone_magnitude", comment: "")
|
||||
}
|
||||
|
||||
private func startCountdown() {
|
||||
guard let notification = notification else { return }
|
||||
|
||||
// calculate the impact timestamp and start a timer for the countdown label
|
||||
if let impactTimestamp = EQNUtility.calculateUserSeismicTimestamp(fromUserInfo: notification) {
|
||||
self.impactTimestamp = impactTimestamp
|
||||
countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdownTimerFired(_:)), userInfo: nil, repeats: true)
|
||||
countdownTimer?.fire()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
// clearn any other previous notifications
|
||||
notificationTitleLabel.text = ""
|
||||
@@ -149,20 +137,6 @@ class AlertsSeismicNotificationExpandedTableViewCell: EQNBaseTableViewCell, MKMa
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func countdownTimerFired(_ sender: Timer) {
|
||||
guard let impactTimestamp = impactTimestamp else { return }
|
||||
|
||||
let now = Date()
|
||||
let difference = lround(max(impactTimestamp.timeIntervalSince(now), 0))
|
||||
waveTimeLabel.text = String(format: NSLocalizedString("alert_wave", comment: ""), difference)
|
||||
|
||||
if difference <= 0 {
|
||||
// stop the countdown
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = nil
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func shareAppTapped(_ sender: UIButton) {
|
||||
onTapShareApp?()
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
#if ADS_ENABLED
|
||||
[self handleAdBanner];
|
||||
#else
|
||||
[self hideAdBanner];
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
@@ -13,6 +13,7 @@ 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!
|
||||
@@ -65,6 +66,7 @@ class PurchaseProVersionViewController: UIViewController {
|
||||
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() {
|
||||
|
||||
@@ -22,6 +22,7 @@ class SubscriptionDetailViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet private weak var containerView: UIView!
|
||||
@IBOutlet private weak var productTitleLabel: UILabel!
|
||||
@IBOutlet private weak var productImageView: UIImageView!
|
||||
@IBOutlet private weak var productDescriptionLabel: UILabel!
|
||||
@@ -43,42 +44,44 @@ class SubscriptionDetailViewController: UIViewController {
|
||||
object: nil)
|
||||
|
||||
updateUI()
|
||||
setupUI()
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupUI() {
|
||||
containerView.eqn_applyShadowAndRoundedCorners()
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
guard let product = product, isViewLoaded else { return }
|
||||
|
||||
productImageView.image = VersioneProProducts.image(for: product.productIdentifier)
|
||||
productTitleLabel.text = product.localizedTitle
|
||||
productDescriptionLabel.text = product.localizedDescription
|
||||
|
||||
var purchaseRecapString = ""
|
||||
var subscriptionDetailsString = ""
|
||||
switch product.productIdentifier {
|
||||
|
||||
case VersioneProProducts.Identifier.Subscription10kMonthly:
|
||||
productImageView.image = UIImage.init(named: "top_10k")
|
||||
case VersioneProProducts.Identifier.Subscription10kMonthly,
|
||||
VersioneProProducts.Identifier.Subscription100kMonthly:
|
||||
purchaseRecapString = "inapp_monthly_payment"
|
||||
|
||||
case VersioneProProducts.Identifier.Subscription100kMonthly:
|
||||
productImageView.image = UIImage.init(named: "top_100k")
|
||||
purchaseRecapString = "inapp_monthly_payment"
|
||||
|
||||
|
||||
case VersioneProProducts.Identifier.Subscription100kYearly, VersioneProProducts.Identifier.Subscription100kYearlyDiscounted:
|
||||
productImageView.image = UIImage.init(named: "top_100k")
|
||||
subscriptionDetailsString = "inapp_detail_description"
|
||||
case VersioneProProducts.Identifier.Subscription100kYearly,
|
||||
VersioneProProducts.Identifier.Subscription100kYearlyDiscounted,
|
||||
VersioneProProducts.Identifier.Subscription10kYearly,
|
||||
VersioneProProducts.Identifier.Subscription10kYearlyDiscounted:
|
||||
purchaseRecapString = "inapp_yearly_payment"
|
||||
|
||||
case VersioneProProducts.Identifier.Subscription10kYearly, VersioneProProducts.Identifier.Subscription10kYearlyDiscounted:
|
||||
productImageView.image = UIImage.init(named: "top_10k")
|
||||
purchaseRecapString = "inapp_yearly_payment"
|
||||
|
||||
subscriptionDetailsString = "inapp_detail_description"
|
||||
case VersioneProProducts.Identifier.Subscription10kPerpetual,
|
||||
VersioneProProducts.Identifier.Subscription100kPerpetual:
|
||||
purchaseRecapString = "inapp_lifetime_payment"
|
||||
subscriptionDetailsString = "inapp_lifetime_detail_description"
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
subscriptionDetailsLabel.text = NSLocalizedString("", comment: "")
|
||||
subscriptionDetailsLabel.text = NSLocalizedString(subscriptionDetailsString, comment: "")
|
||||
openPrivacyButton.setTitle(NSLocalizedString("network_pro_privacy_disclaimer", comment: ""), for: .normal)
|
||||
openTermsButton.setTitle(NSLocalizedString("network_pro_terms_conditions", comment: ""), for: .normal)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
class SubscriptionProductTableViewCell: EQNInsetTableViewCell {
|
||||
class SubscriptionProductTableViewCell: UITableViewCell {
|
||||
|
||||
var product: SKProduct? {
|
||||
didSet {
|
||||
@@ -28,22 +28,38 @@ class SubscriptionProductTableViewCell: EQNInsetTableViewCell {
|
||||
@IBOutlet private weak var productInfoLabel: UILabel!
|
||||
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
// force an inset to have the same style of EQNBaseTableViewCell
|
||||
override var frame: CGRect {
|
||||
get {
|
||||
return super.frame
|
||||
}
|
||||
set (newFrame) {
|
||||
let inset: CGFloat = 8
|
||||
var frame = newFrame
|
||||
frame.origin.x += inset
|
||||
frame.size.width -= 2 * inset
|
||||
super.frame = frame
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateUI() {
|
||||
guard let product = product else { return }
|
||||
|
||||
productImageView.image = imageForProductIdentifier(product.productIdentifier)
|
||||
productImageView.image = VersioneProProducts.image(for: product.productIdentifier)
|
||||
productTitleLabel.text = product.localizedTitle
|
||||
productDescriptionLabel?.text = product.localizedDescription
|
||||
|
||||
let infoKey = is100kSubscriptionForProductIdentifier(product.productIdentifier) ? "inapp_available_100k" : "inapp_available_10k"
|
||||
let infoKey = VersioneProProducts.is100kSubscription(for: product.productIdentifier) ? "inapp_available_100k" : "inapp_available_10k"
|
||||
let counter = availability(for: product.productIdentifier)
|
||||
productInfoLabel.text = String(format: NSLocalizedString(infoKey, comment: ""), counter)
|
||||
}
|
||||
|
||||
private func availability(for productIdentifier: String) -> Int {
|
||||
if is100kSubscriptionForProductIdentifier(productIdentifier) {
|
||||
if VersioneProProducts.is100kSubscription(for: productIdentifier) {
|
||||
return availability?.top100kAvailable ?? 0
|
||||
}
|
||||
return availability?.top10kAvailable ?? 0
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
class SubscriptionsActiveTableViewCell: EQNInsetTableViewCell {
|
||||
class SubscriptionsActiveTableViewCell: EQNBaseTableViewCell {
|
||||
|
||||
var product: SKProduct? {
|
||||
didSet {
|
||||
@@ -40,7 +40,7 @@ class SubscriptionsActiveTableViewCell: EQNInsetTableViewCell {
|
||||
if let productIdentifier = product?.productIdentifier {
|
||||
noSubscriptionsLabel.isHidden = true
|
||||
activeSubscriptionImageView.isHidden = false
|
||||
activeSubscriptionImageView.image = imageForProductIdentifier(productIdentifier)
|
||||
activeSubscriptionImageView.image = VersioneProProducts.image(for: productIdentifier)
|
||||
} else {
|
||||
noSubscriptionsLabel.isHidden = false
|
||||
activeSubscriptionImageView.isHidden = true
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class SubscriptionsDescriptionTableViewCell: EQNInsetTableViewCell {
|
||||
class SubscriptionsDescriptionTableViewCell: EQNBaseTableViewCell {
|
||||
|
||||
@IBOutlet private weak var headerLabel: UILabel!
|
||||
@IBOutlet private weak var descriptionLabel: UILabel!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class SubscriptionsHeaderTableViewCell: EQNInsetTableViewCell {
|
||||
class SubscriptionsHeaderTableViewCell: UITableViewCell {
|
||||
|
||||
var isLoading = false {
|
||||
didSet {
|
||||
@@ -25,13 +25,6 @@ class SubscriptionsHeaderTableViewCell: EQNInsetTableViewCell {
|
||||
@IBOutlet private weak var headerTitleLabel: UILabel!
|
||||
@IBOutlet private weak var loadingActivityIndicator: UIActivityIndicatorView!
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateUI() {
|
||||
|
||||
@@ -21,11 +21,13 @@ class SubscriptionsViewController: UITableViewController {
|
||||
case description
|
||||
case monthly
|
||||
case yearly
|
||||
case perpetual
|
||||
|
||||
var sectionTitle: String? {
|
||||
switch self {
|
||||
case .monthly: return NSLocalizedString("inapp_monthly_subscriptions", comment: "")
|
||||
case .yearly: return NSLocalizedString("inapp_yearly_subscriptions", comment: "")
|
||||
case .perpetual: return NSLocalizedString("inapp_lifetime_subscriptions", comment: "")
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
@@ -36,6 +38,7 @@ class SubscriptionsViewController: UITableViewController {
|
||||
private var allProducts = [SKProduct]()
|
||||
private var monthlyProducts = [SKProduct]()
|
||||
private var yearlyProducts = [SKProduct]()
|
||||
private var perpetualProducts = [SKProduct]()
|
||||
/// Product already bought by the user
|
||||
private var subscribedProduct: SKProduct?
|
||||
/// Availability for subscriptions
|
||||
@@ -105,6 +108,7 @@ class SubscriptionsViewController: UITableViewController {
|
||||
private func updateUI() {
|
||||
monthlyProducts.removeAll()
|
||||
yearlyProducts.removeAll()
|
||||
perpetualProducts.removeAll()
|
||||
|
||||
// creates list to show
|
||||
let isDiscountAvailable = checkDiscountPrice()
|
||||
@@ -127,6 +131,11 @@ class SubscriptionsViewController: UITableViewController {
|
||||
yearlyProducts.append(product)
|
||||
}
|
||||
}
|
||||
// perpetual scribuscriptions doesn't have discounted version
|
||||
if product.productIdentifier == VersioneProProducts.Identifier.Subscription10kPerpetual ||
|
||||
product.productIdentifier == VersioneProProducts.Identifier.Subscription100kPerpetual {
|
||||
perpetualProducts.append(product)
|
||||
}
|
||||
}
|
||||
|
||||
tableView.reloadData()
|
||||
@@ -142,7 +151,7 @@ class SubscriptionsViewController: UITableViewController {
|
||||
|
||||
let purchased = products.filter { (product) -> Bool in
|
||||
let isPurchased = VersioneProProducts.store.isProductPurchased(product.productIdentifier)
|
||||
let isSubscription = VersioneProProducts.Identifier.isSubscription(for: product.productIdentifier)
|
||||
let isSubscription = VersioneProProducts.isSubscription(for: product.productIdentifier)
|
||||
return isPurchased && isSubscription
|
||||
}
|
||||
self.subscribedProduct = purchased.first
|
||||
@@ -231,7 +240,7 @@ class SubscriptionsViewController: UITableViewController {
|
||||
if tableSection.sectionTitle != nil {
|
||||
return 50
|
||||
}
|
||||
return 10
|
||||
return 0
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
@@ -239,8 +248,10 @@ class SubscriptionsViewController: UITableViewController {
|
||||
switch tableSection {
|
||||
case .active: return 1
|
||||
case .description: return 1
|
||||
case .monthly: return monthlyProducts.count
|
||||
case .yearly: return yearlyProducts.count
|
||||
case .monthly,
|
||||
.yearly,
|
||||
.perpetual:
|
||||
return availableProducts(for: tableSection).count
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +263,33 @@ class SubscriptionsViewController: UITableViewController {
|
||||
}
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
let tableSection = sections[indexPath.section]
|
||||
if tableSection == .active || tableSection == .description {
|
||||
return
|
||||
}
|
||||
|
||||
// add round borders to first and last row in products cells
|
||||
let cornerRadius = AppTheme.shared.cardCornerRadius
|
||||
var corners: UIRectCorner = []
|
||||
|
||||
if indexPath.row == 0 {
|
||||
corners.update(with: .topLeft)
|
||||
corners.update(with: .topRight)
|
||||
}
|
||||
|
||||
if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
|
||||
corners.update(with: .bottomLeft)
|
||||
corners.update(with: .bottomRight)
|
||||
}
|
||||
|
||||
let maskLayer = CAShapeLayer()
|
||||
maskLayer.path = UIBezierPath(roundedRect: cell.bounds,
|
||||
byRoundingCorners: corners,
|
||||
cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)).cgPath
|
||||
cell.layer.mask = maskLayer
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let tableSection = sections[indexPath.section]
|
||||
@@ -265,7 +303,7 @@ class SubscriptionsViewController: UITableViewController {
|
||||
return cell
|
||||
}
|
||||
|
||||
let products = tableSection == .monthly ? monthlyProducts : yearlyProducts
|
||||
let products = availableProducts(for: tableSection)
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "SubscriptionCell", for: indexPath) as! SubscriptionProductTableViewCell
|
||||
cell.product = products[indexPath.row]
|
||||
cell.availability = availability
|
||||
@@ -276,11 +314,22 @@ class SubscriptionsViewController: UITableViewController {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
|
||||
let tableSection = sections[indexPath.section]
|
||||
if tableSection == .monthly || tableSection == .yearly {
|
||||
let products = tableSection == .monthly ? monthlyProducts : yearlyProducts
|
||||
let products = availableProducts(for: tableSection)
|
||||
if !products.isEmpty {
|
||||
performSegue(withIdentifier: Self.SegueIdentifierSubscriptionDetail, sender: products[indexPath.row])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func availableProducts(for section: TableSection) -> [SKProduct] {
|
||||
switch section {
|
||||
case .monthly: return monthlyProducts
|
||||
case .yearly: return yearlyProducts
|
||||
case .perpetual: return perpetualProducts
|
||||
default: return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SubscriptionsViewController: StoryboardInitializable {
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// RealtimeAlertView.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 15/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
|
||||
class RealtimeAlertView: UIView {
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .title2)
|
||||
label.text = NSLocalizedString("app_name", comment: "")
|
||||
return label
|
||||
}()
|
||||
|
||||
let descriptionLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
let waveTimeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .title3)
|
||||
label.textColor = AppTheme.Colors.red
|
||||
label.text = String(format: NSLocalizedString("alert_wave", comment: ""), 0)
|
||||
label.textAlignment = .center
|
||||
label.isHidden = true
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var mapView: MKMapView = {
|
||||
let map = MKMapView()
|
||||
map.translatesAutoresizingMaskIntoConstraints = false
|
||||
map.delegate = self
|
||||
map.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
||||
map.showsUserLocation = true
|
||||
return map
|
||||
}()
|
||||
|
||||
let closeButton: EQNBlurredCloseButton = {
|
||||
let button = EQNBlurredCloseButton()
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.setTitleColor(.darkGray, for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: .zero)
|
||||
configureUI()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func configureUI() {
|
||||
backgroundColor = AppTheme.Colors.lightGray
|
||||
|
||||
addSubview(closeButton)
|
||||
addSubview(titleLabel)
|
||||
addSubview(descriptionLabel)
|
||||
addSubview(waveTimeLabel)
|
||||
addSubview(mapView)
|
||||
|
||||
closeButton.addDefaultConstraint(to: self)
|
||||
|
||||
titleLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
titleLabel.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor, constant: -10.0).isActive = true
|
||||
titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 10.0).isActive = true
|
||||
|
||||
descriptionLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
descriptionLabel.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
|
||||
waveTimeLabel.leadingAnchor.constraint(equalTo: descriptionLabel.leadingAnchor).isActive = true
|
||||
waveTimeLabel.trailingAnchor.constraint(equalTo: descriptionLabel.trailingAnchor).isActive = true
|
||||
waveTimeLabel.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
|
||||
mapView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||
mapView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
||||
mapView.topAnchor.constraint(equalTo: waveTimeLabel.bottomAnchor, constant: 20.0).isActive = true
|
||||
mapView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func addMapCircle(
|
||||
center: CLLocationCoordinate2D,
|
||||
radius: CLLocationDistance,
|
||||
overlayId: String
|
||||
) {
|
||||
// remove any other existing overlays
|
||||
let overlays = mapView.overlays.filter { $0.title == overlayId }
|
||||
mapView.removeOverlays(overlays)
|
||||
|
||||
// add new overlay
|
||||
let circle = MKCircle(center: center, radius: radius)
|
||||
circle.title = overlayId
|
||||
mapView.addOverlay(circle)
|
||||
}
|
||||
|
||||
func addMapLine(
|
||||
coordinates: [CLLocationCoordinate2D]
|
||||
) {
|
||||
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
|
||||
mapView.addOverlay(polyline)
|
||||
}
|
||||
|
||||
func addMapAnnotation(
|
||||
title: String = "",
|
||||
center: CLLocationCoordinate2D,
|
||||
intensity: Int
|
||||
) {
|
||||
let annotation = EQNMapAnnotationPastquake(title: title, coordinate: center, intensity: intensity)
|
||||
mapView.addAnnotation(annotation)
|
||||
}
|
||||
}
|
||||
|
||||
extension RealtimeAlertView: MKMapViewDelegate {
|
||||
|
||||
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
switch overlay {
|
||||
case let circle as MKCircle:
|
||||
let circleRenderer = MKCircleRenderer(overlay: circle)
|
||||
circleRenderer.strokeColor = AppTheme.Colors.red
|
||||
circleRenderer.fillColor = AppTheme.Colors.red.withAlphaComponent(0.2)
|
||||
circleRenderer.lineWidth = 3.0
|
||||
return circleRenderer
|
||||
case let polyline as MKPolyline:
|
||||
let polylineRenderer = MKPolylineRenderer(polyline: polyline)
|
||||
polylineRenderer.strokeColor = .blue
|
||||
polylineRenderer.lineWidth = 2.0
|
||||
return polylineRenderer
|
||||
default:
|
||||
return MKOverlayRenderer(overlay: overlay)
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||
guard let annotation = annotation as? EQNMapAnnotationPastquake else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
|
||||
annotationView.image = annotation.image
|
||||
annotationView.title = annotation.title
|
||||
return annotationView
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
//
|
||||
// RealtimeAlertViewController.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 15/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
|
||||
class RealtimeAlertViewController: UIViewController, MKMapViewDelegate {
|
||||
|
||||
@objc var onClose: () -> Void = {}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
private let notificationView = RealtimeAlertView()
|
||||
/// Alert to display
|
||||
private let realtimeAlert: EQNRealtimeAlert
|
||||
/// Timer to constantly update countdown label
|
||||
private var countdownTimer: Timer?
|
||||
/// Refresh time for wave animation
|
||||
private let waveAnimationRefreshRate = 0.1
|
||||
/// Current radius of the wave animation on the map
|
||||
private var waveAnimationCurrentRadius: CLLocationDistance = 0
|
||||
private var waveAnimationVelocity: Double = 1_000
|
||||
/// Timer to simulate animation for the wave
|
||||
private var waveAnimationTimer: Timer?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
@objc
|
||||
init(alert: EQNRealtimeAlert) {
|
||||
self.realtimeAlert = alert
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.waveAnimationCurrentRadius = currentWavePosition()
|
||||
self.waveAnimationVelocity = evaluateWaveAnimationVelocity()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
// importante togliere il delegato, altrimenti causa crash
|
||||
notificationView.mapView.delegate = nil
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func loadView() {
|
||||
view = notificationView
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
configureUI()
|
||||
updateUI()
|
||||
|
||||
startCountdown()
|
||||
startWaveAnimation()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func configureUI() {
|
||||
notificationView.closeButton.addTarget(self, action: #selector(onTapClose(_:)), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
notificationView.descriptionLabel.text = realtimeAlert.title
|
||||
|
||||
// update title with distance from earthquake
|
||||
let distanceRound = Int(round(realtimeAlert.distanceFromUser() / 1_000))
|
||||
notificationView.descriptionLabel.text = (notificationView.descriptionLabel.text ?? "")
|
||||
+ ".\n"
|
||||
+ String(format: NSLocalizedString("timer_message2_other", comment: ""), distanceRound)
|
||||
|
||||
// center map on the earthquake coordinate
|
||||
let span = MKCoordinateSpan(latitudeDelta: 10.5, longitudeDelta: 10.5)
|
||||
let region = MKCoordinateRegion(center: realtimeAlert.coordinate.coordinate, span: span)
|
||||
notificationView.mapView.setCenter(realtimeAlert.coordinate.coordinate, animated: false)
|
||||
notificationView.mapView.setRegion(region, animated: true)
|
||||
|
||||
// aggiungiamo annotation con epicentro sisma
|
||||
notificationView.addMapAnnotation(center: realtimeAlert.coordinate.coordinate, intensity: realtimeAlert.intensity)
|
||||
|
||||
// simuliamo animazione dell'onda sismica
|
||||
notificationView.addMapCircle(center: realtimeAlert.coordinate.coordinate, radius: waveAnimationCurrentRadius, overlayId: "wave_animation")
|
||||
|
||||
// aggiungiamo un segmento tra la posizione del sisma e quella dell'utente
|
||||
if let lastPosition = EQNUser.default().lastPosition {
|
||||
notificationView.addMapLine(coordinates: [realtimeAlert.coordinate.coordinate, lastPosition.coordinate])
|
||||
}
|
||||
}
|
||||
|
||||
private func startCountdown() {
|
||||
// show countdown only if time is less than 300 seconds
|
||||
if realtimeAlert.currentCountdown() < 300 {
|
||||
// start a timer for the countdown label
|
||||
notificationView.waveTimeLabel.isHidden = false
|
||||
countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdownTimerFired(_:)), userInfo: nil, repeats: true)
|
||||
countdownTimer?.fire()
|
||||
}
|
||||
}
|
||||
|
||||
private func startWaveAnimation() {
|
||||
waveAnimationTimer = Timer.scheduledTimer(timeInterval: waveAnimationRefreshRate, target: self, selector: #selector(mapWaveAnimationFired(_:)), userInfo: nil, repeats: true)
|
||||
waveAnimationTimer?.fire()
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
@objc private func onTapClose(_ sender: UIButton) {
|
||||
// invalidiamo i timer, altri
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = nil
|
||||
waveAnimationTimer?.invalidate()
|
||||
waveAnimationTimer = nil
|
||||
|
||||
onClose()
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Timer
|
||||
|
||||
@objc private func countdownTimerFired(_ sender: Timer) {
|
||||
let countdown = realtimeAlert.currentCountdown()
|
||||
notificationView.waveTimeLabel.text = String(format: NSLocalizedString("alert_wave", comment: ""), countdown)
|
||||
|
||||
if countdown <= 0 {
|
||||
// stop the countdown
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func mapWaveAnimationFired(_ sender: Timer) {
|
||||
waveAnimationCurrentRadius += waveAnimationVelocity
|
||||
notificationView.addMapCircle(center: realtimeAlert.coordinate.coordinate, radius: waveAnimationCurrentRadius, overlayId: "wave_animation")
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// Evaluate current position for the wave
|
||||
/// Used to define initial position for the wave circle
|
||||
/// - Returns: Distance of the wave from the original earthquake point
|
||||
private func currentWavePosition() -> Double {
|
||||
// distanza tra utente e terremoto
|
||||
let distance = realtimeAlert.distanceFromUser()
|
||||
|
||||
// calcoliamo la distanza rimanente da mostrare, perchè la schermata potrebbe anche essere aperta in ritardo
|
||||
let remainingDistance = realtimeAlert.waveSpeed * Double(realtimeAlert.currentCountdown())
|
||||
return distance - remainingDistance
|
||||
}
|
||||
|
||||
/// Evaluate wave velocity based on push notification data
|
||||
/// - Returns: Wave velocity, used for animation
|
||||
private func evaluateWaveAnimationVelocity() -> Double {
|
||||
let velocity = realtimeAlert.waveSpeed
|
||||
return velocity * waveAnimationRefreshRate
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
import MapKit
|
||||
import CoreLocation
|
||||
|
||||
protocol SeismicNetworkTableViewCellDelegate: class {
|
||||
protocol SeismicNetworkTableViewCellDelegate: AnyObject {
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell)
|
||||
@@ -90,7 +90,7 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = UIFont.preferredFont(for: .title2, weight: .semibold)
|
||||
label.numberOfLines = 2
|
||||
label.numberOfLines = 3
|
||||
return label
|
||||
}()
|
||||
|
||||
@@ -256,7 +256,9 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
titleImageView.widthAnchor.constraint(equalTo: titleImageView.heightAnchor).isActive = true
|
||||
networkLabel.heightAnchor.constraint(equalToConstant: 34.0).isActive = true
|
||||
networkLabel.setContentHuggingPriority(.init(800), for: .horizontal)
|
||||
networkLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||
placeLabel.setContentHuggingPriority(.init(200), for: .horizontal)
|
||||
placeLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
shareButton.widthAnchor.constraint(equalToConstant: titleComponentsHeight).isActive = true
|
||||
shareButton.widthAnchor.constraint(equalTo: shareButton.heightAnchor).isActive = true
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc protocol SeismicFiltersViewControllerDelegate: class {
|
||||
protocol SeismicFiltersViewControllerDelegate: AnyObject {
|
||||
func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
case modificaImpostazioni
|
||||
}
|
||||
|
||||
@objc weak var delegate: SeismicFiltersViewControllerDelegate?
|
||||
weak var delegate: SeismicFiltersViewControllerDelegate?
|
||||
/// Tells if delegate needs to redownload data when filter is dismissed
|
||||
@objc private(set) var needsDataUpdate = false
|
||||
|
||||
@@ -66,7 +66,8 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
super.viewDidLoad()
|
||||
|
||||
setupUI()
|
||||
updateUI()
|
||||
loadDataSource()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
@@ -83,7 +84,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
closeButton.setLocalizedTitle(key: "official_close", uppercased: false)
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
private func loadDataSource() {
|
||||
currentMagnitudoMinima = EQNData.magitudoDebole(for: EQNSeismic.shared.magnitudoMinima)
|
||||
if initialMagnitudoMinima == nil {
|
||||
initialMagnitudoMinima = currentMagnitudoMinima
|
||||
@@ -97,7 +98,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
initialQualsiasiMagnitudo = currentSismiQualsiasiMagnitudo
|
||||
}
|
||||
currentModificaImpostazioni = EQNSeismic.shared.modificaImpostazioniAbilitato
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
// MARK: - Table view delegate and data source
|
||||
@@ -111,7 +111,7 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
|
||||
switch setting.type {
|
||||
case .slider:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: SettingSliderTableViewCell.Identifier, for: indexPath) as! SettingSliderTableViewCell
|
||||
let cell = SettingSliderTableViewCell(style: .default, reuseIdentifier: nil)
|
||||
cell.titleLabel.text = setting.displayTitle
|
||||
|
||||
if indexPath.row == RowIdentifier.magnitudoMinima.rawValue {
|
||||
@@ -120,7 +120,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentMagnitudoMinima = value
|
||||
EQNSeismic.shared.magnitudoMinima = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
cell.dragEnded = { [unowned self] in
|
||||
showWarningAlertIfNeeded(for: currentMagnitudoMinima)
|
||||
@@ -131,7 +130,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentDistanzaMassima = value
|
||||
EQNSeismic.shared.distanzaMassima = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.periodoTemporale.rawValue {
|
||||
cell.configureSlider(with: dataSourcePeriodoTemporale, current: currentPeriodoTemporale)
|
||||
@@ -139,7 +137,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentPeriodoTemporale = value
|
||||
EQNSeismic.shared.periodoTemporale = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.sismiFortiDistanza.rawValue {
|
||||
cell.isDisabled = !currentSismiFortiAbilitati
|
||||
@@ -148,13 +145,12 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiFortiDistanza = value
|
||||
EQNSeismic.shared.sismiFortiMagnitudo = value.value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
return cell
|
||||
case .enable:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: SettingEnableTableViewCell.Identifier, for: indexPath) as! SettingEnableTableViewCell
|
||||
let cell = SettingEnableTableViewCell(style: .default, reuseIdentifier: nil)
|
||||
cell.titleLabel.text = setting.displayTitle
|
||||
cell.detailTextLabel?.text = setting.subtitle
|
||||
|
||||
@@ -164,7 +160,9 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiFortiAbilitati = value
|
||||
EQNSeismic.shared.sismiFortiAbilitati = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
|
||||
loadDataSource()
|
||||
tableView.reloadData()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.sismiQualsiasiMagnitudo.rawValue {
|
||||
cell.toggleSwitch.isOn = currentSismiQualsiasiMagnitudo
|
||||
@@ -172,7 +170,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentSismiQualsiasiMagnitudo = value
|
||||
EQNSeismic.shared.sismiQualsiasiAbilitati = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
} else if indexPath.row == RowIdentifier.modificaImpostazioni.rawValue {
|
||||
cell.toggleSwitch.isOn = currentModificaImpostazioni
|
||||
@@ -180,7 +177,6 @@ class SeismicFiltersViewController: UIViewController, UITableViewDelegate, UITab
|
||||
currentModificaImpostazioni = value
|
||||
EQNSeismic.shared.modificaImpostazioniAbilitato = value
|
||||
EQNSeismic.shared.saveFilters()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol SeismicCardSettingsViewControllerDelegate: class {
|
||||
protocol SeismicCardSettingsViewControllerDelegate: AnyObject {
|
||||
func seismicCardSettingsDidComplete(_ controller: SeismicCardSettingsViewController)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
protocol SeismicNetworksMapDetailViewControllerDelegate: class {
|
||||
protocol SeismicNetworksMapDetailViewControllerDelegate: AnyObject {
|
||||
func seismicNetworksMapDetailControllerWillUpdateData(_ controller: SeismicNetworksMapDetailViewController, needsDataUpdate: Bool)
|
||||
}
|
||||
|
||||
|
||||
@@ -155,10 +155,12 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
let filteredSeismics = EQNSeismic.shared.filterSeismicList(allSeismics ?? [])
|
||||
rows = filteredSeismics.map { .seismic($0) }
|
||||
|
||||
#if ADS_ENABLED
|
||||
// if is not a pro user, show an advertise
|
||||
if !EQNPurchaseUtility.isProVersionEnabled() {
|
||||
loadAd()
|
||||
}
|
||||
#endif
|
||||
|
||||
// if a map detail is presented, update its data
|
||||
if let mapController = currentMapController {
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
import UIKit
|
||||
|
||||
|
||||
@objc protocol SeismicSettingsNetworksViewControllerDelegate: class {
|
||||
protocol SeismicSettingsNetworksViewControllerDelegate: AnyObject {
|
||||
func seismicSettingsNetworksControllerDidComplete(_ controller: SeismicSettingsNetworksViewController)
|
||||
}
|
||||
|
||||
class SeismicSettingsNetworksViewController: UITableViewController {
|
||||
|
||||
@objc weak var delegate: SeismicSettingsNetworksViewControllerDelegate?
|
||||
weak var delegate: SeismicSettingsNetworksViewControllerDelegate?
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@@ -86,7 +86,12 @@ class SeismicSettingsNetworksViewController: UITableViewController {
|
||||
savedNetworks.append(network.acronym)
|
||||
}
|
||||
|
||||
tableView.reloadRows(at: [indexPath], with: .automatic)
|
||||
// reload all rows with the given acronym
|
||||
let indexes = networks
|
||||
.enumerated()
|
||||
.filter { $0.element.acronym == network.acronym }
|
||||
.map { IndexPath(row: $0.offset, section: 0) }
|
||||
tableView.reloadRows(at: indexes, with: .automatic)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objc protocol SeismicSettingsViewControllerDelegate: class {
|
||||
protocol SeismicSettingsViewControllerDelegate: AnyObject {
|
||||
func seismicSettingsControllerDidComplete(_ controller: SeismicSettingsViewController)
|
||||
func seismicSettingsControllerWillOpenProviders(_ controller: SeismicSettingsViewController)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import Foundation
|
||||
|
||||
class SeismicSettingsViewController: UIViewController {
|
||||
|
||||
@objc weak var delegate: SeismicSettingsViewControllerDelegate?
|
||||
weak var delegate: SeismicSettingsViewControllerDelegate?
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
|
||||
@@ -89,8 +89,6 @@ class SettingDateTableViewCell: UITableViewCell {
|
||||
// MARK: - Private
|
||||
|
||||
private func setupUI() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
stackView.addArrangedSubview(titleLabel)
|
||||
stackView.addArrangedSubview(valuesLabel)
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ class SettingEnableTableViewCell: UITableViewCell {
|
||||
|
||||
private func setupUI() {
|
||||
selectionStyle = .none
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
@@ -54,8 +54,6 @@ class SettingMultivaluesTableViewCell: UITableViewCell {
|
||||
// MARK: - Private
|
||||
|
||||
private func setupUI() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.axis = .vertical
|
||||
|
||||
@@ -55,7 +55,6 @@ class SettingSegmentedTableViewCell: UITableViewCell {
|
||||
|
||||
private func setupUI() {
|
||||
selectionStyle = .none
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
@@ -66,7 +66,6 @@ class SettingSliderTableViewCell: UITableViewCell {
|
||||
|
||||
private func setupUI() {
|
||||
selectionStyle = .none
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -99,6 +98,12 @@ class SettingSliderTableViewCell: UITableViewCell {
|
||||
let index = Int(sender.value)
|
||||
let item = items[index]
|
||||
|
||||
// make slider with step values
|
||||
let step: Float = 1
|
||||
let roundedValue = round(sender.value / step) * step
|
||||
sender.value = roundedValue
|
||||
|
||||
// update value
|
||||
valueLabel.text = item.display
|
||||
valueChanged?(item)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,8 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
self.dataSourceSismi = [EQNData seismicToNotify];
|
||||
self.dataSourceRaggioSisma = [EQNData raggioSismi];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@@ -94,7 +95,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
[self.tableView registerClass:[SettingDateTableViewCell class] forCellReuseIdentifier:SettingDateTableViewCell.Identifier];
|
||||
}
|
||||
|
||||
- (void)updateUI
|
||||
- (void)loadDataSource
|
||||
{
|
||||
self.notificationEnabled = [EQNAllertaSismica sharedInstance].isAbilitato;
|
||||
self.criticalAlertsEnabled = [EQNAllertaSismica sharedInstance].isCriticalAlertsEnabled;
|
||||
@@ -120,8 +121,6 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
self.currentEndTime = endTime;
|
||||
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
|
||||
@@ -262,35 +261,40 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
{
|
||||
[EQNAllertaSismica sharedInstance].sismiDaNotificare = seismic.value;
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
[self updateUI];
|
||||
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateLowSeismicRadius:(EQNGenericValue *)radius
|
||||
{
|
||||
[EQNAllertaSismica sharedInstance].raggioSismiLievi = radius.value;
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
[self updateUI];
|
||||
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateStrongSeismicRadius:(EQNGenericValue *)radius
|
||||
{
|
||||
[EQNAllertaSismica sharedInstance].raggioSismiForti = radius.value;
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
[self updateUI];
|
||||
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateStartTime:(NSDate *)date
|
||||
{
|
||||
[EQNAllertaSismica sharedInstance].oraioInizio = date;
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
[self updateUI];
|
||||
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateEndTime:(NSDate *)date
|
||||
{
|
||||
[EQNAllertaSismica sharedInstance].orarioFine = date;
|
||||
[[EQNAllertaSismica sharedInstance] saveUserInfo];
|
||||
[self updateUI];
|
||||
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)askForCriticalAlertsPermission
|
||||
|
||||
@@ -62,14 +62,16 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
self.dataSourceRaggioSisma = [EQNData raggioSismi];
|
||||
self.dataSourceMagnitudoForti = [EQNData magitudoForti];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@@ -86,7 +88,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
[self.tableView registerClass:[SettingMultivaluesTableViewCell class] forCellReuseIdentifier:SettingMultivaluesTableViewCell.Identifier];
|
||||
}
|
||||
|
||||
- (void)updateUI
|
||||
- (void)loadDataSource
|
||||
{
|
||||
self.notificationEnabled = [EQNNotificheReteSismiche sharedInstance].isAbilitato;
|
||||
self.notificationNearEarthquakeEnabled = [EQNNotificheReteSismiche sharedInstance].isAbilitaVicini;
|
||||
@@ -110,8 +112,6 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
}
|
||||
|
||||
[[EQNNotificheReteSismiche sharedInstance] saveUserInfo];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
[EQNNotificheReteSismiche sharedInstance].distanzaPosizione = radius.value;
|
||||
[[EQNNotificheReteSismiche sharedInstance] saveUserInfo];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateSeismicEnergy:(EQNGenericValue *)energy
|
||||
@@ -237,7 +237,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
[EQNNotificheReteSismiche sharedInstance].energiaSisma = energy.value;
|
||||
[[EQNNotificheReteSismiche sharedInstance] saveUserInfo];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (void)updateStrongEarthquakeEnergy:(EQNGenericValue *)energy
|
||||
@@ -245,7 +245,7 @@ typedef NS_ENUM(NSInteger, RowIdentifier) {
|
||||
[EQNNotificheReteSismiche sharedInstance].energiaTerremotiForti = energy.value;
|
||||
[[EQNNotificheReteSismiche sharedInstance] saveUserInfo];
|
||||
|
||||
[self updateUI];
|
||||
[self loadDataSource];
|
||||
}
|
||||
|
||||
- (NSString *)stringOfSelectedNetworks
|
||||
|
||||
@@ -66,10 +66,14 @@ static NSString * const EQNServerUrlAlertSimulator = @"https://srv.earthquakenet
|
||||
|
||||
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";
|
||||
|
||||
/// 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
|
||||
@@ -105,6 +109,8 @@ static NSTimeInterval const EQNSeismicDataRefreshInterval = 120.0;
|
||||
static NSTimeInterval const EQNSendReportDelayBetweenMessages = 5.0;
|
||||
/// Tempo di attesa (minuti) per l'invio di due commenti
|
||||
static NSTimeInterval const EQNSendReportDelayBetweenComments = 30.0;
|
||||
/// Tempo (in minuti) entro cui vengono mostrate allerte in tempo reale ricevute
|
||||
static NSTimeInterval const EQNRealtimeAlertExpiration = 480;
|
||||
|
||||
#ifdef DEBUG
|
||||
static NSString * const EQNAdMobAppIdAdaptiveBanner = @"ca-app-pub-3940256099942544/2934735716"; // test
|
||||
@@ -215,11 +221,6 @@ typedef enum : NSInteger {
|
||||
#define NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
|
||||
#define NOTIFICHE_ALLERA_SISMICA_ORA_FINE @"NOTIFICHE_ALLERA_SISMICA_ORA_INIZIO"
|
||||
|
||||
// NOTIFICHE RETE SMARTPHONE
|
||||
#define NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA @"NOTIFICHE_RETE_SMARTPHONE_DATA_NOTIFICA"
|
||||
#define NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA @"NOTIFICHE_RETE_SMARTPHONE_DIZIONARIO_NOTIFICA"
|
||||
#define TEMPO_VISUALIZZAZIONE_NOTIFICA 10800
|
||||
|
||||
|
||||
// FILTRO ENTI
|
||||
#define EQN_MAGNITUDO_MINIMA @"EQN_MAGNITUDO_MINIMA"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// UIView+EQNExtensions.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 23/04/21.
|
||||
// Copyright © 2021 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
extension UIView {
|
||||
|
||||
func eqn_applyShadowAndRoundedCorners() {
|
||||
// rounded corners
|
||||
layer.cornerRadius = AppTheme.shared.cardCornerRadius
|
||||
layer.masksToBounds = false
|
||||
|
||||
// apply a shadow to the current view
|
||||
layer.shadowColor = UIColor.black.cgColor
|
||||
layer.shadowOpacity = 0.5
|
||||
layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
layer.shadowRadius = 2
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,6 @@ import Foundation
|
||||
|
||||
|
||||
@objc
|
||||
protocol EQNCommandProtocol: class {
|
||||
protocol EQNCommandProtocol: AnyObject {
|
||||
@objc func execute()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// EQNRealtimeAlert.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 17/06/22.
|
||||
// Copyright © 2022 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
|
||||
|
||||
@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.eqn_intValue(for: "intensity") ?? 0
|
||||
self.waveSpeed = (notification.eqn_doubleValue(for: "wave_speed") ?? 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.eqn_doubleValue(for: "latitude"),
|
||||
let longitude = notification.eqn_doubleValue(for: "longitude") else {
|
||||
return nil
|
||||
}
|
||||
return CLLocation(latitude: latitude, longitude: longitude)
|
||||
}
|
||||
}
|
||||
@@ -130,14 +130,11 @@
|
||||
|
||||
- (void)inviaPosizioneServer
|
||||
{
|
||||
NSLog(@"URLPosizione %@", [EQNGeneratoreURLServer urlPosizione]);
|
||||
|
||||
[[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[EQNGeneratoreURLServer urlPosizione] richiesta:EQNTipoChiamataPosizione success:^(id result) {
|
||||
|
||||
NSLog(@"inviato");
|
||||
|
||||
} failure:^(NSError *errore) {
|
||||
|
||||
NSLog(@"[EQNUtility] Position saved on server");
|
||||
[self saveUserInfo];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"[EQNUtility] Unable to save position. Error: %@", error.localizedDescription);
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,10 @@
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSData *data = [defaults objectForKey:keyName];
|
||||
if (!data) {
|
||||
NSLog(@"[EQNUtility] No array saved for key '%@'", keyName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
|
||||
@@ -119,6 +123,10 @@
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSData *data = [defaults objectForKey:keyName];
|
||||
if (!data) {
|
||||
NSLog(@"[EQNUtility] No dictionary saved for key '%@'", keyName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
[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.raggioSismiLievi forKey:NOTIFICHE_ALLERA_SISMICA_RAGGIO_SISMI_FORTI];
|
||||
[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];
|
||||
|
||||
@@ -37,40 +37,66 @@ public struct VersioneProProducts {
|
||||
static let Subscription10kMonthly = "com.finazzi.distquake.Abbonamento10k.mensileAutomatico"
|
||||
static let Subscription10kYearly = "com.finazzi.distquake.Abbonamento10k.annualeAutomatico"
|
||||
static let Subscription10kYearlyDiscounted = "com.finazzi.distquake.Abbonamento10k.annualeAutomaticoScontato"
|
||||
static let Subscription10kPerpetual = "com.finazzi.distquake.Abbonamento10k.perpetuo"
|
||||
|
||||
static let Subscription100kMonthly = "com.finazzi.distquake.Abbonamento100k.mensileAutomatico"
|
||||
static let Subscription100kYearly = "com.finazzi.distquake.Abbonamento100k.annualeAutomatico"
|
||||
static let Subscription100kYearlyDiscounted = "com.finazzi.distquake.Abbonamento100k.annualeAutomaticoscontato"
|
||||
static let Subscription100kPerpetual = "com.finazzi.distquake.Abbonamento100k.perpetuo"
|
||||
|
||||
|
||||
static let identifiers: Set<ProductIdentifier> = [
|
||||
ProVersionFullPrice, ProVersionDiscounted,
|
||||
Subscription10kMonthly, Subscription10kYearly, Subscription10kYearlyDiscounted,
|
||||
Subscription100kMonthly, Subscription100kYearly, Subscription100kYearlyDiscounted
|
||||
Subscription100kMonthly, Subscription100kYearly, Subscription100kYearlyDiscounted,
|
||||
Subscription10kPerpetual, Subscription100kPerpetual
|
||||
]
|
||||
|
||||
static let identifierForProVersion: Set<ProductIdentifier> = [
|
||||
ProVersionFullPrice, ProVersionDiscounted,
|
||||
Subscription10kYearly, Subscription10kYearlyDiscounted,
|
||||
Subscription100kYearly, Subscription100kYearlyDiscounted
|
||||
Subscription100kYearly, Subscription100kYearlyDiscounted,
|
||||
Subscription10kPerpetual, Subscription100kPerpetual
|
||||
]
|
||||
|
||||
static let identifiersForTop10k: Set<ProductIdentifier> = [
|
||||
Subscription10kMonthly, Subscription10kYearly, Subscription10kYearlyDiscounted
|
||||
Subscription10kMonthly, Subscription10kYearly, Subscription10kYearlyDiscounted, Subscription10kPerpetual
|
||||
]
|
||||
|
||||
static let identifiersForTop100k: Set<ProductIdentifier> = [
|
||||
Subscription100kMonthly, Subscription100kYearly, Subscription100kYearlyDiscounted
|
||||
Subscription100kMonthly, Subscription100kYearly, Subscription100kYearlyDiscounted, Subscription100kPerpetual
|
||||
]
|
||||
|
||||
static let identifierForSubscriptions: Set<ProductIdentifier> = [
|
||||
Subscription10kMonthly, Subscription100kMonthly,
|
||||
Subscription10kYearly, Subscription10kYearlyDiscounted,
|
||||
Subscription100kYearly, Subscription100kYearlyDiscounted
|
||||
Subscription100kYearly, Subscription100kYearlyDiscounted,
|
||||
Subscription10kPerpetual, Subscription100kPerpetual
|
||||
]
|
||||
|
||||
static func isSubscription(for identifier: String) -> Bool {
|
||||
Self.identifierForSubscriptions.contains(identifier)
|
||||
}
|
||||
|
||||
static func isSubscription(for identifier: String) -> Bool {
|
||||
Identifier.identifierForSubscriptions.contains(identifier)
|
||||
}
|
||||
|
||||
static func is10kSubscription(for identifier: String) -> Bool {
|
||||
Identifier.identifiersForTop10k.contains(identifier)
|
||||
}
|
||||
|
||||
static func is100kSubscription(for identifier: String) -> Bool {
|
||||
Identifier.identifiersForTop100k.contains(identifier)
|
||||
}
|
||||
|
||||
static func image(for productIdentifier: String) -> UIImage? {
|
||||
if is100kSubscription(for: productIdentifier){
|
||||
return UIImage(named: "top_100k")
|
||||
}
|
||||
|
||||
if is10kSubscription(for: productIdentifier) {
|
||||
return UIImage(named: "top_10k")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
public static let store = IAPHelper(productIds: VersioneProProducts.Identifier.identifiers)
|
||||
@@ -80,27 +106,4 @@ func resourceNameForProductIdentifier(_ productIdentifier: String) -> String? {
|
||||
return productIdentifier.components(separatedBy: ".").last
|
||||
}
|
||||
|
||||
func imageForProductIdentifier(_ productIdentifier: String) -> UIImage? {
|
||||
let products100k = [VersioneProProducts.Identifier.Subscription100kMonthly,
|
||||
VersioneProProducts.Identifier.Subscription100kYearly,
|
||||
VersioneProProducts.Identifier.Subscription100kYearlyDiscounted]
|
||||
if products100k.contains(productIdentifier) {
|
||||
return UIImage(named: "top_100k")
|
||||
}
|
||||
|
||||
let products10k = [VersioneProProducts.Identifier.Subscription10kMonthly,
|
||||
VersioneProProducts.Identifier.Subscription10kYearly,
|
||||
VersioneProProducts.Identifier.Subscription10kYearlyDiscounted]
|
||||
if products10k.contains(productIdentifier) {
|
||||
return UIImage(named: "top_10k")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func is100kSubscriptionForProductIdentifier(_ productIdentifier: String) -> Bool {
|
||||
let products100k = [VersioneProProducts.Identifier.Subscription100kMonthly,
|
||||
VersioneProProducts.Identifier.Subscription100kYearly,
|
||||
VersioneProProducts.Identifier.Subscription100kYearlyDiscounted]
|
||||
return products100k.contains(productIdentifier)
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 323 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 12 KiB |
@@ -137,6 +137,7 @@
|
||||
case EQNTipoChiamataRilevamento:
|
||||
onSuccess([EQNUtility clearStringMessaggi:newStr]);
|
||||
break;
|
||||
case EQNTipoChiamataPosizione:
|
||||
case EQNTipoChiamataCalibrazione:
|
||||
case EQNTipoChiamataImpostazioniNotifiche:
|
||||
case EQNTipoChiamataAlertSimulator:
|
||||
|
||||
@@ -20,14 +20,7 @@ class EQNBaseTableViewCell: UITableViewCell {
|
||||
|
||||
clipsToBounds = true
|
||||
|
||||
// rounded corners
|
||||
containerView.layer.cornerRadius = AppTheme.shared.cardCornerRadius
|
||||
containerView.layer.masksToBounds = false
|
||||
|
||||
// apply a shadow to the container view
|
||||
containerView.layer.shadowColor = UIColor.black.cgColor
|
||||
containerView.layer.shadowOpacity = 0.5
|
||||
containerView.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
containerView.layer.shadowRadius = 2
|
||||
// rounded corners and shadow
|
||||
containerView.eqn_applyShadowAndRoundedCorners()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +61,9 @@ class EQNBlurredCloseButton: UIButton {
|
||||
|
||||
/// Add constaints to show the button on the upper right corner
|
||||
func addDefaultConstraint(to view: UIView) {
|
||||
leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10.0).isActive = true
|
||||
trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10.0).isActive = true
|
||||
topAnchor.constraint(equalTo: view.topAnchor, constant: 10.0).isActive = true
|
||||
widthAnchor.constraint(equalTo: heightAnchor).isActive = true
|
||||
heightAnchor.constraint(equalToConstant: 40.0).isActive = true
|
||||
heightAnchor.constraint(equalToConstant: 34.0).isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// EQNInsetTableViewCell.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Busi Andrea on 29/07/2020.
|
||||
// Copyright © 2020 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class EQNInsetTableViewCell: UITableViewCell {
|
||||
override var frame: CGRect {
|
||||
get {
|
||||
return super.frame
|
||||
}
|
||||
set (newFrame) {
|
||||
let inset: CGFloat = 15
|
||||
var frame = newFrame
|
||||
frame.origin.x += inset
|
||||
frame.size.width -= 2 * inset
|
||||
super.frame = frame
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,12 +209,15 @@
|
||||
"network_pro_terms_conditions" = "Όροι και συνθήκες";
|
||||
"network_pro_paying" = "Πληρώνετε:";
|
||||
"inapp_detail_description" = "• Η πληρωμή σας θα χρεωθεί στο λογαριασμό σας στο iTunes κατά την επιβεβαίωση της αγοράς\n• η συνδρομή ανανεώνεται αυτόματα εκτός εάν η αυτόματη ανανέωση απενεργοποιείται τουλάχιστον 24 ώρες πριν από το τέλος της τρέχουσας περιόδου\n• η συνδρομή θα χρεωθεί για ανανέωση εντός 24 Ώρες πριν από το τέλος της τρέχουσας περιόδου και το κόστος ανανέωσης που εντοπίστηκαν\n• Οι συνδρομές μπορούν να διαχειριστούν από τον χρήστη και η αυτόματη ανανέωση μπορεί να απενεργοποιηθεί με την πρόσβαση στις ρυθμίσεις του λογαριασμού του χρήστη μετά την αγορά.";
|
||||
"inapp_lifetime_detail_description" = "• Η πληρωμή σας θα χρεωθεί στο λογαριασμό σας στο iTunes κατά την επιβεβαίωση της αγοράς";
|
||||
"inapp_purchase" = "ΕΓΓΡΑΦΕΊΤΕ ΣΤΗΝ ΥΠΗΡΕΣΊΑ";
|
||||
"official_select_country_placeholder" = "Επιλέξτε τη χώρα";
|
||||
"inapp_lifetime_subscriptions" = "Συνδρομές διάρκειας ζωής";
|
||||
"inapp_yearly_subscriptions" = "Ετήσιες συνδρομές";
|
||||
"inapp_monthly_subscriptions" = "Μηνιαίες συνδρομές";
|
||||
"inapp_monthly_payment" = "θα πληρώσετε ανά μήνα:";
|
||||
"inapp_yearly_payment" = "θα πληρώσετε ετησίως:";
|
||||
"inapp_lifetime_payment" = "θα πληρώσετε:";
|
||||
"ok" = "Εντάξει";
|
||||
"critical_alerts_setting" = "Κρίσιμες ειδοποιήσεις. Κάντε έναν ήχο επίσης, δεν διαταράσσετε τη λειτουργία";
|
||||
"attention" = "Προσοχή";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Select the country";
|
||||
"inapp_lifetime_subscriptions" = "Lifetime subscriptions";
|
||||
"inapp_yearly_subscriptions" = "Annual subscriptions";
|
||||
"inapp_monthly_subscriptions" = "Monthly subscriptions";
|
||||
"inapp_monthly_payment" = "you will pay per month:";
|
||||
"inapp_yearly_payment" = "you will pay per year:";
|
||||
"inapp_lifetime_payment" = "you will pay:";
|
||||
"ok" = "Ok";
|
||||
"critical_alerts_setting" = "Critical alerts. Make a sound also in do not disturb mode";
|
||||
"attention" = "Attention";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Seleccione el pais";
|
||||
"inapp_lifetime_subscriptions" = "Suscripciones de por vida";
|
||||
"inapp_yearly_subscriptions" = "Suscripciones anuales";
|
||||
"inapp_monthly_subscriptions" = "Suscripciones mensuales";
|
||||
"inapp_monthly_payment" = "pagarás por mes:";
|
||||
"inapp_yearly_payment" = "pagarás por año:";
|
||||
"inapp_lifetime_payment" = "pagarás:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Alertas críticas. Emite un sonido también en el modo no molestar";
|
||||
"attention" = "Atención";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Sélectionnez le pays";
|
||||
"inapp_lifetime_subscriptions" = "Abonnements à vie";
|
||||
"inapp_yearly_subscriptions" = "Abonnements annuels";
|
||||
"inapp_monthly_subscriptions" = "Abonnements mensuels";
|
||||
"inapp_monthly_payment" = "vous paierez par mois:";
|
||||
"inapp_yearly_payment" = "vous paierez par an:";
|
||||
"inapp_lifetime_payment" = "vous paierez:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Alertes critiques. Émettre un son également en mode Ne pas déranger";
|
||||
"attention" = "Attention";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Odaberite zemlju";
|
||||
"inapp_lifetime_subscriptions" = "Doživotne pretplate";
|
||||
"inapp_yearly_subscriptions" = "Godišnje pretplate";
|
||||
"inapp_monthly_subscriptions" = "Mjesečne pretplate";
|
||||
"inapp_monthly_payment" = "ćete platiti po mjesecu:";
|
||||
"inapp_yearly_payment" = "ćete platiti godišnje:";
|
||||
"inapp_lifetime_payment" = "ćete platiti:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Kritična upozorenja. Dajte zvuk i u načinu ne ometaj";
|
||||
"attention" = "Pažnja";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Pilih negaranya";
|
||||
"inapp_lifetime_subscriptions" = "Langganan seumur hidup";
|
||||
"inapp_yearly_subscriptions" = "Langganan tahunan";
|
||||
"inapp_monthly_subscriptions" = "Langganan bulanan";
|
||||
"inapp_monthly_payment" = "Anda akan membayar per bulan:";
|
||||
"inapp_yearly_payment" = "Anda akan membayar per tahu:";
|
||||
"inapp_lifetime_payment" = "Anda akan membayar:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Peringatan kritis. Bersuara juga dalam mode jangan ganggu";
|
||||
"attention" = "Perhatian";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Scegli la nazione";
|
||||
"inapp_lifetime_subscriptions" = "Abbonamenti a vita";
|
||||
"inapp_yearly_subscriptions" = "Abbonamenti annuali";
|
||||
"inapp_monthly_subscriptions" = "Abbonamenti mensili";
|
||||
"inapp_monthly_payment" = "pagherai al mese:";
|
||||
"inapp_yearly_payment" = "pagherai all'anno:";
|
||||
"inapp_lifetime_payment" = "pagherai:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Allerte critiche. Produci un suono anche in modalità non disturbare";
|
||||
"attention" = "Attenzione";
|
||||
|
||||
@@ -209,12 +209,15 @@
|
||||
"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";
|
||||
"official_select_country_placeholder" = "Ülkeyi seçin";
|
||||
"inapp_lifetime_subscriptions" = "Ömür boyu abonelikler";
|
||||
"inapp_yearly_subscriptions" = "Yıllık abonelikler";
|
||||
"inapp_monthly_subscriptions" = "Aylık abonelikler";
|
||||
"inapp_monthly_payment" = "aylık ödeyeceksiniz:";
|
||||
"inapp_yearly_payment" = "senelik ödeyeceksin:";
|
||||
"inapp_lifetime_payment" = "ödeyeceksin:";
|
||||
"ok" = "OK";
|
||||
"critical_alerts_setting" = "Kritik uyarılar. Rahatsız etmeyin modunda da ses çıkar";
|
||||
"attention" = "Dikkat";
|
||||
|
||||
@@ -1,96 +1,120 @@
|
||||
PODS:
|
||||
- DZNEmptyDataSet (1.8.1)
|
||||
- Firebase/Core (7.10.0):
|
||||
- Firebase/Core (9.1.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (~> 7.10.0)
|
||||
- Firebase/CoreOnly (7.10.0):
|
||||
- FirebaseCore (= 7.10.0)
|
||||
- Firebase/Crashlytics (7.10.0):
|
||||
- FirebaseAnalytics (~> 9.1.0)
|
||||
- Firebase/CoreOnly (9.1.0):
|
||||
- FirebaseCore (= 9.1.0)
|
||||
- Firebase/Crashlytics (9.1.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 7.10.0)
|
||||
- Firebase/Messaging (7.10.0):
|
||||
- FirebaseCrashlytics (~> 9.1.0)
|
||||
- Firebase/Messaging (9.1.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 7.10.0)
|
||||
- FirebaseAnalytics (7.10.0):
|
||||
- FirebaseCore (~> 7.0)
|
||||
- FirebaseInstallations (~> 7.0)
|
||||
- GoogleAppMeasurement (= 7.10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.0)
|
||||
- GoogleUtilities/Network (~> 7.0)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.0)"
|
||||
- nanopb (~> 2.30908.0)
|
||||
- FirebaseCore (7.10.0):
|
||||
- FirebaseCoreDiagnostics (~> 7.4)
|
||||
- GoogleUtilities/Environment (~> 7.0)
|
||||
- GoogleUtilities/Logger (~> 7.0)
|
||||
- FirebaseCoreDiagnostics (7.10.0):
|
||||
- GoogleDataTransport (~> 8.4)
|
||||
- GoogleUtilities/Environment (~> 7.0)
|
||||
- GoogleUtilities/Logger (~> 7.0)
|
||||
- nanopb (~> 2.30908.0)
|
||||
- FirebaseCrashlytics (7.10.0):
|
||||
- FirebaseCore (~> 7.0)
|
||||
- FirebaseInstallations (~> 7.0)
|
||||
- GoogleDataTransport (~> 8.4)
|
||||
- nanopb (~> 2.30908.0)
|
||||
- PromisesObjC (~> 1.2)
|
||||
- FirebaseInstallations (7.10.0):
|
||||
- FirebaseCore (~> 7.0)
|
||||
- GoogleUtilities/Environment (~> 7.0)
|
||||
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||
- PromisesObjC (~> 1.2)
|
||||
- FirebaseInstanceID (7.10.0):
|
||||
- FirebaseCore (~> 7.0)
|
||||
- FirebaseInstallations (~> 7.0)
|
||||
- GoogleUtilities/Environment (~> 7.0)
|
||||
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||
- FirebaseMessaging (7.10.0):
|
||||
- FirebaseCore (~> 7.0)
|
||||
- FirebaseInstanceID (~> 7.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||
- GoogleUtilities/Environment (~> 7.0)
|
||||
- GoogleUtilities/Reachability (~> 7.0)
|
||||
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||
- Google-Mobile-Ads-SDK (8.3.0):
|
||||
- GoogleAppMeasurement (~> 7.0)
|
||||
- FirebaseMessaging (~> 9.1.0)
|
||||
- FirebaseAnalytics (9.1.0):
|
||||
- FirebaseAnalytics/AdIdSupport (= 9.1.0)
|
||||
- FirebaseCore (~> 9.0)
|
||||
- FirebaseInstallations (~> 9.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseAnalytics/AdIdSupport (9.1.0):
|
||||
- FirebaseCore (~> 9.0)
|
||||
- FirebaseInstallations (~> 9.0)
|
||||
- GoogleAppMeasurement (= 9.1.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseCore (9.1.0):
|
||||
- FirebaseCoreDiagnostics (~> 9.0)
|
||||
- FirebaseCoreInternal (~> 9.0)
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- GoogleUtilities/Logger (~> 7.7)
|
||||
- FirebaseCoreDiagnostics (9.1.0):
|
||||
- GoogleDataTransport (< 10.0.0, >= 9.1.4)
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- GoogleUtilities/Logger (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseCoreInternal (9.1.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- FirebaseCrashlytics (9.1.0):
|
||||
- FirebaseCore (~> 9.0)
|
||||
- FirebaseInstallations (~> 9.0)
|
||||
- GoogleDataTransport (< 10.0.0, >= 9.1.4)
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseInstallations (9.1.0):
|
||||
- FirebaseCore (~> 9.0)
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseMessaging (9.1.0):
|
||||
- FirebaseCore (~> 9.0)
|
||||
- FirebaseInstallations (~> 9.0)
|
||||
- GoogleDataTransport (< 10.0.0, >= 9.1.4)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- GoogleUtilities/Reachability (~> 7.7)
|
||||
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- Google-Mobile-Ads-SDK (9.6.0):
|
||||
- GoogleAppMeasurement (< 10.0, >= 7.0)
|
||||
- GoogleUserMessagingPlatform (>= 1.1)
|
||||
- GoogleAppMeasurement (7.10.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.0)
|
||||
- GoogleUtilities/Network (~> 7.0)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.0)"
|
||||
- nanopb (~> 2.30908.0)
|
||||
- GoogleDataTransport (8.4.0):
|
||||
- GoogleUtilities/Environment (~> 7.2)
|
||||
- nanopb (~> 2.30908.0)
|
||||
- PromisesObjC (~> 1.2)
|
||||
- GoogleAppMeasurement (9.1.0):
|
||||
- GoogleAppMeasurement/AdIdSupport (= 9.1.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/AdIdSupport (9.1.0):
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 9.1.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (9.1.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.7)
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleDataTransport (9.1.4):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUserMessagingPlatform (2.0.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.3.1):
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.3.1):
|
||||
- PromisesObjC (~> 1.2)
|
||||
- GoogleUtilities/Logger (7.3.1):
|
||||
- GoogleUtilities/Environment (7.7.0):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.7.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/MethodSwizzler (7.3.1):
|
||||
- GoogleUtilities/MethodSwizzler (7.7.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network (7.3.1):
|
||||
- GoogleUtilities/Network (7.7.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.3.1)"
|
||||
- GoogleUtilities/Reachability (7.3.1):
|
||||
- "GoogleUtilities/NSData+zlib (7.7.0)"
|
||||
- GoogleUtilities/Reachability (7.7.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.3.1):
|
||||
- GoogleUtilities/UserDefaults (7.7.0):
|
||||
- GoogleUtilities/Logger
|
||||
- nanopb (2.30908.0):
|
||||
- nanopb/decode (= 2.30908.0)
|
||||
- nanopb/encode (= 2.30908.0)
|
||||
- nanopb/decode (2.30908.0)
|
||||
- nanopb/encode (2.30908.0)
|
||||
- PromisesObjC (1.2.12)
|
||||
- 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.0)
|
||||
- Solar (2.1.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
@@ -108,9 +132,9 @@ SPEC REPOS:
|
||||
- FirebaseAnalytics
|
||||
- FirebaseCore
|
||||
- FirebaseCoreDiagnostics
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseCrashlytics
|
||||
- FirebaseInstallations
|
||||
- FirebaseInstanceID
|
||||
- FirebaseMessaging
|
||||
- Google-Mobile-Ads-SDK
|
||||
- GoogleAppMeasurement
|
||||
@@ -123,23 +147,23 @@ SPEC REPOS:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
|
||||
Firebase: fffddd0bab8677d07376538365faa93ff3889b39
|
||||
FirebaseAnalytics: 4641d7ae4220174f6ca5626163ffc5de2e90391e
|
||||
FirebaseCore: ec566d917b2195fc2610aeb148dae99f57a788f9
|
||||
FirebaseCoreDiagnostics: 5662a3823ffcc0acbaa9a21ba5ed302fac634705
|
||||
FirebaseCrashlytics: e7669d368a22d202f1d0c7546ffdfdff496e1a8c
|
||||
FirebaseInstallations: bf2ec8dbf36ff4c91af6b9a003d15855757680c1
|
||||
FirebaseInstanceID: 5ad92c898e1328b66e8dd58811964d6fe4d334c3
|
||||
FirebaseMessaging: 76b3058cef7f339cf10db196e03bbbb2165fb5d7
|
||||
Google-Mobile-Ads-SDK: c14f5a63db1414b4ca0ee1539c9f3d700ace96c2
|
||||
GoogleAppMeasurement: 1c863b1161fc3c8cf614a7460d1be6a7c262aab3
|
||||
GoogleDataTransport: cd9db2180fcecd8da1b561aea31e3e56cf834aa7
|
||||
Firebase: 91c243d75573ac6e7c9735ec859b72bffb61347d
|
||||
FirebaseAnalytics: bf11064790ac96804df1df9ddc0ae45af950d9fc
|
||||
FirebaseCore: b7bfc258e996eada23b3666bd6b9a22ca092acb8
|
||||
FirebaseCoreDiagnostics: 2dabba3412b23b524823325739f45e520f67d1e7
|
||||
FirebaseCoreInternal: f3c838ae0b41cd840bbf34f90debfede78d352e5
|
||||
FirebaseCrashlytics: 8e21736dcf15d814b79229eb7e79ba3a5eec5f30
|
||||
FirebaseInstallations: a91c74276b544524ce144c8315d8cdbce2dbe30b
|
||||
FirebaseMessaging: 0bf5caa621182ccc66ba3be3b15e68d800d98e9f
|
||||
Google-Mobile-Ads-SDK: bdf13d37aa77e368510687b5305d4972b4f9e9c7
|
||||
GoogleAppMeasurement: 8ecc717f2abe3f9ee95a5d38db08827852894acc
|
||||
GoogleDataTransport: 5fffe35792f8b96ec8d6775f5eccd83c998d5a3b
|
||||
GoogleUserMessagingPlatform: ab890ce5f6620f293a21b6bdd82e416a2c73aeca
|
||||
GoogleUtilities: e1d9ed4e544fc32a93e00e721400cbc3f377200d
|
||||
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
|
||||
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
|
||||
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
||||
PromisesObjC: 99b6f43f9e1044bd87a95a60beff28c2c44ddb72
|
||||
Solar: 2dc6e7cc39186cb0c8228fa08df76fb50c7d8f24
|
||||
|
||||
PODFILE CHECKSUM: dd5131b6d7a83fb7c22ecc161ed4fc143eda0ac1
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
COCOAPODS: 1.11.3
|
||||
|
||||