1// Copyright 2018-present 650 Industries. All rights reserved.
2
3#import <EXNotifications/EXNotificationsHandlerModule.h>
4#import <EXNotifications/EXNotificationSerializer.h>
5#import <EXNotifications/EXNotificationCenterDelegate.h>
6
7#import <ExpoModulesCore/EXEventEmitterService.h>
8
9@interface EXNotificationsHandlerModule ()
10
11@property (nonatomic, weak) id<EXNotificationCenterDelegate> notificationCenterDelegate;
12
13@property (nonatomic, assign) BOOL isListening;
14@property (nonatomic, assign) BOOL isBeingObserved;
15
16@property (nonatomic, weak) id<EXEventEmitterService> eventEmitter;
17
18@property (nonatomic, strong) NSMutableDictionary<NSString *, EXSingleNotificationHandlerTask *> *tasksMap;
19
20@end
21
22@implementation EXNotificationsHandlerModule
23
24EX_EXPORT_MODULE(ExpoNotificationsHandlerModule);
25
26- (instancetype)init
27{
28  if (self = [super init]) {
29    _tasksMap = [NSMutableDictionary dictionary];
30  }
31  return self;
32}
33
34# pragma mark - Exported methods
35
36EX_EXPORT_METHOD_AS(handleNotificationAsync,
37                    handleNotificationAsync:(NSString *)identifier withBehavior:(NSDictionary *)behavior resolver:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject)
38{
39  EXSingleNotificationHandlerTask *task = _tasksMap[identifier];
40  if (!task) {
41    NSString *message = [NSString stringWithFormat:@"Failed to handle notification %@, it has already been handled.", identifier];
42    return reject(@"ERR_NOTIFICATION_HANDLED", message, nil);
43  }
44  NSError *error = [task handleResponse:behavior];
45  if (error) {
46    return reject(error.userInfo[@"code"], error.userInfo[@"message"], error);
47  } else {
48    resolve(nil);
49  }
50}
51
52# pragma mark - EXModuleRegistryConsumer
53
54- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
55{
56  _eventEmitter = [moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)];
57  _notificationCenterDelegate = [moduleRegistry getSingletonModuleForName:@"NotificationCenterDelegate"];
58}
59
60# pragma mark - EXEventEmitter
61
62- (NSArray<NSString *> *)supportedEvents
63{
64  return [EXSingleNotificationHandlerTask eventNames];
65}
66
67- (void)startObserving
68{
69  [self setIsBeingObserved:YES];
70}
71
72- (void)stopObserving
73{
74  [self setIsBeingObserved:NO];
75}
76
77- (void)setIsBeingObserved:(BOOL)isBeingObserved
78{
79  _isBeingObserved = isBeingObserved;
80  BOOL shouldListen = _isBeingObserved;
81  if (shouldListen && !_isListening) {
82    [_notificationCenterDelegate addDelegate:self];
83    _isListening = YES;
84  } else if (!shouldListen && _isListening) {
85    [_notificationCenterDelegate removeDelegate:self];
86    _isListening = NO;
87  }
88}
89
90# pragma mark - EXNotificationsDelegate
91
92- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
93{
94  EXSingleNotificationHandlerTask *task = [[EXSingleNotificationHandlerTask alloc] initWithEventEmitter:_eventEmitter
95                                                                                           notification:notification
96                                                                                      completionHandler:completionHandler
97                                                                                               delegate:self];
98  [_tasksMap setObject:task forKey:task.identifier];
99  [task start];
100}
101
102# pragma mark - EXSingleNotificationHandlerTaskDelegate
103
104- (void)taskDidFinish:(EXSingleNotificationHandlerTask *)task
105{
106  [_tasksMap removeObjectForKey:task.identifier];
107}
108
109@end
110