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