Compare commits

...

21 Commits

Author SHA1 Message Date
Andrea Busi 15088b744f release: Increase version for release 2022-12-30 00:18:07 +01:00
Andrea Busi ac03a0cccb refactor: Update translations for tracking permission 2022-12-30 00:17:57 +01:00
Andrea Busi 76a26e3100 release: Increase version for release 2022-12-07 17:56:52 +01:00
Andrea Busi cac6ed67ac feat: Configure AppTracking and Facebook required flags 2022-12-07 09:26:37 +01:00
Andrea Busi 094c682dbd refactor: Reorganize Firebase configuration 2022-12-07 09:26:03 +01:00
Andrea Busi c44f46ca46 refactor: Reorganize push notification configuration 2022-12-07 09:25:38 +01:00
Andrea Busi 5e8c3d0796 release: Increase version fo release 2022-12-06 09:12:53 +01:00
Andrea Busi 61ce27ed4b feat: Enable Facebook SDK in app 2022-12-02 17:33:42 +01:00
Andrea Busi 3aea60e560 dependency: Add Facebook SDK 2022-12-02 15:18:18 +01:00
Andrea Busi 84b61fd7e2 release: Increase version for release 2022-11-28 22:21:51 +01:00
Andrea Busi a5a8c6f5c5 fix: Solve missing critical alerts after notification service migration 2022-11-28 10:33:30 +01:00
Andrea Busi 61587a0341 release: Increase version for release 2022-11-24 11:08:22 +01:00
Andrea Busi a56a04a4ad refactor: Recreate NotificationService (in Swift) to solve unpredictable behaviour
Resolves: https://gitlab.steamware.net/eqn/eqn.ios/-/issues/54
2022-11-24 11:08:22 +01:00
Andrea Busi 7173dc7031 dependency: Update Shogun 2022-11-24 10:52:39 +01:00
Andrea Busi 35dbdbab28 fix: Reduce space 2022-11-18 10:57:08 +01:00
Andrea Busi 14614267d4 feat: Add color in user report total 2022-11-18 10:50:24 +01:00
Andrea Busi 32833010ed dependency: Update Shogun 2022-11-18 10:50:08 +01:00
Andrea Busi ecc77e9f2b fix: Solve runtime warning 2022-11-18 08:34:41 +01:00
Andrea Busi e69747f133 refactor: Migrate preference to AppPreferences class 2022-11-18 08:33:35 +01:00
Andrea Busi 09685fd4a7 feat: Store user selection for compact/expanded view in suer report 2022-11-17 22:21:59 +01:00
Andrea Busi 3e122240dc refactor: Rework image creation 2022-11-17 22:13:18 +01:00
31 changed files with 948 additions and 847 deletions
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## Versione 5.4
- Aggiunto SDK Facebook
## Versione 5.3.2
- Corretto problema con notifiche critiche
## Versione 5.3.1
- Ricreato progetto NotificationService
- Correzioni minori
## Versione 5.3
- Rivista gestione registrazione utente
@@ -119,7 +119,7 @@
EQNMapAnnotationUserReport *report = (EQNMapAnnotationUserReport *)annotation;
EQNCustomAnnotationView *annotationView = (EQNCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:EQNCustomAnnotationView.SmallIdentifier];
annotationView.image = report.image;
annotationView.image = [report imageWithHeight:EQNCustomAnnotationView.SmallViewImageHeight];
annotationView.title = report.timeDifference;
return annotationView;
}
@@ -1,5 +0,0 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "NotificationService.h"
+1 -24
View File
@@ -2,35 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>EQNNotificationService</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>NotificationService</string>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
</dict>
</plist>
@@ -1,47 +0,0 @@
//
// 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()
}
}
}
}
@@ -1,13 +0,0 @@
//
// NotificationService.h
// EQNNotificationService
//
// Refactored by Andrea Busi
// Copyright © 2020 Earthquake Network. All rights reserved.
//
#import <UserNotifications/UserNotifications.h>
@interface NotificationService : UNNotificationServiceExtension
@end
@@ -1,170 +0,0 @@
//
// NotificationService.m
// EQNNotificationService
//
// Refactored by Andrea Busi
// Copyright © 2020 Earthquake Network. All rights reserved.
//
#import "NotificationService.h"
#import "EQNAllertaSismica.h"
#import "Costanti.h"
#import "EQNNotificationService-Swift.h"
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
static NSString * const EQNSoundNotificationEQN = @"alert_sound.wav";
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler
{
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
// Configure the notification's payload.
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:request.content.title arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:request.content.body arguments:nil];
self.bestAttemptContent.title = content.title;
self.bestAttemptContent.body = content.body;
// check for required informations
NSDictionary *userInfo = request.content.userInfo;
NSString *notificationType = [userInfo objectForKey:@"type"];
if (userInfo == nil || notificationType == nil) {
[self contentComplete];
return;
}
NSString *iconName = @"";
if ([notificationType isEqualToString:@"eqn"]) {
// check if user has enabled critical alerts
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:EQNUserDefaultAppGroupSuite];
BOOL criticalAlertsEnabled = [sharedDefaults boolForKey:NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS];
// !!WORKAROUND
// this is a workaround to use critical alerts with legacy FCM api
// when the server implementation will be migrated to Firebase v1 APIs, this could be removed
BOOL isCritical = [[userInfo objectForKey:@"critical"] boolValue];
if (isCritical && criticalAlertsEnabled) {
self.bestAttemptContent.sound = [UNNotificationSound criticalSoundNamed:EQNSoundNotificationEQN withAudioVolume:1.0];
} else {
self.bestAttemptContent.sound = [UNNotificationSound soundNamed:EQNSoundNotificationEQN];
}
NSString *intensity = [userInfo objectForKey:@"intensity"];
switch ([intensity intValue]) {
case 0:
iconName = @"star_realtime_white.png";
break;
case 1:
iconName = @"star_realtime_lightblue.png";
break;
case 2:
iconName = @"star_realtime_blue.png";
break;
default:
break;
}
} else if ([notificationType isEqualToString:@"manual"]) {
// there are 12 levels, so a customized icon doesn't make sense
// use a generic warning icon instead
iconName = @"warning_yellow.png";
} else if ([notificationType isEqualToString:@"official"]) {
NSString *provaider = [userInfo objectForKey:@"provider"];
double intensity = [[userInfo objectForKey:@"magnitude"] doubleValue];
NSString *colore = @"";
if (intensity < 2.0) {
colore = @"_white";
} else if (intensity < 3.5) {
colore = @"_green";
} else if (intensity < 4.5) {
colore = @"_yellow";
} else if (intensity < 5.5) {
colore = @"_red";
} else {
colore = @"_purple";
}
if ([provaider isEqualToString:@"USGS"]) {
iconName = [NSString stringWithFormat:@"star%@.png", colore];
} else if ([provaider isEqualToString:@"SGC"]) {
iconName = [NSString stringWithFormat:@"star3%@.png", colore];
} else if ([provaider isEqualToString:@"CSN"]) {
iconName = [NSString stringWithFormat:@"star3f%@.png", colore];
} else if ([provaider isEqualToString:@"SSN"]) {
iconName = [NSString stringWithFormat:@"star4%@.png", colore];
} else if ([provaider isEqualToString:@"INPRES"]) {
iconName = [NSString stringWithFormat:@"star4r%@.png", colore];
} else if ([provaider isEqualToString:@"FUNVISIS"]) {
iconName = [NSString stringWithFormat:@"star6%@.png", colore];
} else if ([provaider isEqualToString:@"Ineter"]) {
iconName = [NSString stringWithFormat:@"triangle%@.png", colore];
} else if ([provaider isEqualToString:@"RSN"]) {
iconName = [NSString stringWithFormat:@"triangle2%@.png", colore];
} else if ([provaider isEqualToString:@"PHIVOLCS"]) {
iconName = [NSString stringWithFormat:@"triround_inner%@.png", colore];
} else if ([provaider isEqualToString:@"IGEPN"]) {
iconName = [NSString stringWithFormat:@"triround%@.png", colore];
} else if ([provaider isEqualToString:@"INGV"]) {
iconName = [NSString stringWithFormat:@"circle%@.png", colore];
} else if ([provaider isEqualToString:@"EMSC"]) {
iconName = [NSString stringWithFormat:@"dyamond%@.png", colore];
} else if ([provaider isEqualToString:@"IGP"]) {
iconName = [NSString stringWithFormat:@"dyamond_round%@.png", colore];
} else if ([provaider isEqualToString:@"JMA"]) {
iconName = [NSString stringWithFormat:@"esa%@.png", colore];
} else if ([provaider isEqualToString:@"GEONET"]) {
iconName = [NSString stringWithFormat:@"oct%@.png", colore];
} if ([provaider isEqualToString:@"CSI"]) {
iconName = [NSString stringWithFormat:@"penta%@.png", colore];
} else if ([provaider isEqualToString:@"IGN"]) {
iconName = [NSString stringWithFormat:@"square%@.png", colore];
} else if ([provaider isEqualToString:@"UASD"] || [provaider isEqualToString:@"BDTIM"] || [provaider isEqualToString:@"NCS"]) {
iconName = [NSString stringWithFormat:@"thick_star%@.png", colore];
} else if ([provaider isEqualToString:@"RSPR"]) {
iconName = [NSString stringWithFormat:@"star6f%@.png", colore];
}
}
if (![iconName isEqualToString:@""]) {
iconName = [iconName stringByReplacingOccurrencesOfString:@".png" withString:@""];
NSURL *imageUrl = [NSBundle.mainBundle URLForResource:iconName withExtension:@"png"];
NSError *attachmentError = nil;
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:iconName
URL:imageUrl
options:nil
error:&attachmentError];
if (!attachmentError) {
self.bestAttemptContent.attachments = @[attachment];
}
}
// remove same type posted notification
[self removeNotificationsForType:notificationType completion:^{
[self contentComplete];
}];;
}
- (void)serviceExtensionTimeWillExpire
{
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
[self contentComplete];
}
- (void)contentComplete
{
self.contentHandler(self.bestAttemptContent);
}
@end
@@ -0,0 +1,184 @@
//
// NotificationService.swift
// EQNNotificationService
//
// Created by Andrea Busi on 24/11/22.
// Copyright © 2022 Earthquake Network. All rights reserved.
//
import UserNotifications
import Shogun
class NotificationService: UNNotificationServiceExtension {
// riportiamo queste costanti dall'app bundle, per non dover referenziare file in ObjC
private static let EQNUserDefaultAppGroupSuite = "group.com.finazzi.distquake"
private static let NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS = "NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS"
private static let EQNSoundNotification = UNNotificationSoundName("alert_sound.wav")
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
guard let bestAttemptContent = bestAttemptContent else {
print("[NotificationService] Unable to get notification content")
contentComplete()
return
}
let userInfo = request.content.userInfo
guard let notificationType = userInfo.string(forKey: "type") else {
print("[NotificationService] Unable to get notification type")
contentComplete()
return
}
var iconName = ""
switch notificationType.lowercased() {
case "eqn":
// check if user has enabled critical alerts
let sharedDefaults = UserDefaults(suiteName: Self.EQNUserDefaultAppGroupSuite)
let criticalAlertsEnabled = sharedDefaults?.bool(forKey: Self.NOTIFICHE_ALLERA_SISMICA_CRITICAL_ALERTS) ?? false
// !!WORKAROUND
// this is a workaround to use critical alerts with legacy FCM api
// when the server implementation will be migrated to Firebase v1 APIs, this could be removed
let isCritical = userInfo.integer(forKey: "critical", orDefault: 0) == 1
if isCritical && criticalAlertsEnabled {
bestAttemptContent.sound = UNNotificationSound.criticalSoundNamed(Self.EQNSoundNotification)
} else {
bestAttemptContent.sound = UNNotificationSound(named: Self.EQNSoundNotification)
}
let intensity = userInfo.integer(forKey: "intensity")
switch intensity {
case 0:
iconName = "star_realtime_white.png"
case 1:
iconName = "star_realtime_lightblue.png"
case 2:
iconName = "star_realtime_blue.png"
default:
break
}
case "manual":
// there are 12 levels, so a customized icon doesn't make sense
// use a generic warning icon instead
iconName = "warning_yellow.png"
case "official":
let provider = userInfo.string(forKey: "provider", orDefault: "")
let intensity = userInfo.double(forKey: "magnitude", orDefault: 0)
let color: String
if intensity < 2.0 {
color = "_white"
} else if intensity < 3.5 {
color = "_green"
} else if intensity < 4.5 {
color = "_yellow"
} else if intensity < 5.5 {
color = "_red"
} else {
color = "_purple"
}
iconName = manualIconName(for: provider, color: color)
default:
break
}
// add the icon as notification attachment
if !iconName.isEmpty {
iconName = iconName.replacingOccurrences(of: ".png", with: "")
if let imageUrl = Bundle(for: NotificationService.self).url(forResource: iconName, withExtension: "png"),
let attachment = try? UNNotificationAttachment(identifier: iconName, url: imageUrl) {
bestAttemptContent.attachments = [ attachment ]
}
}
// remove same type posted notification
removeNotifications(for: notificationType) { [weak self] in
self?.contentComplete()
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
// MARK: - Private
private func contentComplete() {
if let bestAttemptContent {
contentHandler?(bestAttemptContent)
}
}
private 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()
}
}
}
// MARK: - Helpers
private func manualIconName(for provider: String, color: String) -> String {
switch provider.uppercased() {
case "USGS": return "star\(color).png"
case "SGC": return "star3\(color).png"
case "CSN": return "star3f\(color).png"
case "SSN": return "star4\(color).png"
case "INPRES": return "star4r\(color).png"
case "FUNVISIS": return "star6\(color).png"
case "INETER": return "triangle\(color).png"
case "RSN": return "triangle2\(color).png"
case "PHIVOLCS": return "triround_inner\(color).png"
case "IGEPN": return "triround\(color).png"
case "INGV": return "circle\(color).png"
case "EMSC": return "dyamond\(color).png"
case "IGP": return "dyamond_round\(color).png"
case "JMA": return "esa\(color).png"
case "GEONET": return "oct\(color).png"
case "CSI": return "penta\(color).png"
case "IGN": return "square\(color).png"
case "UASD", "BDTIM", "NCS": return "thick_star\(color).png"
case "RSPR": return "star6f\(color).png"
default: return ""
}
}
}
File diff suppressed because it is too large Load Diff
@@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/andreabusi-it/Shogun",
"state" : {
"revision" : "63d1fdb957d917410e58a958a49fdb52f8de10ac",
"version" : "0.2.3"
"revision" : "4120014b7e567296a95cd05a8a801a198f4cdac9",
"version" : "0.5.0"
}
}
],
+49 -10
View File
@@ -19,10 +19,12 @@
#import "EQNNotificheReteSismiche.h"
#import "EQNMainTabBarController.h"
@import UserNotifications;
@import AppTrackingTransparency;
@import Firebase;
@import FirebaseCrashlytics;
@import UserNotifications;
@import GoogleMobileAds;
@import FBSDKCoreKit;
@interface AppDelegate () <FIRMessagingDelegate, UNUserNotificationCenterDelegate>
@property (strong, nonatomic) NSArray<id<EQNCommandProtocol>> *commands;
@@ -50,20 +52,14 @@
[EQNUser defaultUser];
[EQNManager defaultManager];
[FIRApp configure];
[FIRMessaging messaging].delegate = self;
[self configureFirebase];
[self configureFacebookSDKWithApplication:application andOptions:launchOptions];
// add some generic logs for Crashlytics
NSString *language = [[NSLocale preferredLanguages] firstObject];
[[FIRCrashlytics crashlytics] setCustomValue:language forKey:@"lang"];
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
[self registraNotifica];
}];
[self configurePushNotifications];
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
[application registerForRemoteNotifications];
@@ -197,6 +193,49 @@
[self.mainTabBarController selectSection:section];
}
#pragma mark - Configurations
- (void)configurePushNotifications
{
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
[self registraNotifica];
[self configureAppTracking];
}];
}
- (void)configureAppTracking
{
if (@available(iOS 14, *)) {
// add a delay otherwise the alert will not be displayed
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
} else {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = NO;
}
}];
});
} else {
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
}
}
- (void)configureFirebase
{
[FIRApp configure];
[FIRMessaging messaging].delegate = self;
}
- (void)configureFacebookSDKWithApplication:(UIApplication *)application andOptions:(NSDictionary *)launchOptions
{
[FBSDKApplicationDelegate.sharedInstance application:application didFinishLaunchingWithOptions:launchOptions];
[FBSDKSettings.sharedSettings setIsAdvertiserIDCollectionEnabled:YES];
[FBSDKSettings.sharedSettings setIsAdvertiserIDCollectionEnabled:YES];
}
#pragma mark - FIRMessagingDelegate
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken
@@ -113,7 +113,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
[super refreshUI];
// `AllerteTableRowReteSmartphone` and `AllerteTableRowDatiPosizione` are hidden bu default, user can show them
BOOL showAllCards = [[NSUserDefaults standardUserDefaults] boolForKey:EQNUserDefaultKeyAlertsShowAllCards];
BOOL showAllCards = AppPreferences.shared.alertsShowAllCards;
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
@@ -177,9 +177,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
- (IBAction)collapseExpandTapped:(id)sender
{
// toggle saved value
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL showAll = [defaults boolForKey:EQNUserDefaultKeyAlertsShowAllCards];
[defaults setBool:!showAll forKey:EQNUserDefaultKeyAlertsShowAllCards];
AppPreferences.shared.alertsShowAllCards = !AppPreferences.shared.alertsShowAllCards;
[self refreshUI];
}
@@ -7,6 +7,7 @@
//
import UIKit
import Shogun
class SegnalazioniLast24HoursCell: EQNBaseTableViewCell {
@@ -49,6 +50,15 @@ class SegnalazioniLast24HoursCell: EQNBaseTableViewCell {
return
}
self.reportsLabel.text = "\(smartphoneNetwork.manual)"
let reports = smartphoneNetwork.manual
self.reportsLabel.text = "\(reports)"
if reports < 100 {
self.reportsLabel.textColor = UIColor(hex6: 0x01b400)
} else if reports < 1000 {
self.reportsLabel.textColor = UIColor(hex6: 0xe8da00)
} else {
self.reportsLabel.textColor = UIColor(hex6: 0xff0000)
}
}
}
@@ -21,12 +21,11 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
false
}
private let appPreferences = AppPreferences.shared
/// Contains circles and related colors to draw overlays on the map
private var mapCircles = [MapCircle]()
/// Reports currently showned on the map
private var filteredReports = [EQNSegnalazione]()
/// Defines if time has to be shown on map annotations
private var showAnnotationTime = false
// MARK: - UI
@@ -191,7 +190,7 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
}
@objc private func onTapMapDetailStyleButton(_ sender: Any) {
showAnnotationTime.toggle()
appPreferences.userReportExpandedView.toggle()
loadDataSource()
}
@@ -339,10 +338,11 @@ class SegnalazioniMapViewController: EQNBaseMapViewController {
return nil
}
let identifier = showAnnotationTime ? EQNCustomAnnotationView.SingleLineIdentifier : EQNCustomAnnotationView.SmallIdentifier
let identifier = appPreferences.userReportExpandedView ? EQNCustomAnnotationView.SingleLineIdentifier : EQNCustomAnnotationView.SmallIdentifier
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as! EQNCustomAnnotationView
annotationView.image = annotation.image
let size = appPreferences.userReportExpandedView ? EQNCustomAnnotationView.SingleLineImageHeight : EQNCustomAnnotationView.SmallViewImageHeight
annotationView.image = annotation.image(with: size)
annotationView.title = annotation.timeDifference
annotationView.canShowCallout = true
// Psizioniamo più in alto le segnalazioni con intensità maggiore.
@@ -204,7 +204,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
private func setupUI() {
selectionStyle = .default
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear
// container view
+1
View File
@@ -75,6 +75,7 @@ static NSString * const EQNUserDefaultLastLocation = @"EQNLast_Location";
static NSString * const EQNUserDefaultSeismicNetworkCards = @"EQNData.RetiSismiche";
static NSString * const EQNUserDefaultRealTimeAlertPayload = @"EQNData.RealtimeAlertPayload";
static NSString * const EQNUserDefaultRealTimeAlertDate = @"EQNData.RealtimeAlertDate";
static NSString * const EQNUserDefaultUserReportExpandedView = @"EQNData.UserReportExpandedView";
static NSString * const EQNUserDefaultMigrationV5_3 = @"EQNUserDefaultMigrationV5_3";
+26
View File
@@ -78,5 +78,31 @@
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb1444404982546319</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>1444404982546319</string>
<key>FacebookClientToken</key>
<string>46c7a338b2bbd2186b2f1c12865b4004</string>
<key>FacebookDisplayName</key>
<string>Earthquake Network</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-share-api</string>
</array>
<key>FacebookAutoLogAppEventsEnabled</key>
<true/>
<key>FacebookAdvertiserIDCollectionEnabled</key>
<true/>
<key>NSUserTrackingUsageDescription</key>
<string>Il tracciamento serve a capire se la pubblicità dell'app è efficace</string>
</dict>
</plist>
@@ -0,0 +1,31 @@
//
// AppPreferences.swift
// Earthquake Network
//
// Created by Andrea Busi on 17/11/22.
// Copyright © 2022 Earthquake Network. All rights reserved.
//
import Foundation
@objc
class AppPreferences: NSObject {
@objc
static let shared = AppPreferences()
// MARK: - Public
/// Defines if time has to be shown on map annotations in User Reports
var userReportExpandedView: Bool {
get { UserDefaults.standard.bool(forKey: EQNUserDefaultUserReportExpandedView) }
set { UserDefaults.standard.set(newValue, forKey: EQNUserDefaultUserReportExpandedView) }
}
@objc
var alertsShowAllCards: Bool {
get { UserDefaults.standard.bool(forKey: EQNUserDefaultKeyAlertsShowAllCards) }
set { UserDefaults.standard.set(newValue, forKey: EQNUserDefaultKeyAlertsShowAllCards) }
}
}
@@ -17,9 +17,9 @@ class EQNMapAnnotationUserReport: NSObject, MKAnnotation {
@objc var coordinate: CLLocationCoordinate2D
@objc var title: String?
@objc var subtitle: String?
@objc var image: UIImage?
@objc var timeDifference: String?
private let magnitude: Int
var report: EQNSegnalazione?
// MARK: - Init
@@ -37,21 +37,24 @@ class EQNMapAnnotationUserReport: NSObject, MKAnnotation {
magnitude: Int,
coordinate: CLLocationCoordinate2D
) {
self.magnitude = magnitude
self.coordinate = coordinate
self.title = Self.title(for: magnitude)
self.subtitle = Self.subtitle(for: magnitude)
self.coordinate = coordinate
self.image = Self.image(for: magnitude)
}
// MARK: - Helper
private static func image(for magnitute: Int) -> UIImage? {
guard let color = UIColor(named: "Mercalli \(magnitute)") else {
print("[EQNMapAnnotationUserReport] Unable to get a color for magnitude: \(magnitute)")
@objc(imageWithHeight:)
func image(
with height: CGFloat
) -> UIImage? {
guard let color = UIColor(named: "Mercalli \(magnitude)") else {
print("[EQNMapAnnotationUserReport] Unable to get a color for magnitude: \(magnitude)")
return nil
}
return UIImage.circle(diameter: EQNCustomAnnotationView.SmallHeight, color: color, borderWidth: 1.0, borderColor: .darkGray)
return UIImage.circle(diameter: height, color: color, borderWidth: 1.0, borderColor: .black)
}
private static func title(for magnitude: Int) -> String {
@@ -2032,19 +2032,19 @@ Sisma rilevato da 10 smartphone</string>
<rect key="frame" x="0.0" y="0.0" width="414" height="190"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1qM-9D-X99">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1qM-9D-X99">
<rect key="frame" x="8" y="8" width="398" height="174"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="No real time alert recently received by your smartphone" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqv-yY-TAs">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No real time alert recently received by your smartphone" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqv-yY-TAs">
<rect key="frame" x="8" y="8" width="382" height="62"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" red="0.047058823529411764" green="0.62745098039215685" blue="0.13725490196078433" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="R9F-ba-WMK">
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="R9F-ba-WMK">
<rect key="frame" x="8" y="78" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BjK-4E-Vhw" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BjK-4E-Vhw" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="TEST ALERT 🚨">
@@ -2054,7 +2054,7 @@ Sisma rilevato da 10 smartphone</string>
<action selector="testAlertTapped" destination="vSa-gk-t22" eventType="touchUpInside" id="HNp-eo-vpW"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="195" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="SIMULATOR ⏱">
@@ -2069,10 +2069,10 @@ Sisma rilevato da 10 smartphone</string>
<constraint firstAttribute="height" constant="40" id="EgR-4H-j5l"/>
</constraints>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ETL-qq-Abj">
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ETL-qq-Abj">
<rect key="frame" x="8" y="126" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aAC-Wz-fKA" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aAC-Wz-fKA" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="HOW IT WORKS 💡">
@@ -2082,7 +2082,7 @@ Sisma rilevato da 10 smartphone</string>
<action selector="howItWorksTapped" destination="vSa-gk-t22" eventType="touchUpInside" id="kLj-v8-6JR"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tml-Pn-Faa" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tml-Pn-Faa" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="195" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="SHARE APP 👥">
@@ -2137,10 +2137,10 @@ Sisma rilevato da 10 smartphone</string>
<rect key="frame" x="0.0" y="0.0" width="414" height="160"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8aY-un-i0P">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8aY-un-i0P">
<rect key="frame" x="8" y="8" width="398" height="144"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Past seismic alerts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="13" translatesAutoresizingMaskIntoConstraints="NO" id="qss-8q-f70" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Past seismic alerts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="13" translatesAutoresizingMaskIntoConstraints="NO" id="qss-8q-f70" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="146" height="26"/>
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
@@ -2150,16 +2150,16 @@ Sisma rilevato da 10 smartphone</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" distribution="fillEqually" alignment="center" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Wn0-ni-ud8">
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Wn0-ni-ud8">
<rect key="frame" x="134" y="34" width="130.5" height="54"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Last 24h: 0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hbH-vC-Yma">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Last 24h: 0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hbH-vC-Yma">
<rect key="frame" x="11.5" y="0.0" width="107.5" height="25"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Since 2013: 0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l5q-I9-iOb">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Since 2013: 0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l5q-I9-iOb">
<rect key="frame" x="0.0" y="29" width="130.5" height="25"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" name="Gray (dark)"/>
@@ -2167,7 +2167,7 @@ Sisma rilevato da 10 smartphone</string>
</label>
</subviews>
</stackView>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="o3D-zn-NCG" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="o3D-zn-NCG" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="8" y="96" width="382" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="I5V-bX-rod"/>
@@ -2216,10 +2216,10 @@ Sisma rilevato da 10 smartphone</string>
<rect key="frame" x="0.0" y="0.0" width="414" height="170"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ahE-3v-miX">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ahE-3v-miX">
<rect key="frame" x="8" y="8" width="398" height="154"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Smartphone network" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ngu-Uw-4wO" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Smartphone network" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ngu-Uw-4wO" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="164" height="26"/>
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
@@ -2229,24 +2229,24 @@ Sisma rilevato da 10 smartphone</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" distribution="fillProportionally" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="niE-pg-jos">
<rect key="frame" x="8" y="34" width="382" height="64"/>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillProportionally" translatesAutoresizingMaskIntoConstraints="NO" id="niE-pg-jos">
<rect key="frame" x="8" y="30" width="382" height="72"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" tag="10" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r3y-EB-oyz">
<rect key="frame" x="0.0" y="0.0" width="382" height="31.5"/>
<label opaque="NO" userInteractionEnabled="NO" tag="10" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r3y-EB-oyz">
<rect key="frame" x="0.0" y="0.0" width="382" height="37"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<color key="textColor" red="0.0039215686274509803" green="0.70588235294117641" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="smartphones are monitoring for earthquakes" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dnR-12-9yN">
<rect key="frame" x="0.0" y="35.5" width="382" height="28.5"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="smartphones are monitoring for earthquakes" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dnR-12-9yN">
<rect key="frame" x="0.0" y="37" width="382" height="35"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<button opaque="NO" tag="200" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Pkb-ih-spD" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<button opaque="NO" tag="200" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Pkb-ih-spD" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="8" y="106" width="382" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="QAZ-gl-lSE"/>
@@ -2267,9 +2267,9 @@ Sisma rilevato da 10 smartphone</string>
<constraint firstAttribute="trailing" secondItem="Ngu-Uw-4wO" secondAttribute="trailing" priority="250" id="EOC-za-7F4"/>
<constraint firstAttribute="trailing" secondItem="niE-pg-jos" secondAttribute="trailing" constant="8" id="Ntr-m9-veW"/>
<constraint firstItem="niE-pg-jos" firstAttribute="leading" secondItem="ahE-3v-miX" secondAttribute="leading" constant="8" id="S5y-GR-Zra"/>
<constraint firstItem="Pkb-ih-spD" firstAttribute="top" secondItem="niE-pg-jos" secondAttribute="bottom" constant="8" id="ed8-Gm-NMS"/>
<constraint firstItem="Pkb-ih-spD" firstAttribute="top" secondItem="niE-pg-jos" secondAttribute="bottom" constant="4" id="ed8-Gm-NMS"/>
<constraint firstItem="Ngu-Uw-4wO" firstAttribute="leading" secondItem="ahE-3v-miX" secondAttribute="leading" id="ggT-NO-C0P"/>
<constraint firstItem="niE-pg-jos" firstAttribute="top" secondItem="Ngu-Uw-4wO" secondAttribute="bottom" constant="8" id="hlw-bV-hHd"/>
<constraint firstItem="niE-pg-jos" firstAttribute="top" secondItem="Ngu-Uw-4wO" secondAttribute="bottom" constant="4" id="hlw-bV-hHd"/>
<constraint firstItem="Pkb-ih-spD" firstAttribute="leading" secondItem="ahE-3v-miX" secondAttribute="leading" constant="8" id="htT-dX-lAU"/>
<constraint firstAttribute="bottom" secondItem="Pkb-ih-spD" secondAttribute="bottom" constant="8" id="xtX-bh-EPd"/>
</constraints>
@@ -2298,10 +2298,10 @@ Sisma rilevato da 10 smartphone</string>
<rect key="frame" x="0.0" y="0.0" width="414" height="170"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GF8-ah-qqT">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GF8-ah-qqT">
<rect key="frame" x="8" y="8" width="398" height="154"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Priority service" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JeR-MS-yEq" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Priority service" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JeR-MS-yEq" customClass="EQNEdgeInsetLabel" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="117.5" height="26"/>
<color key="backgroundColor" red="0.50766238939999997" green="0.75272958739999996" blue="0.98132258650000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
@@ -2311,31 +2311,31 @@ Sisma rilevato da 10 smartphone</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" ambiguous="YES" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="zHS-h1-Tdo">
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="zHS-h1-Tdo">
<rect key="frame" x="8" y="34" width="284" height="112"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Be the first to be alerted when a quake is detected real time." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1mF-xh-GVj">
<rect key="frame" x="0.0" y="0.0" width="284" height="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Be the first to be alerted when a quake is detected real time." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1mF-xh-GVj">
<rect key="frame" x="0.0" y="0.0" width="284" height="42.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="A user has subscribed to the service only %d minute ago!" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3dQ-Eh-0Iw">
<rect key="frame" x="0.0" y="76" width="284" height="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="A user has subscribed to the service only %d minute ago!" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3dQ-Eh-0Iw">
<rect key="frame" x="0.0" y="69.5" width="284" height="42.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" name="Red"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="priority" translatesAutoresizingMaskIntoConstraints="NO" id="3Hs-fb-4gz">
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="priority" translatesAutoresizingMaskIntoConstraints="NO" id="3Hs-fb-4gz">
<rect key="frame" x="296" y="8" width="98" height="95"/>
<constraints>
<constraint firstAttribute="width" constant="98" id="e82-JS-FuC"/>
<constraint firstAttribute="height" constant="95" id="jV5-l5-FhY"/>
</constraints>
</imageView>
<button opaque="NO" tag="10" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fko-1v-doJ">
<button opaque="NO" tag="10" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fko-1v-doJ">
<rect key="frame" x="296" y="29.5" width="94" height="95"/>
<constraints>
<constraint firstAttribute="width" constant="94" id="f5j-RJ-bnc"/>
@@ -2624,43 +2624,43 @@ Sisma rilevato da 10 smartphone</string>
<color red="0.10999999940395355" green="0.13300000131130219" blue="0.14900000393390656" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Light blue">
<color red="0.50588235294117645" green="0.75294117647058822" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.50599998235702515" green="0.75300002098083496" blue="0.98000001907348633" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 100">
<color red="0.792156862745098" green="0.15294117647058825" blue="0.14901960784313725" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.79199999570846558" green="0.15299999713897705" blue="0.14900000393390656" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 110">
<color red="0.8666666666666667" green="0.066666666666666666" blue="0.32941176470588235" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.86699998378753662" green="0.067000001668930054" blue="0.32899999618530273" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 120">
<color red="0.792156862745098" green="0.023529411764705882" blue="0.52941176470588236" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.79199999570846558" green="0.024000000208616257" blue="0.52899998426437378" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 20">
<color red="0.92941176470588238" green="0.93725490196078431" blue="0.95294117647058818" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.92900002002716064" green="0.93699997663497925" blue="0.95300000905990601" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 30">
<color red="0.74901960784313726" green="0.7686274509803922" blue="0.85098039215686272" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.74900001287460327" green="0.76899999380111694" blue="0.85100001096725464" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 40">
<color red="0.6705882352941176" green="0.84313725490196079" blue="0.8901960784313725" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.67100000381469727" green="0.84299999475479126" blue="0.88999998569488525" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 50">
<color red="0.59607843137254901" green="0.78431372549019607" blue="0.56470588235294117" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.59600001573562622" green="0.7839999794960022" blue="0.56499999761581421" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 60">
<color red="0.96078431372549022" green="0.92549019607843142" blue="0.13725490196078433" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.96100002527236938" green="0.92500001192092896" blue="0.13699999451637268" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 70">
<color red="0.93725490196078431" green="0.76470588235294112" blue="0.058823529411764705" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.93699997663497925" green="0.76499998569488525" blue="0.059000000357627869" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 80">
<color red="0.8666666666666667" green="0.52941176470588236" blue="0.14509803921568629" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.86699998378753662" green="0.52899998426437378" blue="0.14499999582767487" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Mercalli 90">
<color red="0.81960784313725488" green="0.32941176470588235" blue="0.14117647058823529" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.81999999284744263" green="0.32899999618530273" blue="0.14100000262260437" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Red">
<color red="1" green="0.14901960784313725" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="1" green="0.14900000393390656" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="groupTableViewBackgroundColor">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -17,9 +17,14 @@ public class EQNCustomAnnotationView: MKAnnotationView {
@objc static let SingleLineIdentifier = "EQNCustomAnnotationViewSingleLine"
@objc static let DoubleLineIdentifier = "EQNCustomAnnotationViewDoubleLine"
static let SmallHeight: CGFloat = 12.0
private static let HeightLabel: CGFloat = 15.0
@objc static let SmallViewHeight: CGFloat = 12.0
@objc static let SmallViewImageHeight: CGFloat = SmallViewHeight
@objc static let SingleLineViewHeight: CGFloat = 40.0
@objc static let SingleLineLabelHeight: CGFloat = 15.0
@objc static let SingleLineImageHeight: CGFloat = SingleLineViewHeight - SingleLineLabelHeight
@objc static let DoubleLineViewHeight: CGFloat = 55.0
@objc static let DoubleLineLabelHeight: CGFloat = 15.0
@objc static let DoubleLineImageHeight: CGFloat = DoubleLineViewHeight - 2*DoubleLineLabelHeight
// MARK: - Public
@@ -70,13 +75,13 @@ public class EQNCustomAnnotationView: MKAnnotationView {
backgroundColor = .clear
if reuseIdentifier == Self.SmallIdentifier {
frame = CGRect(x: 0, y: 0, width: Self.SmallHeight, height: Self.SmallHeight)
frame = CGRect(x: 0, y: 0, width: Self.SmallViewHeight, height: Self.SmallViewHeight)
setupSmallUI()
} else if reuseIdentifier == Self.SingleLineIdentifier {
frame = CGRect(x: 0, y: 0, width: 40, height: 40)
frame = CGRect(x: 0, y: 0, width: Self.SingleLineViewHeight, height: Self.SingleLineViewHeight)
setupSingleLineUI()
} else if reuseIdentifier == Self.DoubleLineIdentifier {
frame = CGRect(x: 0, y: 0, width: 40, height: 55)
frame = CGRect(x: 0, y: 0, width: 40, height: Self.DoubleLineViewHeight)
setupDoubleLineUI()
}
}
@@ -93,7 +98,7 @@ public class EQNCustomAnnotationView: MKAnnotationView {
}
private func setupSingleLineUI() {
let labelFrame = CGRect(x: 0, y: 0, width: frame.width, height: Self.HeightLabel)
let labelFrame = CGRect(x: 0, y: 0, width: frame.width, height: Self.SingleLineLabelHeight)
labelTop.frame = labelFrame
addSubview(labelTop)
@@ -101,12 +106,12 @@ public class EQNCustomAnnotationView: MKAnnotationView {
imageView.frame = CGRect(x: 0, y: labelFrame.height, width: frame.width, height: imageViewHeight)
addSubview(imageView)
let yOffeset = frame.height / 2.0 - (Self.HeightLabel + imageViewHeight / 2.0)
let yOffeset = frame.height / 2.0 - (Self.SingleLineLabelHeight + imageViewHeight / 2.0)
centerOffset = CGPoint(x: 0, y: yOffeset)
}
private func setupDoubleLineUI() {
let labelTopFrame = CGRect(x: 0, y: 0, width: frame.width, height: Self.HeightLabel)
let labelTopFrame = CGRect(x: 0, y: 0, width: frame.width, height: Self.DoubleLineLabelHeight)
labelTop.frame = labelTopFrame
addSubview(labelTop)
@@ -114,7 +119,7 @@ public class EQNCustomAnnotationView: MKAnnotationView {
imageView.frame = CGRect(x: 0, y: labelTopFrame.height, width: frame.width, height: imageViewHeight)
addSubview(imageView)
labelBottom.frame = CGRect(x: 0, y: imageView.frame.maxY, width: frame.width, height: Self.HeightLabel)
labelBottom.frame = CGRect(x: 0, y: imageView.frame.maxY, width: frame.width, height: Self.DoubleLineLabelHeight)
addSubview(labelBottom)
}
}
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Απαιτείται πρόσβαση στη βιβλιοθήκη για να αποθηκεύσετε τις εικόνες που δημιουργούνται από την εφαρμογή";
"NSCalendarsUsageDescription" = "Απαιτείται πρόσβαση στο ημερολόγιο προκειμένου να σωθούν οι πληροφορίες των σεισμών ενδιαφέροντος";
"NSContactsUsageDescription" = "Απαιτείται πρόσβαση στις επαφές για να προσθέσετε άτομα στα δημιουργημένα συμβάντα";
"NSUserTrackingUsageDescription" = "Η παρακολούθηση χρησιμοποιείται για να κατανοήσουμε εάν η διαφήμιση της εφαρμογής είναι αποτελεσματική";
"CFBundleDisplayName" = "Ανιχνευτής Σεισμών";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Access to the library is required in order to save the images generated by the app";
"NSCalendarsUsageDescription" = "Access to the calendar is required in order to save the information of the earthquakes of interest";
"NSContactsUsageDescription" = "Access to contacts is required in order to add people to the created events";
"NSUserTrackingUsageDescription" = "Tracking is used to understand if the advertising of the app is effective";
"CFBundleDisplayName" = "Earthquake Network";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Se requiere acceso a la biblioteca para guardar las imágenes generadas por la aplicación";
"NSCalendarsUsageDescription" = "Se requiere acceso al calendario para guardar la información de los terremotos de interés";
"NSContactsUsageDescription" = "Se requiere acceso a los contactos para agregar personas a los eventos creados";
"NSUserTrackingUsageDescription" = "El seguimiento se utiliza para comprender si la publicidad de la aplicación es efectiva";
"CFBundleDisplayName" = "Sismos Detector";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "L'accès à la bibliothèque est nécessaire pour enregistrer les images générées par l'application";
"NSCalendarsUsageDescription" = "L'accès au calendrier est nécessaire afin de sauvegarder les informations des tremblements de terre d'intérêt";
"NSContactsUsageDescription" = "L'accès aux contacts est requis pour ajouter des personnes aux événements créés";
"NSUserTrackingUsageDescription" = "Le suivi est utilisé pour comprendre si la publicité de l'application est efficace";
"CFBundleDisplayName" = "Détecteur de Séisme";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Pristup knjižnici potreban je kako biste spremili slike generirane u aplikaciji";
"NSCalendarsUsageDescription" = "Pristup kalendaru potreban je kako bi se sačuvale informacije o potresima od interesa";
"NSContactsUsageDescription" = "Pristup kontaktima potreban je kako biste dodali ljude u stvorene događaje";
"NSUserTrackingUsageDescription" = "Praćenje se koristi kako bi se shvatilo je li oglašavanje aplikacije učinkovito";
"CFBundleDisplayName" = "Detektor Potresa";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Akses ke perpustakaan diperlukan untuk menyimpan gambar yang dihasilkan oleh aplikasi";
"NSCalendarsUsageDescription" = "Akses ke kalender diperlukan untuk menyimpan informasi gempa yang menarik";
"NSContactsUsageDescription" = "Akses ke kontak diperlukan untuk menambahkan orang ke acara yang dibuat";
"NSUserTrackingUsageDescription" = "Pelacakan digunakan untuk memahami apakah iklan aplikasi efektif";
"CFBundleDisplayName" = "Detektor Gempa";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "L'accesso alla libreria è richiesto per poter salvare le immagini generate dall'app";
"NSCalendarsUsageDescription" = "L'accesso al calendario è richiesto per poter salvare le informazioni dei sismi di interesse";
"NSContactsUsageDescription" = "L'accesso ai contatti è richiesto per poter aggiungere persone agli eventi creati";
"NSUserTrackingUsageDescription" = "Il tracciamento serve a capire se la pubblicità dell'app è efficace";
"CFBundleDisplayName" = "Rilevatore Terremoto";
@@ -4,4 +4,5 @@
"NSPhotoLibraryAddUsageDescription" = "Uygulama tarafından oluşturulan görüntüleri kaydetmek için kitaplığa erişim gereklidir";
"NSCalendarsUsageDescription" = "İlgili depremlere ait bilgilerin kaydedilebilmesi için takvime erişim gereklidir.";
"NSContactsUsageDescription" = "Kişileri oluşturulan etkinliklere eklemek için kişilere erişim gereklidir";
"NSUserTrackingUsageDescription" = "İzleme, uygulamanın reklamının etkili olup olmadığını anlamak için kullanılır";
"CFBundleDisplayName" = "Deprem Ağı";
+1
View File
@@ -8,6 +8,7 @@ target 'Earthquake Network' do
pod 'Firebase/Messaging'
pod 'Firebase/Crashlytics'
pod 'Google-Mobile-Ads-SDK'
pod 'FBSDKCoreKit'
pod 'DZNEmptyDataSet'
pod 'Solar'
end
+14 -1
View File
@@ -1,5 +1,11 @@
PODS:
- DZNEmptyDataSet (1.8.1)
- FBAEMKit (15.1.0):
- FBSDKCoreKit_Basics (= 15.1.0)
- FBSDKCoreKit (15.1.0):
- FBAEMKit (= 15.1.0)
- FBSDKCoreKit_Basics (= 15.1.0)
- FBSDKCoreKit_Basics (15.1.0)
- Firebase/Core (10.1.0):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 10.1.0)
@@ -113,6 +119,7 @@ PODS:
DEPENDENCIES:
- DZNEmptyDataSet
- FBSDKCoreKit
- Firebase/Core
- Firebase/Crashlytics
- Firebase/Messaging
@@ -122,6 +129,9 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- DZNEmptyDataSet
- FBAEMKit
- FBSDKCoreKit
- FBSDKCoreKit_Basics
- Firebase
- FirebaseAnalytics
- FirebaseCore
@@ -140,6 +150,9 @@ SPEC REPOS:
SPEC CHECKSUMS:
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
FBAEMKit: c7f82b5145d446bcbbcd50485c032689032fc6a2
FBSDKCoreKit: 7542746fc63a2a38dd6a865eeb54268341f37b83
FBSDKCoreKit_Basics: 92d6b26c0bed30ab09bbdd96dccaa26e6c9978d1
Firebase: 444b35a9c568a516666213c2f6cccd10cb12559f
FirebaseAnalytics: 24cb27b52b2e11ad5013528195b4ca0755dec960
FirebaseCore: 55e7ae35991ccca4db03ff8d8df6ed5f17a3e4c7
@@ -156,6 +169,6 @@ SPEC CHECKSUMS:
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
Solar: 2dc6e7cc39186cb0c8228fa08df76fb50c7d8f24
PODFILE CHECKSUM: dd5131b6d7a83fb7c22ecc161ed4fc143eda0ac1
PODFILE CHECKSUM: 8ea8b5074e46a5d9288cef7a482f8c5bebe2d6e2
COCOAPODS: 1.11.3