Query notifications in background fetch

This will show a local notification in case we missed a push notification

Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
This commit is contained in:
Marcel Müller 2022-08-19 00:22:25 +02:00 коммит произвёл Ivan Sein
Родитель 0ce79b16b9
Коммит ddaf76f385
6 изменённых файлов: 124 добавлений и 9 удалений

Просмотреть файл

@ -400,6 +400,17 @@
[NCUtils log:@"Start performBackgroundFetchWithCompletionHandler"];
dispatch_group_enter(backgroundRefreshGroup);
[[NCNotificationController sharedInstance] checkForNewNotificationsWithCompletionBlock:^(NSError *error) {
[NCUtils log:@"CompletionHandler checkForNewNotificationsWithCompletionBlock"];
if (error) {
errorOccurred = YES;
}
dispatch_group_leave(backgroundRefreshGroup);
}];
dispatch_group_enter(backgroundRefreshGroup);
[[NCRoomsManager sharedInstance] updateRoomsAndChatsUpdatingUserStatus:NO withCompletionBlock:^(NSError *error) {
[NCUtils log:@"CompletionHandler updateRoomsAndChatsUpdatingUserStatus"];

Просмотреть файл

@ -27,11 +27,14 @@
extern NSString * const NCNotificationControllerWillPresentNotification;
extern NSString * const NCLocalNotificationJoinChatNotification;
typedef void (^CheckForNewNotificationsWithCompletionBlock)(NSError *error);
typedef enum {
kNCLocalNotificationTypeMissedCall = 1,
kNCLocalNotificationTypeCancelledCall,
kNCLocalNotificationTypeFailedSendChat,
kNCLocalNotificationTypeCallFromOldAccount
kNCLocalNotificationTypeCallFromOldAccount,
kNCLocalNotificationTypeChatNotification
} NCLocalNotificationType;
@interface NCNotificationController : NSObject
@ -44,5 +47,6 @@ typedef enum {
- (void)showIncomingCallForPushNotification:(NCPushNotification *)pushNotification;
- (void)showIncomingCallForOldAccount;
- (void)removeAllNotificationsForAccountId:(NSString *)accountId;
- (void)checkForNewNotificationsWithCompletionBlock:(CheckForNewNotificationsWithCompletionBlock)block;
@end

Просмотреть файл

@ -180,6 +180,32 @@ NSString * const NCLocalNotificationJoinChatNotification = @"NCLocalN
[[CallKitManager sharedInstance] reportIncomingCallForOldAccount];
}
- (void)showLocalNotificationForChatNotification:(NCNotification *)notification forAccountId:(NSString *)accountId
{
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = notification.chatMessageTitle;
content.body = notification.message;
content.summaryArgument = notification.chatMessageAuthor;
content.threadIdentifier = notification.roomToken;
content.sound = [UNNotificationSound defaultSound];
// Currently not supported for local notifications
//content.categoryIdentifier = @"CATEGORY_CHAT";
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:notification.roomToken forKey:@"roomToken"];
[userInfo setObject:accountId forKey:@"accountId"];
[userInfo setValue:@(kNCLocalNotificationTypeChatNotification) forKey:@"localNotificationType"];
content.userInfo = userInfo;
NSString *identifier = [NSString stringWithFormat:@"ChatNotification-%ld", notification.notificationId];
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
[_notificationCenter addNotificationRequest:request withCompletionHandler:nil];
[[NCDatabaseManager sharedInstance] increaseUnreadBadgeNumberForAccountId:accountId];
[self updateAppIconBadgeNumber];
}
- (void)updateAppIconBadgeNumber
{
dispatch_async(dispatch_get_main_queue(), ^{
@ -255,6 +281,70 @@ NSString * const NCLocalNotificationJoinChatNotification = @"NCLocalN
[self updateAppIconBadgeNumber];
}
- (void)checkForNewNotificationsWithCompletionBlock:(CheckForNewNotificationsWithCompletionBlock)block
{
dispatch_group_t notificationsGroup = dispatch_group_create();
for (TalkAccount *account in [TalkAccount allObjects]) {
ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
if (!serverCapabilities || !serverCapabilities.notificationsAppEnabled) {
continue;
}
dispatch_group_enter(notificationsGroup);
[[NCAPIController sharedInstance] getServerNotificationsForAccount:account withLastETag:account.lastNotificationETag withCompletionBlock:^(NSArray *notifications, NSString* ETag, NSError *error) {
if (error) {
dispatch_group_leave(notificationsGroup);
return;
}
NSInteger lastNotificationId = 0;
for (NSDictionary *notification in notifications) {
NCNotification *serverNotification = [NCNotification notificationWithDictionary:notification];
// Only process chat notifications from Talk
if (!serverNotification || ![serverNotification.app isEqualToString:kNCPNAppIdKey] || serverNotification.notificationType != kNCNotificationTypeChat) {
continue;
}
if (lastNotificationId < serverNotification.notificationId) {
lastNotificationId = serverNotification.notificationId;
}
if (account.lastNotificationId != 0 && serverNotification.notificationId > account.lastNotificationId) {
// Don't show notifications if this is the first time we retrieve notifications for this account
// Otherwise after adding a new account all unread notifications from the server would be shown
[self showLocalNotificationForChatNotification:serverNotification forAccountId:account.accountId];
}
}
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
NSPredicate *query = [NSPredicate predicateWithFormat:@"accountId = %@", account.accountId];
TalkAccount *managedAccount = [TalkAccount objectsWithPredicate:query].firstObject;
managedAccount.lastNotificationETag = ETag;
if (managedAccount.lastNotificationId < lastNotificationId) {
managedAccount.lastNotificationId = lastNotificationId;
}
}];
dispatch_group_leave(notificationsGroup);
}];
}
dispatch_group_notify(notificationsGroup, dispatch_get_main_queue(), ^{
// Notify backgroundFetch that we're finished
if (block) {
block(nil);
}
});
}
#pragma mark - UNUserNotificationCenter delegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
@ -370,6 +460,7 @@ NSString * const NCLocalNotificationJoinChatNotification = @"NCLocalN
case kNCLocalNotificationTypeMissedCall:
case kNCLocalNotificationTypeCancelledCall:
case kNCLocalNotificationTypeFailedSendChat:
case kNCLocalNotificationTypeChatNotification:
{
[[NCUserInterfaceController sharedInstance] presentChatForLocalNotification:notificationUserInfo];
}

Просмотреть файл

@ -34,6 +34,7 @@ typedef NS_ENUM(NSInteger, NCPushNotificationType) {
};
extern NSString * const kNCPNAppKey;
extern NSString * const kNCPNAppIdKey;
extern NSString * const kNCPNTypeKey;
extern NSString * const kNCPNSubjectKey;
extern NSString * const kNCPNIdKey;

Просмотреть файл

@ -55,6 +55,8 @@ NS_ASSUME_NONNULL_BEGIN
@property BOOL hasContactSyncEnabled;
@property BOOL active;
@property NSString *lastReceivedConfigurationHash;
@property NSInteger lastNotificationId;
@property NSString *lastNotificationETag;
@end

Просмотреть файл

@ -111,14 +111,20 @@
}
foundDecryptableMessage = YES;
// Update unread notifications counter for push notification account
[realm beginWriteTransaction];
NSPredicate *query = [NSPredicate predicateWithFormat:@"accountId = %@", account.accountId];
TalkAccount *managedAccount = [TalkAccount objectsInRealm:realm withPredicate:query].firstObject;
managedAccount.unreadBadgeNumber += 1;
managedAccount.unreadNotification = (managedAccount.active) ? NO : YES;
[realm commitWriteTransaction];
[realm transactionWithBlock:^{
NSPredicate *query = [NSPredicate predicateWithFormat:@"accountId = %@", account.accountId];
TalkAccount *managedAccount = [TalkAccount objectsInRealm:realm withPredicate:query].firstObject;
// Update unread notifications counter for push notification account
managedAccount.unreadBadgeNumber += 1;
managedAccount.unreadNotification = (managedAccount.active) ? NO : YES;
// Make sure we don't accidentally show a notification again, when we check for notifications in the background
if (managedAccount.lastNotificationId < pushNotification.notificationId) {
managedAccount.lastNotificationId = pushNotification.notificationId;
}
}];
// Get the total number of unread notifications
NSInteger unreadNotifications = 0;