@react-native-firebase/messaging 23.8.0 → 23.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1197 -0
- package/RNFBMessaging.podspec +50 -0
- package/android/.editorconfig +10 -0
- package/android/build.gradle +149 -0
- package/android/lint.xml +5 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +43 -0
- package/android/src/main/java/io/invertase/firebase/messaging/JsonConvert.java +127 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingHeadlessService.java +30 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingModule.java +332 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingPackage.java +41 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingReceiver.java +66 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingSerializer.java +225 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingService.java +37 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStore.java +15 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreHelper.java +23 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreImpl.java +97 -0
- package/android/src/main/res/values/colors.xml +143 -0
- package/app.plugin.js +1 -0
- package/dist/commonjs/version.js +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/commonjs/lib/namespaced.d.ts +1 -1
- package/dist/typescript/commonjs/lib/version.d.ts +1 -1
- package/dist/typescript/module/lib/namespaced.d.ts +1 -1
- package/dist/typescript/module/lib/version.d.ts +1 -1
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h +54 -0
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.m +251 -0
- package/ios/RNFBMessaging/RNFBMessaging+FIRMessagingDelegate.h +31 -0
- package/ios/RNFBMessaging/RNFBMessaging+FIRMessagingDelegate.m +70 -0
- package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.h +29 -0
- package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.m +173 -0
- package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.h +37 -0
- package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +185 -0
- package/ios/RNFBMessaging/RNFBMessagingModule.h +26 -0
- package/ios/RNFBMessaging/RNFBMessagingModule.m +431 -0
- package/ios/RNFBMessaging/RNFBMessagingSerializer.h +32 -0
- package/ios/RNFBMessaging/RNFBMessagingSerializer.m +235 -0
- package/ios/RNFBMessaging.xcodeproj/project.pbxproj +384 -0
- package/ios/RNFBMessaging.xcodeproj/xcshareddata/IDETemplateMacros.plist +24 -0
- package/lib/version.ts +1 -1
- package/package.json +5 -15
- package/plugin/build/android/index.d.ts +2 -0
- package/plugin/build/android/index.js +5 -0
- package/plugin/build/android/setupFirebaseNotifationIcon.d.ts +8 -0
- package/plugin/build/android/setupFirebaseNotifationIcon.js +62 -0
- package/plugin/build/index.d.ts +3 -0
- package/plugin/build/index.js +16 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <Firebase/Firebase.h>
|
|
19
|
+
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
|
|
20
|
+
#import <objc/runtime.h>
|
|
21
|
+
|
|
22
|
+
#import <RNFBApp/RNFBRCTEventEmitter.h>
|
|
23
|
+
#import <RNFBApp/RNFBSharedUtils.h>
|
|
24
|
+
#import <React/RCTConvert.h>
|
|
25
|
+
|
|
26
|
+
#import "RNFBMessaging+AppDelegate.h"
|
|
27
|
+
#import "RNFBMessagingSerializer.h"
|
|
28
|
+
|
|
29
|
+
@implementation RNFBMessagingAppDelegate
|
|
30
|
+
|
|
31
|
+
+ (instancetype)sharedInstance {
|
|
32
|
+
static dispatch_once_t once;
|
|
33
|
+
__strong static RNFBMessagingAppDelegate *sharedInstance;
|
|
34
|
+
dispatch_once(&once, ^{
|
|
35
|
+
sharedInstance = [[RNFBMessagingAppDelegate alloc] init];
|
|
36
|
+
sharedInstance.conditionBackgroundMessageHandlerSet = [[NSCondition alloc] init];
|
|
37
|
+
sharedInstance.backgroundMessageHandlerSet = NO;
|
|
38
|
+
});
|
|
39
|
+
return sharedInstance;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
- (void)observe {
|
|
43
|
+
static dispatch_once_t once;
|
|
44
|
+
__weak RNFBMessagingAppDelegate *weakSelf = self;
|
|
45
|
+
dispatch_once(&once, ^{
|
|
46
|
+
RNFBMessagingAppDelegate *strongSelf = weakSelf;
|
|
47
|
+
|
|
48
|
+
[GULAppDelegateSwizzler registerAppDelegateInterceptor:strongSelf];
|
|
49
|
+
[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods];
|
|
50
|
+
|
|
51
|
+
SEL didReceiveRemoteNotificationWithCompletionSEL =
|
|
52
|
+
NSSelectorFromString(@"application:didReceiveRemoteNotification:fetchCompletionHandler:");
|
|
53
|
+
if ([[GULAppDelegateSwizzler sharedApplication].delegate
|
|
54
|
+
respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) {
|
|
55
|
+
// noop - user has own implementation of this method in their AppDelegate, this
|
|
56
|
+
// means GULAppDelegateSwizzler will have already replaced it with a donor method
|
|
57
|
+
} else {
|
|
58
|
+
// add our own donor implementation of
|
|
59
|
+
// application:didReceiveRemoteNotification:fetchCompletionHandler:
|
|
60
|
+
Method donorMethod = class_getInstanceMethod(object_getClass(strongSelf),
|
|
61
|
+
didReceiveRemoteNotificationWithCompletionSEL);
|
|
62
|
+
class_addMethod(object_getClass([GULAppDelegateSwizzler sharedApplication].delegate),
|
|
63
|
+
didReceiveRemoteNotificationWithCompletionSEL,
|
|
64
|
+
method_getImplementation(donorMethod), method_getTypeEncoding(donorMethod));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// used to signal that a javascript handler for background messages is set
|
|
70
|
+
- (void)signalBackgroundMessageHandlerSet {
|
|
71
|
+
RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance];
|
|
72
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet lock];
|
|
73
|
+
DLog(@"signalBackgroundMessageHandlerSet sharedInstance.backgroundMessageHandlerSet was %@",
|
|
74
|
+
sharedInstance.backgroundMessageHandlerSet ? @"YES" : @"NO");
|
|
75
|
+
sharedInstance.backgroundMessageHandlerSet = YES;
|
|
76
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet broadcast];
|
|
77
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet unlock];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// used to temporarily store a promise instance to resolve calls to `registerForRemoteNotifications`
|
|
81
|
+
- (void)setPromiseResolve:(RCTPromiseResolveBlock)resolve
|
|
82
|
+
andPromiseReject:(RCTPromiseRejectBlock)reject {
|
|
83
|
+
_registerPromiseResolver = resolve;
|
|
84
|
+
_registerPromiseRejecter = reject;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#pragma mark -
|
|
88
|
+
#pragma mark AppDelegate Methods
|
|
89
|
+
|
|
90
|
+
// called when `registerForRemoteNotifications` completes successfully
|
|
91
|
+
- (void)application:(UIApplication *)application
|
|
92
|
+
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
93
|
+
#ifdef DEBUG
|
|
94
|
+
[[FIRMessaging messaging] setAPNSToken:deviceToken type:FIRMessagingAPNSTokenTypeSandbox];
|
|
95
|
+
#else
|
|
96
|
+
[[FIRMessaging messaging] setAPNSToken:deviceToken type:FIRMessagingAPNSTokenTypeProd];
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
if (_registerPromiseResolver != nil) {
|
|
100
|
+
_registerPromiseResolver(@(
|
|
101
|
+
[RCTConvert BOOL:@([UIApplication sharedApplication].isRegisteredForRemoteNotifications)]));
|
|
102
|
+
_registerPromiseResolver = nil;
|
|
103
|
+
_registerPromiseRejecter = nil;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// called when `registerForRemoteNotifications` fails to complete
|
|
108
|
+
- (void)application:(UIApplication *)application
|
|
109
|
+
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
110
|
+
if (_registerPromiseRejecter != nil) {
|
|
111
|
+
[RNFBSharedUtils rejectPromiseWithNSError:_registerPromiseRejecter error:error];
|
|
112
|
+
_registerPromiseResolver = nil;
|
|
113
|
+
_registerPromiseRejecter = nil;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
- (void)application:(UIApplication *)application
|
|
118
|
+
didReceiveRemoteNotification:(NSDictionary *)userInfo
|
|
119
|
+
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
|
|
120
|
+
#if __has_include(<FirebaseAuth/FirebaseAuth.h>)
|
|
121
|
+
|
|
122
|
+
for (id appId in [FIRApp allApps]) {
|
|
123
|
+
FIRApp *app = [[FIRApp allApps] objectForKey:appId];
|
|
124
|
+
if ([[FIRAuth authWithApp:app] canHandleNotification:userInfo]) {
|
|
125
|
+
DLog(@"didReceiveRemoteNotification Firebase Auth handled the notification with instance: %@",
|
|
126
|
+
app.name);
|
|
127
|
+
completionHandler(UIBackgroundFetchResultNoData);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// If the notification is a probe notification, always call the completion
|
|
133
|
+
// handler with UIBackgroundFetchResultNoData.
|
|
134
|
+
//
|
|
135
|
+
// This fixes a race condition between `FIRAuth/didReceiveRemoteNotification` and this
|
|
136
|
+
// module causing detox to hang when `FIRAuth/didReceiveRemoteNotification` is called first.
|
|
137
|
+
// see
|
|
138
|
+
// https://stackoverflow.com/questions/72044950/detox-tests-hang-with-pending-items-on-dispatch-queue/72989494
|
|
139
|
+
NSDictionary *data = userInfo[@"com.google.firebase.auth"];
|
|
140
|
+
if ([data isKindOfClass:[NSString class]]) {
|
|
141
|
+
// Deserialize in case the data is a JSON string.
|
|
142
|
+
NSData *JSONData = [((NSString *)data) dataUsingEncoding:NSUTF8StringEncoding];
|
|
143
|
+
data = [NSJSONSerialization JSONObjectWithData:JSONData options:0 error:NULL];
|
|
144
|
+
}
|
|
145
|
+
if ([data isKindOfClass:[NSDictionary class]] && data[@"warning"]) {
|
|
146
|
+
completionHandler(UIBackgroundFetchResultNoData);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
#endif
|
|
150
|
+
|
|
151
|
+
[[NSNotificationCenter defaultCenter]
|
|
152
|
+
postNotificationName:@"RNFBMessagingDidReceiveRemoteNotification"
|
|
153
|
+
object:userInfo];
|
|
154
|
+
|
|
155
|
+
if (userInfo[@"gcm.message_id"]) {
|
|
156
|
+
DLog(@"didReceiveRemoteNotification gcm.message_id was present %@", userInfo);
|
|
157
|
+
|
|
158
|
+
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
|
159
|
+
// Store the completion handler to call later when the JS code finishes
|
|
160
|
+
RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance];
|
|
161
|
+
sharedInstance.completionHandler = completionHandler;
|
|
162
|
+
|
|
163
|
+
// If app is in background state, register background task to guarantee async queues aren't
|
|
164
|
+
// frozen.
|
|
165
|
+
sharedInstance.backgroundTaskId = [application beginBackgroundTaskWithExpirationHandler:^{
|
|
166
|
+
dispatch_get_main_queue(), ^{
|
|
167
|
+
if (sharedInstance.backgroundTaskId != UIBackgroundTaskInvalid) {
|
|
168
|
+
[application endBackgroundTask:sharedInstance.backgroundTaskId];
|
|
169
|
+
sharedInstance.backgroundTaskId = UIBackgroundTaskInvalid;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}];
|
|
173
|
+
|
|
174
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(25 * NSEC_PER_SEC)),
|
|
175
|
+
dispatch_get_main_queue(), ^{
|
|
176
|
+
if (sharedInstance.completionHandler) {
|
|
177
|
+
sharedInstance.completionHandler(UIBackgroundFetchResultNewData);
|
|
178
|
+
sharedInstance.completionHandler = nil;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Stop background task after the longest timeout, async queue is okay to
|
|
182
|
+
// freeze again after handling period
|
|
183
|
+
if (sharedInstance.backgroundTaskId != UIBackgroundTaskInvalid) {
|
|
184
|
+
[application endBackgroundTask:sharedInstance.backgroundTaskId];
|
|
185
|
+
sharedInstance.backgroundTaskId = UIBackgroundTaskInvalid;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet lock];
|
|
190
|
+
@try {
|
|
191
|
+
DLog(@"didReceiveRemoteNotification sharedInstance.backgroundMessageHandlerSet = %@",
|
|
192
|
+
sharedInstance.backgroundMessageHandlerSet ? @"YES" : @"NO");
|
|
193
|
+
if (sharedInstance.backgroundMessageHandlerSet) {
|
|
194
|
+
// Normal path, backgroundMessageHandlerSet has already been set, queue the notification
|
|
195
|
+
// for immediate delivery
|
|
196
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
197
|
+
[[RNFBRCTEventEmitter shared]
|
|
198
|
+
sendEventWithName:@"messaging_message_received_background"
|
|
199
|
+
body:[RNFBMessagingSerializer remoteMessageUserInfoToDict:userInfo]];
|
|
200
|
+
});
|
|
201
|
+
DLog(@"didReceiveRemoteNotification without waiting for backgroundMessageHandlerSet to "
|
|
202
|
+
@"be set");
|
|
203
|
+
} else {
|
|
204
|
+
// This spin needs to be on a background/concurrent queue to await the setup of
|
|
205
|
+
// backgroundMessageHandlerSet and not block the main thread
|
|
206
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
207
|
+
// Reaquire the lock in this new closure
|
|
208
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet lock];
|
|
209
|
+
@try {
|
|
210
|
+
// Spin/wait until backgroundMessageHandlerSet
|
|
211
|
+
// NB it is possible while this closure was being scheduled that
|
|
212
|
+
// backgroundMessageHandlerSet is already set and this loop is skipped
|
|
213
|
+
while (!sharedInstance.backgroundMessageHandlerSet) {
|
|
214
|
+
DLog(@"didReceiveRemoteNotification waiting for "
|
|
215
|
+
@"sharedInstance.backgroundMessageHandlerSet %@",
|
|
216
|
+
sharedInstance.backgroundMessageHandlerSet ? @"YES" : @"NO");
|
|
217
|
+
if (![sharedInstance.conditionBackgroundMessageHandlerSet
|
|
218
|
+
waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:25]]) {
|
|
219
|
+
// If after 25 seconds the client hasn't called backgroundMessageHandlerSet, give
|
|
220
|
+
// up on this notification
|
|
221
|
+
ELog(@"didReceiveRemoteNotification timed out waiting for "
|
|
222
|
+
@"sharedInstance.backgroundMessageHandlerSet");
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
227
|
+
[[RNFBRCTEventEmitter shared]
|
|
228
|
+
sendEventWithName:@"messaging_message_received_background"
|
|
229
|
+
body:[RNFBMessagingSerializer
|
|
230
|
+
remoteMessageUserInfoToDict:userInfo]];
|
|
231
|
+
});
|
|
232
|
+
DLog(@"didReceiveRemoteNotification after waiting for backgroundMessageHandlerSet");
|
|
233
|
+
} @finally {
|
|
234
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet unlock];
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
} @finally {
|
|
239
|
+
[sharedInstance.conditionBackgroundMessageHandlerSet unlock];
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
DLog(@"didReceiveRemoteNotification while app was in foreground");
|
|
243
|
+
[[RNFBRCTEventEmitter shared]
|
|
244
|
+
sendEventWithName:@"messaging_message_received"
|
|
245
|
+
body:[RNFBMessagingSerializer remoteMessageUserInfoToDict:userInfo]];
|
|
246
|
+
completionHandler(UIBackgroundFetchResultNoData);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <Firebase/Firebase.h>
|
|
19
|
+
#import <Foundation/Foundation.h>
|
|
20
|
+
|
|
21
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
22
|
+
|
|
23
|
+
@interface RNFBMessagingFIRMessagingDelegate : NSObject <FIRMessagingDelegate>
|
|
24
|
+
|
|
25
|
+
+ (_Nonnull instancetype)sharedInstance;
|
|
26
|
+
|
|
27
|
+
- (void)observe;
|
|
28
|
+
|
|
29
|
+
@end
|
|
30
|
+
|
|
31
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
|
|
19
|
+
#import <RNFBApp/RNFBRCTEventEmitter.h>
|
|
20
|
+
#import <objc/message.h>
|
|
21
|
+
#import <objc/runtime.h>
|
|
22
|
+
|
|
23
|
+
#import "RNFBMessaging+FIRMessagingDelegate.h"
|
|
24
|
+
#import "RNFBMessagingSerializer.h"
|
|
25
|
+
|
|
26
|
+
@implementation RNFBMessagingFIRMessagingDelegate
|
|
27
|
+
|
|
28
|
+
+ (instancetype)sharedInstance {
|
|
29
|
+
static dispatch_once_t once;
|
|
30
|
+
__strong static RNFBMessagingFIRMessagingDelegate *sharedInstance;
|
|
31
|
+
dispatch_once(&once, ^{
|
|
32
|
+
sharedInstance = [[RNFBMessagingFIRMessagingDelegate alloc] init];
|
|
33
|
+
});
|
|
34
|
+
return sharedInstance;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
- (void)observe {
|
|
38
|
+
static dispatch_once_t once;
|
|
39
|
+
__weak RNFBMessagingFIRMessagingDelegate *weakSelf = self;
|
|
40
|
+
dispatch_once(&once, ^{
|
|
41
|
+
RNFBMessagingFIRMessagingDelegate *strongSelf = weakSelf;
|
|
42
|
+
[FIRMessaging messaging].delegate = strongSelf;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#pragma mark -
|
|
47
|
+
#pragma mark FIRMessagingDelegate Methods
|
|
48
|
+
|
|
49
|
+
// JS -> `onTokenRefresh`
|
|
50
|
+
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
|
|
51
|
+
if (fcmToken == nil) { // Don't crash when the token is reset
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
[[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_token_refresh"
|
|
55
|
+
body:@{@"token" : fcmToken}];
|
|
56
|
+
|
|
57
|
+
// If the users AppDelegate implements messaging:didReceiveRegistrationToken: then call it
|
|
58
|
+
SEL messaging_didReceiveRegistrationTokenSelector =
|
|
59
|
+
NSSelectorFromString(@"messaging:didReceiveRegistrationToken:");
|
|
60
|
+
if ([[GULAppDelegateSwizzler sharedApplication].delegate
|
|
61
|
+
respondsToSelector:messaging_didReceiveRegistrationTokenSelector]) {
|
|
62
|
+
void (*usersDidReceiveRegistrationTokenIMP)(id, SEL, FIRMessaging *, NSString *) =
|
|
63
|
+
(typeof(usersDidReceiveRegistrationTokenIMP))&objc_msgSend;
|
|
64
|
+
usersDidReceiveRegistrationTokenIMP([GULAppDelegateSwizzler sharedApplication].delegate,
|
|
65
|
+
messaging_didReceiveRegistrationTokenSelector, messaging,
|
|
66
|
+
fcmToken);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <Foundation/Foundation.h>
|
|
19
|
+
|
|
20
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
21
|
+
|
|
22
|
+
@interface RNFBMessagingNSNotificationCenter : NSObject
|
|
23
|
+
|
|
24
|
+
+ (_Nonnull instancetype)sharedInstance;
|
|
25
|
+
@property(nonatomic) BOOL isHeadless;
|
|
26
|
+
|
|
27
|
+
@end
|
|
28
|
+
|
|
29
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
#import <Firebase/Firebase.h>
|
|
18
|
+
#import <RNFBApp/RNFBJSON.h>
|
|
19
|
+
#import <RNFBApp/RNFBRCTEventEmitter.h>
|
|
20
|
+
#import <React/RCTConvert.h>
|
|
21
|
+
#import <React/RCTRootView.h>
|
|
22
|
+
|
|
23
|
+
#import "RNFBMessaging+AppDelegate.h"
|
|
24
|
+
#import "RNFBMessaging+FIRMessagingDelegate.h"
|
|
25
|
+
#import "RNFBMessaging+NSNotificationCenter.h"
|
|
26
|
+
#import "RNFBMessaging+UNUserNotificationCenter.h"
|
|
27
|
+
|
|
28
|
+
@implementation RNFBMessagingNSNotificationCenter
|
|
29
|
+
@synthesize isHeadless;
|
|
30
|
+
+ (instancetype)sharedInstance {
|
|
31
|
+
static dispatch_once_t once;
|
|
32
|
+
__strong static RNFBMessagingNSNotificationCenter *sharedInstance;
|
|
33
|
+
dispatch_once(&once, ^{
|
|
34
|
+
sharedInstance = [[RNFBMessagingNSNotificationCenter alloc] init];
|
|
35
|
+
});
|
|
36
|
+
return sharedInstance;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
- (void)observe {
|
|
40
|
+
static dispatch_once_t once;
|
|
41
|
+
__weak RNFBMessagingNSNotificationCenter *weakSelf = self;
|
|
42
|
+
dispatch_once(&once, ^{
|
|
43
|
+
RNFBMessagingNSNotificationCenter *strongSelf = weakSelf;
|
|
44
|
+
|
|
45
|
+
// Application
|
|
46
|
+
// JS -> `getInitialNotification`
|
|
47
|
+
// ObjC -> Initialize other delegates & observers
|
|
48
|
+
[[NSNotificationCenter defaultCenter]
|
|
49
|
+
addObserver:strongSelf
|
|
50
|
+
selector:@selector(application_onDidFinishLaunchingNotification:)
|
|
51
|
+
name:UIApplicationDidFinishLaunchingNotification
|
|
52
|
+
object:nil];
|
|
53
|
+
|
|
54
|
+
// Application
|
|
55
|
+
// ObjC - > Mutates the root React components initialProps to toggle `isHeadless` state
|
|
56
|
+
[[NSNotificationCenter defaultCenter] addObserver:strongSelf
|
|
57
|
+
selector:@selector(application_onDidEnterForeground)
|
|
58
|
+
name:UIApplicationWillEnterForegroundNotification
|
|
59
|
+
object:nil];
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// start observing immediately on class load - specifically for
|
|
64
|
+
// UIApplicationDidFinishLaunchingNotification
|
|
65
|
+
+ (void)load {
|
|
66
|
+
[[self sharedInstance] observe];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#pragma mark -
|
|
70
|
+
#pragma mark Application Notifications
|
|
71
|
+
|
|
72
|
+
- (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)notification {
|
|
73
|
+
// setup our delegates & swizzling after app finishes launching
|
|
74
|
+
// these methods are idempotent so can safely be called multiple times
|
|
75
|
+
[[RNFBMessagingAppDelegate sharedInstance] observe];
|
|
76
|
+
[[RNFBMessagingUNUserNotificationCenter sharedInstance] observe];
|
|
77
|
+
[[RNFBMessagingFIRMessagingDelegate sharedInstance] observe];
|
|
78
|
+
|
|
79
|
+
RCTRootView *rctRootView;
|
|
80
|
+
if ([UIApplication sharedApplication].delegate != nil &&
|
|
81
|
+
[UIApplication sharedApplication].delegate.window != nil &&
|
|
82
|
+
[UIApplication sharedApplication].delegate.window.rootViewController != nil &&
|
|
83
|
+
[UIApplication sharedApplication].delegate.window.rootViewController.view != nil &&
|
|
84
|
+
[[UIApplication sharedApplication].delegate.window.rootViewController.view
|
|
85
|
+
isKindOfClass:[RCTRootView class]]) {
|
|
86
|
+
rctRootView =
|
|
87
|
+
(RCTRootView *)[UIApplication sharedApplication].delegate.window.rootViewController.view;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// #if !(TARGET_IPHONE_SIMULATOR)
|
|
91
|
+
if ([[RNFBJSON shared] getBooleanValue:@"messaging_ios_auto_register_for_remote_messages"
|
|
92
|
+
defaultValue:YES]) {
|
|
93
|
+
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
94
|
+
}
|
|
95
|
+
// #endif
|
|
96
|
+
|
|
97
|
+
if (notification.userInfo[UIApplicationLaunchOptionsRemoteNotificationKey]) {
|
|
98
|
+
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
|
99
|
+
isHeadless = YES;
|
|
100
|
+
if (rctRootView != nil) {
|
|
101
|
+
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil
|
|
102
|
+
? [rctRootView.appProperties mutableCopy]
|
|
103
|
+
: [NSMutableDictionary dictionary];
|
|
104
|
+
if ([appPropertiesDict objectForKey:@"isHeadless"] != nil &&
|
|
105
|
+
[appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(NO)])]) {
|
|
106
|
+
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(isHeadless)]);
|
|
107
|
+
rctRootView.appProperties = appPropertiesDict;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// #if !(TARGET_IPHONE_SIMULATOR)
|
|
112
|
+
// When an app launches in the background (BG mode) and is launched with the notification
|
|
113
|
+
// launch option the app delegate method
|
|
114
|
+
// application:didReceiveRemoteNotification:fetchCompletionHandler: will not get called unless
|
|
115
|
+
// registerForRemoteNotifications was called early during app initialization - we call it here
|
|
116
|
+
// in this scenario as the user can only call this via JS, at which point it'd be too late
|
|
117
|
+
// resulting in the app being terminated. called irregardless of
|
|
118
|
+
// `messaging_ios_auto_register_for_remote_messages` as this is most likely an app launching
|
|
119
|
+
// as a result of a remote notification - so has been registered previously
|
|
120
|
+
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
121
|
+
// #endif
|
|
122
|
+
} else {
|
|
123
|
+
isHeadless = NO;
|
|
124
|
+
if (rctRootView != nil) {
|
|
125
|
+
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil
|
|
126
|
+
? [rctRootView.appProperties mutableCopy]
|
|
127
|
+
: [NSMutableDictionary dictionary];
|
|
128
|
+
if ([appPropertiesDict objectForKey:@"isHeadless"] != nil &&
|
|
129
|
+
[appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
|
|
130
|
+
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(isHeadless)]);
|
|
131
|
+
rctRootView.appProperties = appPropertiesDict;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
isHeadless = NO;
|
|
137
|
+
if (rctRootView != nil) {
|
|
138
|
+
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil
|
|
139
|
+
? [rctRootView.appProperties mutableCopy]
|
|
140
|
+
: [NSMutableDictionary dictionary];
|
|
141
|
+
if ([appPropertiesDict objectForKey:@"isHeadless"] != nil &&
|
|
142
|
+
[appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
|
|
143
|
+
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(isHeadless)]);
|
|
144
|
+
rctRootView.appProperties = appPropertiesDict;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
- (void)application_onDidEnterForeground {
|
|
151
|
+
isHeadless = NO;
|
|
152
|
+
if ([UIApplication sharedApplication].delegate != nil &&
|
|
153
|
+
[UIApplication sharedApplication].delegate.window != nil &&
|
|
154
|
+
[UIApplication sharedApplication].delegate.window.rootViewController != nil &&
|
|
155
|
+
[UIApplication sharedApplication].delegate.window.rootViewController.view != nil &&
|
|
156
|
+
[[UIApplication sharedApplication].delegate.window.rootViewController.view
|
|
157
|
+
isKindOfClass:[RCTRootView class]]) {
|
|
158
|
+
RCTRootView *rctRootView =
|
|
159
|
+
(RCTRootView *)[UIApplication sharedApplication].delegate.window.rootViewController.view;
|
|
160
|
+
|
|
161
|
+
if (rctRootView.appProperties != nil &&
|
|
162
|
+
[rctRootView.appProperties[@"isHeadless"] isEqual:@(YES)]) {
|
|
163
|
+
NSMutableDictionary *appPropertiesDict = [rctRootView.appProperties mutableCopy];
|
|
164
|
+
if ([appPropertiesDict objectForKey:@"isHeadless"] != nil &&
|
|
165
|
+
[appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
|
|
166
|
+
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(isHeadless)]);
|
|
167
|
+
rctRootView.appProperties = appPropertiesDict;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <UserNotifications/UserNotifications.h>
|
|
19
|
+
|
|
20
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
21
|
+
|
|
22
|
+
@interface RNFBMessagingUNUserNotificationCenter : NSObject <UNUserNotificationCenterDelegate>
|
|
23
|
+
|
|
24
|
+
@property NSDictionary *_Nullable initialNotification;
|
|
25
|
+
@property BOOL didOpenSettingsForNotification;
|
|
26
|
+
@property(nonatomic, nullable, weak) id<UNUserNotificationCenterDelegate> originalDelegate;
|
|
27
|
+
|
|
28
|
+
+ (_Nonnull instancetype)sharedInstance;
|
|
29
|
+
|
|
30
|
+
- (void)observe;
|
|
31
|
+
|
|
32
|
+
- (nullable NSDictionary *)getInitialNotification;
|
|
33
|
+
|
|
34
|
+
- (NSNumber *)getDidOpenSettingsForNotification;
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
NS_ASSUME_NONNULL_END
|