1// Copyright 2018-present 650 Industries. All rights reserved. 2 3#import <EXNotifications/EXNotificationPresentationModule.h> 4 5#import <EXNotifications/EXNotificationBuilder.h> 6#import <EXNotifications/EXNotificationSerializer.h> 7#import <EXNotifications/EXNotificationCenterDelegate.h> 8 9@interface EXNotificationPresentationModule () 10 11@property (nonatomic, weak) id<EXNotificationBuilder> notificationBuilder; 12 13// Remove once presentNotificationAsync is removed 14@property (nonatomic, strong) NSCountedSet<NSString *> *presentedNotifications; 15@property (nonatomic, weak) id<EXNotificationCenterDelegate> notificationCenterDelegate; 16 17@end 18 19@implementation EXNotificationPresentationModule 20 21UM_EXPORT_MODULE(ExpoNotificationPresenter); 22 23// Remove once presentNotificationAsync is removed 24- (instancetype)init 25{ 26 if (self = [super init]) { 27 _presentedNotifications = [NSCountedSet set]; 28 } 29 return self; 30} 31 32# pragma mark - Exported methods 33 34// Remove once presentNotificationAsync is removed 35UM_EXPORT_METHOD_AS(presentNotificationAsync, 36 presentNotificationWithIdentifier:(NSString *)identifier 37 notification:(NSDictionary *)notificationSpec 38 resolve:(UMPromiseResolveBlock)resolve 39 reject:(UMPromiseRejectBlock)reject) 40{ 41 UNNotificationContent *content = [_notificationBuilder notificationContentFromRequest:notificationSpec]; 42 UNNotificationTrigger *trigger = nil; 43 UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; 44 [_presentedNotifications addObject:identifier]; 45 __weak EXNotificationPresentationModule *weakSelf = self; 46 [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { 47 if (error) { 48 // If there was no error, willPresentNotification: callback will remove the identifier from the set 49 [weakSelf.presentedNotifications removeObject:identifier]; 50 NSString *message = [NSString stringWithFormat:@"Notification could not have been presented: %@", error.description]; 51 reject(@"ERR_NOTIF_PRESENT", message, error); 52 } else { 53 resolve(identifier); 54 } 55 }]; 56} 57 58UM_EXPORT_METHOD_AS(getPresentedNotificationsAsync, 59 getPresentedNotificationsAsyncWithResolve:(UMPromiseResolveBlock)resolve 60 reject:(UMPromiseRejectBlock)reject) 61{ 62 [[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) { 63 resolve([self serializeNotifications:notifications]); 64 }]; 65} 66 67 68UM_EXPORT_METHOD_AS(dismissNotificationAsync, 69 dismissNotificationWithIdentifier:(NSString *)identifier 70 resolve:(UMPromiseResolveBlock)resolve 71 reject:(UMPromiseRejectBlock)reject) 72{ 73 [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[identifier]]; 74 resolve(nil); 75} 76 77UM_EXPORT_METHOD_AS(dismissAllNotificationsAsync, 78 dismissAllNotificationsWithResolver:(UMPromiseResolveBlock)resolve 79 reject:(UMPromiseRejectBlock)reject) 80{ 81 [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications]; 82 resolve(nil); 83} 84 85# pragma mark - UMModuleRegistryConsumer 86 87- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry 88{ 89 _notificationBuilder = [moduleRegistry getModuleImplementingProtocol:@protocol(EXNotificationBuilder)]; 90 91 // Remove once presentNotificationAsync is removed 92 id<EXNotificationCenterDelegate> notificationCenterDelegate = (id<EXNotificationCenterDelegate>)[moduleRegistry getSingletonModuleForName:@"NotificationCenterDelegate"]; 93 [notificationCenterDelegate addDelegate:self]; 94} 95 96// Remove once presentNotificationAsync is removed 97# pragma mark - EXNotificationsDelegate 98 99- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler 100{ 101 UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionNone; 102 103 NSString *identifier = notification.request.identifier; 104 if ([_presentedNotifications containsObject:identifier]) { 105 [_presentedNotifications removeObject:identifier]; 106 presentationOptions = UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge; 107 } 108 109 completionHandler(presentationOptions); 110} 111 112# pragma mark - Helpers 113 114- (NSArray * _Nonnull)serializeNotifications:(NSArray<UNNotification *> * _Nonnull)notifications 115{ 116 NSMutableArray *serializedNotifications = [NSMutableArray new]; 117 for (UNNotification *notification in notifications) { 118 [serializedNotifications addObject:[EXNotificationSerializer serializedNotification:notification]]; 119 } 120 return serializedNotifications; 121} 122 123@end 124