-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathBatchBridgeNotificationCenterDelegate.m
203 lines (172 loc) · 7.49 KB
/
BatchBridgeNotificationCenterDelegate.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//
// Copyright © Batch.com. All rights reserved.
//
#import "BatchBridgeNotificationCenterDelegate.h"
#import <Batch/BatchPush.h>
@implementation BatchBridgeNotificationCenterDelegate
{
BOOL _isBatchReady;
NSMutableArray<UNNotificationResponse*>* _enqueuedNotificationResponses;
__weak __nullable id<UNUserNotificationCenterDelegate> _previousDelegate;
}
static BOOL _batBridgeNotifDelegateShouldAutomaticallyRegister = true;
+ (void)load
{
[[NSNotificationCenter defaultCenter] addObserver:[BatchBridgeNotificationCenterDelegate class]
selector:@selector(applicationFinishedLaunching:) name:UIApplicationDidFinishLaunchingNotification
object:nil];
}
+ (void)applicationFinishedLaunching:(NSNotification*)notification {
if ([BatchBridgeNotificationCenterDelegate automaticallyRegister]) {
[BatchBridgeNotificationCenterDelegate registerAsDelegate];
}
}
+ (BatchBridgeNotificationCenterDelegate *)sharedInstance
{
static BatchBridgeNotificationCenterDelegate *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[BatchBridgeNotificationCenterDelegate alloc] init];
});
return sharedInstance;
}
+ (void)registerAsDelegate
{
UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter];
BatchBridgeNotificationCenterDelegate *instance = [self sharedInstance];
instance.previousDelegate = notifCenter.delegate;
notifCenter.delegate = instance;
}
+ (BOOL)automaticallyRegister
{
return _batBridgeNotifDelegateShouldAutomaticallyRegister;
}
+ (void)setAutomaticallyRegister:(BOOL)automaticallyRegister
{
_batBridgeNotifDelegateShouldAutomaticallyRegister = automaticallyRegister;
}
- (nullable id<UNUserNotificationCenterDelegate>)previousDelegate
{
return _previousDelegate;
}
- (void)setPreviousDelegate:(nullable id<UNUserNotificationCenterDelegate>)delegate
{
// Do not register ourserlves as previous delegate to avoid
// an infinite loop
if (delegate == self || [delegate isKindOfClass:[self class]]) {
_previousDelegate = nil;
} else {
_previousDelegate = delegate;
}
}
- (instancetype)init
{
self = [super init];
if (self) {
_showForegroundNotifications = true;
_shouldUseChainedCompletionHandlerResponse = true;
_isBatchReady = false;
_enqueuedNotificationResponses = [NSMutableArray new];
}
return self;
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
[BatchPush handleUserNotificationCenter:center willPresentNotification:notification willShowSystemForegroundAlert:self.showForegroundNotifications];
id<UNUserNotificationCenterDelegate> chainDelegate = self.previousDelegate;
// It's the chain delegate's responsibility to call the completionHandler
if ([chainDelegate respondsToSelector:@selector(userNotificationCenter:willPresentNotification:withCompletionHandler:)]) {
//returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
void (^chainCompletionHandler)(UNNotificationPresentationOptions);
if (self.shouldUseChainedCompletionHandlerResponse) {
// Set iOS' completion handler as the one we give to the method, as we don't want to override the result
chainCompletionHandler = completionHandler;
} else {
// Set ourselves as the chained completion handler so we can wait for the implementation but rewrite the response
chainCompletionHandler = ^(UNNotificationPresentationOptions ignored) {
[self performPresentCompletionHandler:completionHandler];
};
}
[chainDelegate userNotificationCenter:center
willPresentNotification:notification
withCompletionHandler:chainCompletionHandler];
} else {
[self performPresentCompletionHandler:completionHandler];
}
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
{
if (_isBatchReady) {
[BatchPush handleUserNotificationCenter:center didReceiveNotificationResponse:response];
} else {
[self enqueueNotificationResponse:response];
}
id<UNUserNotificationCenterDelegate> chainDelegate = self.previousDelegate;
// It's the chain delegate's responsibility to call the completionHandler
if ([chainDelegate respondsToSelector:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]) {
[chainDelegate userNotificationCenter:center
didReceiveNotificationResponse:response
withCompletionHandler:completionHandler];
} else {
if (completionHandler) {
completionHandler();
}
}
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification
{
if (@available(iOS 12.0, *)) {
id<UNUserNotificationCenterDelegate> chainDelegate = self.previousDelegate;
if ([chainDelegate respondsToSelector:@selector(userNotificationCenter:openSettingsForNotification:)]) {
[self.previousDelegate userNotificationCenter:center
openSettingsForNotification:notification];
}
}
}
/// Call iOS back on the "present" completion handler with Batch controlled presentation options
- (void)performPresentCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
UNNotificationPresentationOptions options = UNNotificationPresentationOptionNone;
if (self.showForegroundNotifications) {
options = UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound;
#ifdef __IPHONE_14_0
if (@available(iOS 14.0, *)) {
options = options | UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner;
} else {
options = options | UNNotificationPresentationOptionAlert;
}
#else
options = options | UNNotificationPresentationOptionAlert;
#endif
}
if (completionHandler) {
completionHandler(options);
};
}
- (BOOL)isBatchReady {
return _isBatchReady;
}
- (void)setIsBatchReady:(BOOL)isBatchReady {
_isBatchReady = isBatchReady;
if (isBatchReady) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self dequeueNotificationResponses];
});
}
}
- (void)enqueueNotificationResponse:(UNNotificationResponse*)notificationResponse {
@synchronized (_enqueuedNotificationResponses) {
[_enqueuedNotificationResponses addObject:notificationResponse];
}
}
- (void)dequeueNotificationResponses {
NSArray<UNNotificationResponse*> *notificationResponses;
@synchronized (_enqueuedNotificationResponses) {
notificationResponses = [_enqueuedNotificationResponses copy];
[_enqueuedNotificationResponses removeAllObjects];
}
for (UNNotificationResponse *notificationResponse in notificationResponses) {
[BatchPush handleUserNotificationCenter:UNUserNotificationCenter.currentNotificationCenter
didReceiveNotificationResponse:notificationResponse];
}
}
@end