From a2dd605299eef5020d332d0e3eb8f5395b510349 Mon Sep 17 00:00:00 2001 From: Giom Foret Date: Thu, 19 Oct 2017 16:09:50 +0200 Subject: [PATCH 1/2] PushKit - Enhancement -Don't forget the notifications retrieved during an initial sync in background --- Riot/AppDelegate.m | 225 ++++++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 105 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index b9feae4fe..7615b48a3 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -1101,12 +1101,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN NSLog(@"[AppDelegate] didReceiveIncomingPushWithPayload - Unexpected payload %@", payload.dictionaryPayload); } - // Handle the local notifications by triggering a background sync. - [self handleLocalNotifications]; + // Trigger a background sync to handle notifications. + [self launchBackgroundSync]; } } -- (void)handleLocalNotifications +- (void)launchBackgroundSync { // Launch a background sync for all existing matrix sessions NSArray *mxAccounts = [MXKAccountManager sharedManager].activeAccounts; @@ -1115,7 +1115,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Check the current session state if (account.mxSession.state == MXSessionStatePaused) { - NSLog(@"[AppDelegate] handleLocalNotifications: run a background sync"); + NSLog(@"[AppDelegate] launchBackgroundSync"); __weak typeof(self) weakSelf = self; [account backgroundSync:20000 success:^{ @@ -1127,116 +1127,124 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } typeof(self) self = weakSelf; - NSLog(@"[AppDelegate] handleLocalNotifications: the background sync succeeds"); + NSLog(@"[AppDelegate] launchBackgroundSync: the background sync succeeds"); - // The call invite are handled here only when the callkit is not active. - BOOL isCallKitActive = [MXCallKitAdapter callKitAvailable] && [MXKAppSettings standardAppSettings].isCallKitEnabled; + // Trigger local notifcations + [self handleLocalNotificationsForAccount:account]; - NSMutableArray *eventsArray = eventsToNotify[@(account.mxSession.hash)]; - - // Display a local notification for each event retrieved by the bg sync. - for (NSUInteger index = 0; index < eventsArray.count; index++) - { - NSDictionary *eventDict = eventsArray[index]; - NSString *eventId = eventDict[@"event_id"]; - NSString *roomId = eventDict[@"room_id"]; - BOOL checkReadEvent = YES; - MXEvent *event; - - if (eventId && roomId) - { - event = [account.mxSession.store eventWithEventId:eventId inRoom:roomId]; - } - - if (event) - { - // Ignore redacted event. - if (event.isRedactedEvent) - { - continue; - } - - // Consider here the call invites - if (event.eventType == MXEventTypeCallInvite) - { - // Ignore call invite when callkit is active. - if (isCallKitActive) - { - continue; - } - else - { - // Retrieve the current call state from the call manager - MXCallInviteEventContent *callInviteEventContent = [MXCallInviteEventContent modelFromJSON:event.content]; - MXCall *call = [account.mxSession.callManager callWithCallId:callInviteEventContent.callId]; - - if (call.state <= MXCallStateRinging) - { - // Keep display a local notification even if the event has been read on another device. - checkReadEvent = NO; - } - } - } - - if (checkReadEvent) - { - // Ignore event which has been read on another device. - MXReceiptData *readReceipt = [account.mxSession.store getReceiptInRoom:roomId forUserId:account.mxCredentials.userId]; - if (readReceipt) - { - MXEvent *readReceiptEvent = [account.mxSession.store eventWithEventId:readReceipt.eventId inRoom:roomId]; - if (event.originServerTs <= readReceiptEvent.originServerTs) - { - continue; - } - } - } - - // Prepare the local notification - MXPushRule *rule = eventDict[@"push_rule"]; - - NSString *notificationBody = [self notificationBodyForEvent:event pushRule:rule inAccount:account]; - if (notificationBody) - { - UILocalNotification *eventNotification = [[UILocalNotification alloc] init]; - eventNotification.alertBody = notificationBody; - eventNotification.userInfo = @{ @"room_id" : event.roomId }; - - // Set sound name based on the value provided in action of MXPushRule - for (MXPushRuleAction *action in rule.actions) - { - if (action.actionType == MXPushRuleActionTypeSetTweak) - { - if ([action.parameters[@"set_tweak"] isEqualToString:@"sound"]) - { - NSString *soundName = action.parameters[@"value"]; - if ([soundName isEqualToString:@"default"]) - soundName = UILocalNotificationDefaultSoundName; - - eventNotification.soundName = soundName; - } - } - } - - [[UIApplication sharedApplication] scheduleLocalNotification:eventNotification]; - } - } - } - - [eventsArray removeAllObjects]; - - // Update icon badge number - [UIApplication sharedApplication].applicationIconBadgeNumber = [account.mxSession riot_missedDiscussionsCount]; + // Update app icon badge number + [self refreshApplicationIconBadgeNumber]; } failure:^(NSError *error) { - NSLog(@"[AppDelegate] handleLocalNotifications: the background sync fails"); + NSLog(@"[AppDelegate] launchBackgroundSync: the background sync fails"); }]; } } } +- (void)handleLocalNotificationsForAccount:(MXKAccount*)account +{ + NSLog(@"[AppDelegate] handleLocalNotificationsForAccount: %@", account.mxCredentials.userId); + + // The call invite are handled here only when the callkit is not active. + BOOL isCallKitActive = [MXCallKitAdapter callKitAvailable] && [MXKAppSettings standardAppSettings].isCallKitEnabled; + + NSMutableArray *eventsArray = eventsToNotify[@(account.mxSession.hash)]; + + // Display a local notification for each event retrieved by the bg sync. + for (NSUInteger index = 0; index < eventsArray.count; index++) + { + NSDictionary *eventDict = eventsArray[index]; + NSString *eventId = eventDict[@"event_id"]; + NSString *roomId = eventDict[@"room_id"]; + BOOL checkReadEvent = YES; + MXEvent *event; + + if (eventId && roomId) + { + event = [account.mxSession.store eventWithEventId:eventId inRoom:roomId]; + } + + if (event) + { + // Ignore redacted event. + if (event.isRedactedEvent) + { + continue; + } + + // Consider here the call invites + if (event.eventType == MXEventTypeCallInvite) + { + // Ignore call invite when callkit is active. + if (isCallKitActive) + { + continue; + } + else + { + // Retrieve the current call state from the call manager + MXCallInviteEventContent *callInviteEventContent = [MXCallInviteEventContent modelFromJSON:event.content]; + MXCall *call = [account.mxSession.callManager callWithCallId:callInviteEventContent.callId]; + + if (call.state <= MXCallStateRinging) + { + // Keep display a local notification even if the event has been read on another device. + checkReadEvent = NO; + } + } + } + + if (checkReadEvent) + { + // Ignore event which has been read on another device. + MXReceiptData *readReceipt = [account.mxSession.store getReceiptInRoom:roomId forUserId:account.mxCredentials.userId]; + if (readReceipt) + { + MXEvent *readReceiptEvent = [account.mxSession.store eventWithEventId:readReceipt.eventId inRoom:roomId]; + if (event.originServerTs <= readReceiptEvent.originServerTs) + { + continue; + } + } + } + + // Prepare the local notification + MXPushRule *rule = eventDict[@"push_rule"]; + + NSString *notificationBody = [self notificationBodyForEvent:event pushRule:rule inAccount:account]; + if (notificationBody) + { + UILocalNotification *eventNotification = [[UILocalNotification alloc] init]; + eventNotification.alertBody = notificationBody; + eventNotification.userInfo = @{ @"room_id" : event.roomId }; + + // Set sound name based on the value provided in action of MXPushRule + for (MXPushRuleAction *action in rule.actions) + { + if (action.actionType == MXPushRuleActionTypeSetTweak) + { + if ([action.parameters[@"set_tweak"] isEqualToString:@"sound"]) + { + NSString *soundName = action.parameters[@"value"]; + if ([soundName isEqualToString:@"default"]) + soundName = UILocalNotificationDefaultSoundName; + + eventNotification.soundName = soundName; + } + } + } + + [[UIApplication sharedApplication] scheduleLocalNotification:eventNotification]; + } + } + } + + [eventsArray removeAllObjects]; +} + - (nullable NSString *)notificationBodyForEvent:(MXEvent *)event pushRule:(MXPushRule*)rule inAccount:(MXKAccount*)account { if (!event.content || !event.content.count) @@ -1867,16 +1875,23 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN if (account.mxSession == mxSession) { [account pauseInBackgroundTask]; + + // Trigger local notifcations (Indeed the app finishs here an initial sync in background, the user has missed some notifcations) + [self handleLocalNotificationsForAccount:account]; + + // Update app icon badge number + [self refreshApplicationIconBadgeNumber]; + break; } } } else if (mxSession.state == MXSessionStatePaused) { - // Check whether some local notifications must be handled by triggering a background sync. + // Check whether some push notifications are pending. if (self.incomingPushEventIds.count) { - [self handleLocalNotifications]; + [self launchBackgroundSync]; } } } From 3a99a750430c3e1828a6ceb3de840a9d688c7115 Mon Sep 17 00:00:00 2001 From: Giom Foret Date: Thu, 19 Oct 2017 16:25:59 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Buf=20Fix=20-=20Pushkit=20-=20a=20message?= =?UTF-8?q?=20containing=20=E2=80=9C20%ing=E2=80=9D=20into=20=E2=80=9C20ng?= =?UTF-8?q?=E2=80=9D=20in=20the=20notif?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1594 --- Riot/AppDelegate.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 7615b48a3..fe4fdff91 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -1217,6 +1217,10 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN NSString *notificationBody = [self notificationBodyForEvent:event pushRule:rule inAccount:account]; if (notificationBody) { + // Printf style escape characters are stripped from the string prior to display; + // to include a percent symbol (%) in the message, use two percent symbols (%%). + notificationBody = [notificationBody stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]; + UILocalNotification *eventNotification = [[UILocalNotification alloc] init]; eventNotification.alertBody = notificationBody; eventNotification.userInfo = @{ @"room_id" : event.roomId };