Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32998206
D9144.1768350349.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D9144.1768350349.diff
View Options
diff --git a/native/ios/NotificationService/NotificationService.mm b/native/ios/NotificationService/NotificationService.mm
--- a/native/ios/NotificationService/NotificationService.mm
+++ b/native/ios/NotificationService/NotificationService.mm
@@ -9,6 +9,7 @@
NSString *const messageInfosKey = @"messageInfos";
NSString *const encryptedPayloadKey = @"encryptedPayload";
NSString *const encryptionFailureKey = @"encryptionFailure";
+NSString *const collapseIDKey = @"collapseID";
const std::string callingProcessName = "NSE";
// The context for this constant can be found here:
// https://linear.app/comm/issue/ENG-3074#comment-bd2f5e28
@@ -119,9 +120,11 @@
std::string rescindErrorMessage;
try {
@try {
- [self
- removeNotificationWithIdentifier:content
- .userInfo[@"notificationId"]];
+ [self removeNotificationsWithCondition:^BOOL(
+ UNNotification *_Nonnull notif) {
+ return [content.userInfo[@"notificationId"]
+ isEqualToString:notif.request.content.userInfo[@"id"]];
+ }];
} @catch (NSException *e) {
rescindErrorMessage =
"Obj-C exception: " + std::string([e.name UTF8String]) +
@@ -141,6 +144,38 @@
publicUserContent = [[UNNotificationContent alloc] init];
}
+ // Step 4: (optional) execute notification coalescing
+ if ([self isCollapsible:content.userInfo]) {
+ std::string coalescingErrorMessage;
+ try {
+ @try {
+ [self displayLocalNotificationFromContent:content
+ forCollapseKey:content
+ .userInfo[collapseIDKey]];
+ } @catch (NSException *e) {
+ coalescingErrorMessage =
+ "Obj-C exception: " + std::string([e.name UTF8String]) +
+ " during notification coalescing.";
+ }
+ } catch (const std::exception &e) {
+ coalescingErrorMessage = "C++ exception: " + std::string(e.what()) +
+ " during notification coalescing.";
+ }
+
+ if (coalescingErrorMessage.size()) {
+ [errorMessages
+ addObject:[NSString
+ stringWithUTF8String:coalescingErrorMessage.c_str()]];
+ // Even if we fail to execute coalescing then public users
+ // should still see the original message.
+ publicUserContent = content;
+ } else {
+ publicUserContent = [[UNNotificationContent alloc] init];
+ }
+ }
+
+ // Step 5: (optional) create empty notification that
+ // only provides badge count.
if ([self isBadgeOnly:content.userInfo]) {
UNMutableNotificationContent *badgeOnlyContent =
[[UNMutableNotificationContent alloc] init];
@@ -211,6 +246,23 @@
continue;
}
+ if ([self isCollapsible:content.userInfo]) {
+ // If we get to this place it means we were unable to
+ // execute notification coalescing with local notification
+ // mechanism in time given to NSE to process notification.
+ if (!comm::StaffUtils::isStaffRelease()) {
+ handler(content);
+ continue;
+ }
+
+ NSString *errorMessage =
+ @"NSE: Exceeded time limit to collapse a notitication.";
+ UNNotificationContent *errorContent =
+ [self buildContentForError:errorMessage];
+ handler(errorContent);
+ continue;
+ }
+
if ([self shouldBeDecrypted:content.userInfo] &&
!content.userInfo[@"succesfullyDecrypted"]) {
// If we get to this place it means we were unable to
@@ -243,7 +295,8 @@
}
}
-- (void)removeNotificationWithIdentifier:(NSString *)identifier {
+- (void)removeNotificationsWithCondition:
+ (BOOL (^)(UNNotification *_Nonnull))condition {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
void (^delayedSemaphorePostCallback)() = ^() {
@@ -257,20 +310,61 @@
[UNUserNotificationCenter.currentNotificationCenter
getDeliveredNotificationsWithCompletionHandler:^(
NSArray<UNNotification *> *_Nonnull notifications) {
+ NSMutableArray<NSString *> *notificationsToRemove =
+ [[NSMutableArray alloc] init];
for (UNNotification *notif in notifications) {
- if ([identifier isEqual:notif.request.content.userInfo[@"id"]]) {
- [UNUserNotificationCenter.currentNotificationCenter
- removeDeliveredNotificationsWithIdentifiers:@[
- notif.request.identifier
- ]];
+ if (condition(notif)) {
+ [notificationsToRemove addObject:notif.request.identifier];
}
}
+ [UNUserNotificationCenter.currentNotificationCenter
+ removeDeliveredNotificationsWithIdentifiers:notificationsToRemove];
delayedSemaphorePostCallback();
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
+- (void)displayLocalNotificationFromContent:(UNNotificationContent *)content
+ forCollapseKey:(NSString *)collapseKey {
+ UNMutableNotificationContent *localNotifContent =
+ [[UNMutableNotificationContent alloc] init];
+
+ localNotifContent.title = content.title;
+ localNotifContent.body = content.body;
+ localNotifContent.badge = content.badge;
+ localNotifContent.userInfo = content.userInfo;
+
+ UNNotificationRequest *localNotifRequest =
+ [UNNotificationRequest requestWithIdentifier:collapseKey
+ content:localNotifContent
+ trigger:nil];
+
+ // We must wait until local notif display completion
+ // handler returns. Context:
+ // https://developer.apple.com/forums/thread/108340?answerId=331640022#331640022
+
+ dispatch_semaphore_t localNotifDisplaySemaphore =
+ dispatch_semaphore_create(0);
+
+ __block NSError *localNotifDisplayError = nil;
+ [UNUserNotificationCenter.currentNotificationCenter
+ addNotificationRequest:localNotifRequest
+ withCompletionHandler:^(NSError *_Nullable error) {
+ if (error) {
+ localNotifDisplayError = error;
+ }
+ dispatch_semaphore_signal(localNotifDisplaySemaphore);
+ }];
+
+ dispatch_semaphore_wait(localNotifDisplaySemaphore, DISPATCH_TIME_FOREVER);
+
+ if (localNotifDisplayError) {
+ throw std::runtime_error(
+ std::string([localNotifDisplayError.localizedDescription UTF8String]));
+ }
+}
+
- (void)persistMessagePayload:(NSDictionary *)payload {
if (payload[messageInfosKey]) {
TemporaryMessageStorage *temporaryStorage =
@@ -315,6 +409,10 @@
return !payload[@"threadID"];
}
+- (BOOL)isCollapsible:(NSDictionary *)payload {
+ return payload[collapseIDKey];
+}
+
- (UNNotificationContent *)getBadgeOnlyContentFor:
(UNNotificationContent *)content {
UNMutableNotificationContent *badgeOnlyContent =
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 14, 12:25 AM (13 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5927595
Default Alt Text
D9144.1768350349.diff (6 KB)
Attached To
Mode
D9144: Enable encrypted notification coalescing in NSE on iOS
Attached
Detach File
Event Timeline
Log In to Comment