Do not present local notifications if a read receipt arrives immediately after.

// FREEBIE
pull/1/head
Matthew Chen 7 years ago
parent 0115eb8475
commit b7b5dbb563

@ -136,7 +136,7 @@
}
notification.alertBody = alertBodyString;
[[PushManager sharedManager] presentNotification:notification];
[[PushManager sharedManager] presentNotification:notification checkForCancel:NO];
} else {
if ([Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);
@ -193,7 +193,7 @@
break;
}
[[PushManager sharedManager] presentNotification:notification];
[[PushManager sharedManager] presentNotification:notification checkForCancel:YES];
} else {
if ([Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);

@ -66,7 +66,10 @@ typedef void (^pushTokensSuccessBlock)(NSString *pushToken, NSString *voipToken)
- (TOCFuture *)registerPushKitNotificationFuture;
- (BOOL)supportsVOIPPush;
- (void)presentNotification:(UILocalNotification *)notification;
// If checkForCancel is set, the notification will be delayed for
// a moment. If a relevant cancel notification is received in that window,
// the notification will not be displayed.
- (void)presentNotification:(UILocalNotification *)notification checkForCancel:(BOOL)checkForCancel;
- (void)cancelNotificationsWithThreadId:(NSString *)threadId;
#pragma mark Push Notifications Delegate Methods

@ -23,6 +23,7 @@
@property TOCFutureSource *registerWithServerFutureSource;
@property UIAlertView *missingPermissionsAlertView;
@property (nonatomic, retain) NSMutableArray *currentNotifications;
@property (nonatomic, retain) NSMutableArray *pendingNotifications;
@property (nonatomic) UIBackgroundTaskIdentifier callBackgroundTask;
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) OWSMessageFetcherJob *messageFetcherJob;
@ -75,7 +76,8 @@
cancelButtonTitle:NSLocalizedString(@"OK", @"")
otherButtonTitles:nil, nil];
_callBackgroundTask = UIBackgroundTaskInvalid;
_currentNotifications = [NSMutableArray array];
_currentNotifications = [NSMutableArray new];
_pendingNotifications = [NSMutableArray new];
OWSSingletonAssert();
@ -163,7 +165,7 @@
failedSendNotif.alertBody =
[NSString stringWithFormat:NSLocalizedString(@"NOTIFICATION_SEND_FAILED", nil), [thread name]];
failedSendNotif.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId };
[self presentNotification:failedSendNotif];
[self presentNotification:failedSendNotif checkForCancel:NO];
completionHandler();
}];
}
@ -429,19 +431,61 @@ NSString *const PushManagerUserInfoKeysCallBackSignalRecipientId = @"PushManager
return NO;
}
- (void)presentNotification:(UILocalNotification *)notification {
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
[self.currentNotifications addObject:notification];
- (void)presentNotification:(UILocalNotification *)notification checkForCancel:(BOOL)checkForCancel
{
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 {
OWSAssert([NSThread isMainThread]);
// Cull matching pending notifications.
NSMutableArray *toDelete = [NSMutableArray array];
[self.currentNotifications enumerateObjectsUsingBlock:^(UILocalNotification *notif, NSUInteger idx, BOOL *stop) {
if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) {
[[UIApplication sharedApplication] cancelLocalNotification:notif];
[toDelete addObject:notif];
}
[self.pendingNotifications enumerateObjectsUsingBlock:^(
UILocalNotification *notification, NSUInteger idx, BOOL *stop) {
NSString *notificationThreadId = notification.userInfo[Signal_Thread_UserInfo_Key];
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];
}

Loading…
Cancel
Save