Files
eqn.ios/Sources/EQNNotificationContent/NotificationViewController.m
T

166 lines
6.3 KiB
Objective-C

//
// NotificationViewController.m
// EQNNotificationContent
//
// Refactored by Andrea Busi on 14/10/2020.
// Copyright © 2020 Earthquake Network. All rights reserved.
//
#import "NotificationViewController.h"
#import "PastquakesAnnotation.h"
#import "ReteSismicaAnnotation.h"
#import "EQNUtility.h"
@import UserNotifications;
@import UserNotificationsUI;
@import MapKit;
@interface NotificationViewController () <UNNotificationContentExtension, MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
@property (weak, nonatomic) IBOutlet UILabel *waveLabel;
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/// This will be calculated as seismic date + warning time
@property (strong, nonatomic) NSDate *userSeismicTimestamp;
@property (strong, nonatomic) NSTimer *countdownTimer;
@end
@implementation NotificationViewController
- (void)setMapView:(MKMapView *)mapView
{
_mapView = mapView;
_mapView.scrollEnabled = NO;
_mapView.zoomEnabled = NO;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any required interface initialization here.
}
- (void)didReceiveNotification:(UNNotification *)notification
{
UNNotificationContent *content = notification.request.content;
NSDictionary *userInfo = content.userInfo;
// set title and description
self.titleLabel.text = content.title;
self.descriptionLabel.text = content.body;
// add annotation onthe map
CLLocation *coordinate = [[CLLocation alloc] initWithLatitude:[userInfo[@"latitude"] doubleValue]
longitude:[userInfo[@"longitude"] doubleValue]];
MKCoordinateSpan span = MKCoordinateSpanMake(10.5, 10.5);
MKCoordinateRegion region = MKCoordinateRegionMake(coordinate.coordinate, span);
[self.mapView setCenterCoordinate:coordinate.coordinate animated:NO];
[self.mapView setRegion:region animated:YES];
if ([userInfo[@"type"] isEqualToString:@"eqn"]) {
PastquakesAnnotation *annotation = [[PastquakesAnnotation alloc] initWithTitle:content.body
location:coordinate.coordinate
intensita:[userInfo[@"intensity"] intValue]];
[self.mapView addAnnotation:annotation];
} else if ([userInfo[@"type"] isEqualToString:@"manual"]){
ReteSismicaAnnotation *annotation = [[ReteSismicaAnnotation alloc] initWithTitle:content.body
location:coordinate.coordinate
magnitudo:[userInfo[@"magnitudo"] intValue]];
[self.mapView addAnnotation:annotation];
}
self.userSeismicTimestamp = [self calculateUserSeismicTimestampWithInfo:userInfo];
if (self.userSeismicTimestamp) {
// start the countdown
self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(countdownFired:)
userInfo:nil
repeats:YES];
[self.countdownTimer fire];
}
}
#pragma mark - Private
- (nullable NSDate *)calculateUserSeismicTimestampWithInfo:(NSDictionary *)info
{
// dobbiamo calcolare l'ora in cui il sisma arriverà nella posizione dell'utente
// per fare questo, il calcolo sarà:
// timestamp sisma + warning time
// ultima posizione nota dell'utente
CLLocationManager *manager = [[CLLocationManager alloc] init];
CLLocation *lastUserLocation = manager.location;
if (!lastUserLocation) {
return nil;
}
// posizione sisma
double latitude = [info[@"latitude"] doubleValue];
double longitude = [info[@"longitude"] doubleValue];
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
// distanza tra sisma e utente (in km)
CLLocationDistance distance = [lastUserLocation distanceFromLocation:location];
double userDistance = distance/1000;
// calcoliamo warning_time
double waveSpeed = [info[@"wave_speed"] doubleValue];
double warningTime = round(userDistance/waveSpeed - 5);
// aggiungiamo il warning time al timestamp del sisma
NSDate *seismicDate = [EQNUtility getDateFromString:info[@"datetime"]];
NSDate *userSeismicDate = [seismicDate dateByAddingTimeInterval:warningTime];
return userSeismicDate;
}
- (void)countdownFired:(id)sender
{
NSDate *now = [NSDate date];
NSTimeInterval difference = MAX([self.userSeismicTimestamp timeIntervalSinceDate:now], 0);
self.waveLabel.text = [NSString stringWithFormat:@"%@ %.0f %@", NSLocalizedString(@"alert_wave", @""), difference, NSLocalizedString(@"alert_seconds", @"")];
if (difference <= 0) {
// stop the countdown
[self.countdownTimer invalidate];
self.countdownTimer = nil;
}
}
#pragma mark - MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[PastquakesAnnotation class]]) {
PastquakesAnnotation *anLocation = (PastquakesAnnotation *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:IDENTIFIER_ANNOTATION_PASTQUAKES];
if (annotationView == nil) {
annotationView = anLocation.annotationView;
} else {
annotationView.annotation = anLocation;
}
return annotationView;
} else if ([annotation isKindOfClass:[ReteSismicaAnnotation class]]) {
ReteSismicaAnnotation *anLocation = (ReteSismicaAnnotation *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:IDENTIFIER_ANNOTATION_RETESMARTPHONE];
if (annotationView == nil) {
annotationView = anLocation.annotationView;
} else {
annotationView.annotation = anLocation;
}
return annotationView;
}
return nil;
}
@end