|
|
@ -23,6 +23,7 @@
|
|
|
|
@property TOCFutureSource *registerWithServerFutureSource;
|
|
|
|
@property TOCFutureSource *registerWithServerFutureSource;
|
|
|
|
@property UIAlertView *missingPermissionsAlertView;
|
|
|
|
@property UIAlertView *missingPermissionsAlertView;
|
|
|
|
@property (nonatomic, retain) NSMutableArray *currentNotifications;
|
|
|
|
@property (nonatomic, retain) NSMutableArray *currentNotifications;
|
|
|
|
|
|
|
|
@property (nonatomic, retain) NSMutableArray *pendingNotifications;
|
|
|
|
@property (nonatomic) UIBackgroundTaskIdentifier callBackgroundTask;
|
|
|
|
@property (nonatomic) UIBackgroundTaskIdentifier callBackgroundTask;
|
|
|
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
|
|
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
|
|
|
@property (nonatomic, readonly) OWSMessageFetcherJob *messageFetcherJob;
|
|
|
|
@property (nonatomic, readonly) OWSMessageFetcherJob *messageFetcherJob;
|
|
|
@ -75,7 +76,8 @@
|
|
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
otherButtonTitles:nil, nil];
|
|
|
|
otherButtonTitles:nil, nil];
|
|
|
|
_callBackgroundTask = UIBackgroundTaskInvalid;
|
|
|
|
_callBackgroundTask = UIBackgroundTaskInvalid;
|
|
|
|
_currentNotifications = [NSMutableArray array];
|
|
|
|
_currentNotifications = [NSMutableArray new];
|
|
|
|
|
|
|
|
_pendingNotifications = [NSMutableArray new];
|
|
|
|
|
|
|
|
|
|
|
|
OWSSingletonAssert();
|
|
|
|
OWSSingletonAssert();
|
|
|
|
|
|
|
|
|
|
|
@ -163,7 +165,7 @@
|
|
|
|
failedSendNotif.alertBody =
|
|
|
|
failedSendNotif.alertBody =
|
|
|
|
[NSString stringWithFormat:NSLocalizedString(@"NOTIFICATION_SEND_FAILED", nil), [thread name]];
|
|
|
|
[NSString stringWithFormat:NSLocalizedString(@"NOTIFICATION_SEND_FAILED", nil), [thread name]];
|
|
|
|
failedSendNotif.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId };
|
|
|
|
failedSendNotif.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId };
|
|
|
|
[self presentNotification:failedSendNotif];
|
|
|
|
[self presentNotification:failedSendNotif checkForCancel:NO];
|
|
|
|
completionHandler();
|
|
|
|
completionHandler();
|
|
|
|
}];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -429,19 +431,61 @@ NSString *const PushManagerUserInfoKeysCallBackSignalRecipientId = @"PushManager
|
|
|
|
return NO;
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)presentNotification:(UILocalNotification *)notification {
|
|
|
|
- (void)presentNotification:(UILocalNotification *)notification checkForCancel:(BOOL)checkForCancel
|
|
|
|
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
|
|
|
|
{
|
|
|
|
[self.currentNotifications addObject:notification];
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key];
|
|
|
|
|
|
|
|
if (checkForCancel && threadId != nil) {
|
|
|
|
|
|
|
|
[_pendingNotifications addObject:notification];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The longer we wait, the more obsolete notifications we can suppress -
|
|
|
|
|
|
|
|
// but the more lag we introduce to notification delivery.
|
|
|
|
|
|
|
|
const CGFloat kDelaySeconds = 0.3f;
|
|
|
|
|
|
|
|
dispatch_after(
|
|
|
|
|
|
|
|
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * kDelaySeconds)), dispatch_get_main_queue(), ^{
|
|
|
|
|
|
|
|
if (![_pendingNotifications containsObject:notification]) {
|
|
|
|
|
|
|
|
DDLogVerbose(@"%@ notification was cancelled before it was presented: %@, %@",
|
|
|
|
|
|
|
|
self.tag,
|
|
|
|
|
|
|
|
notification.alertBody,
|
|
|
|
|
|
|
|
threadId);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
[_pendingNotifications removeObject:notification];
|
|
|
|
|
|
|
|
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
|
|
|
|
|
|
|
|
[self.currentNotifications addObject:notification];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
|
|
|
|
|
|
|
|
[self.currentNotifications addObject:notification];
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)cancelNotificationsWithThreadId:(NSString *)threadId {
|
|
|
|
- (void)cancelNotificationsWithThreadId:(NSString *)threadId {
|
|
|
|
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cull matching pending notifications.
|
|
|
|
NSMutableArray *toDelete = [NSMutableArray array];
|
|
|
|
NSMutableArray *toDelete = [NSMutableArray array];
|
|
|
|
[self.currentNotifications enumerateObjectsUsingBlock:^(UILocalNotification *notif, NSUInteger idx, BOOL *stop) {
|
|
|
|
[self.pendingNotifications enumerateObjectsUsingBlock:^(
|
|
|
|
if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) {
|
|
|
|
UILocalNotification *notification, NSUInteger idx, BOOL *stop) {
|
|
|
|
[[UIApplication sharedApplication] cancelLocalNotification:notif];
|
|
|
|
NSString *notificationThreadId = notification.userInfo[Signal_Thread_UserInfo_Key];
|
|
|
|
[toDelete addObject:notif];
|
|
|
|
OWSAssert(notificationThreadId != nil);
|
|
|
|
}
|
|
|
|
if ([notificationThreadId isEqualToString:threadId]) {
|
|
|
|
|
|
|
|
DDLogError(@"%@ cancelling delayed notification: %@, %@", self.tag, notification.alertBody, threadId);
|
|
|
|
|
|
|
|
[toDelete addObject:notification];
|
|
|
|
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
}];
|
|
|
|
|
|
|
|
[self.pendingNotifications removeObjectsInArray:toDelete];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cull matching active notifications.
|
|
|
|
|
|
|
|
[toDelete removeAllObjects];
|
|
|
|
|
|
|
|
[self.currentNotifications
|
|
|
|
|
|
|
|
enumerateObjectsUsingBlock:^(UILocalNotification *notification, NSUInteger idx, BOOL *stop) {
|
|
|
|
|
|
|
|
if ([notification.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) {
|
|
|
|
|
|
|
|
[[UIApplication sharedApplication] cancelLocalNotification:notification];
|
|
|
|
|
|
|
|
[toDelete addObject:notification];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}];
|
|
|
|
[self.currentNotifications removeObjectsInArray:toDelete];
|
|
|
|
[self.currentNotifications removeObjectsInArray:toDelete];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|