@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.
Files changed (48) hide show
  1. package/CHANGELOG.md +1197 -0
  2. package/RNFBMessaging.podspec +50 -0
  3. package/android/.editorconfig +10 -0
  4. package/android/build.gradle +149 -0
  5. package/android/lint.xml +5 -0
  6. package/android/settings.gradle +1 -0
  7. package/android/src/main/AndroidManifest.xml +43 -0
  8. package/android/src/main/java/io/invertase/firebase/messaging/JsonConvert.java +127 -0
  9. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingHeadlessService.java +30 -0
  10. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingModule.java +332 -0
  11. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingPackage.java +41 -0
  12. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingReceiver.java +66 -0
  13. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingSerializer.java +225 -0
  14. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingService.java +37 -0
  15. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStore.java +15 -0
  16. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreHelper.java +23 -0
  17. package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreImpl.java +97 -0
  18. package/android/src/main/res/values/colors.xml +143 -0
  19. package/app.plugin.js +1 -0
  20. package/dist/commonjs/version.js +1 -1
  21. package/dist/module/version.js +1 -1
  22. package/dist/typescript/commonjs/lib/namespaced.d.ts +1 -1
  23. package/dist/typescript/commonjs/lib/version.d.ts +1 -1
  24. package/dist/typescript/module/lib/namespaced.d.ts +1 -1
  25. package/dist/typescript/module/lib/version.d.ts +1 -1
  26. package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h +54 -0
  27. package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.m +251 -0
  28. package/ios/RNFBMessaging/RNFBMessaging+FIRMessagingDelegate.h +31 -0
  29. package/ios/RNFBMessaging/RNFBMessaging+FIRMessagingDelegate.m +70 -0
  30. package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.h +29 -0
  31. package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.m +173 -0
  32. package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.h +37 -0
  33. package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +185 -0
  34. package/ios/RNFBMessaging/RNFBMessagingModule.h +26 -0
  35. package/ios/RNFBMessaging/RNFBMessagingModule.m +431 -0
  36. package/ios/RNFBMessaging/RNFBMessagingSerializer.h +32 -0
  37. package/ios/RNFBMessaging/RNFBMessagingSerializer.m +235 -0
  38. package/ios/RNFBMessaging.xcodeproj/project.pbxproj +384 -0
  39. package/ios/RNFBMessaging.xcodeproj/xcshareddata/IDETemplateMacros.plist +24 -0
  40. package/lib/version.ts +1 -1
  41. package/package.json +5 -15
  42. package/plugin/build/android/index.d.ts +2 -0
  43. package/plugin/build/android/index.js +5 -0
  44. package/plugin/build/android/setupFirebaseNotifationIcon.d.ts +8 -0
  45. package/plugin/build/android/setupFirebaseNotifationIcon.js +62 -0
  46. package/plugin/build/index.d.ts +3 -0
  47. package/plugin/build/index.js +16 -0
  48. package/plugin/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,185 @@
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 <RNFBApp/RNFBRCTEventEmitter.h>
19
+
20
+ #import "RNFBJSON.h"
21
+ #import "RNFBMessaging+UNUserNotificationCenter.h"
22
+ #import "RNFBMessagingSerializer.h"
23
+
24
+ @implementation RNFBMessagingUNUserNotificationCenter
25
+ struct {
26
+ unsigned int willPresentNotification : 1;
27
+ unsigned int didReceiveNotificationResponse : 1;
28
+ unsigned int openSettingsForNotification : 1;
29
+ } originalDelegateRespondsTo;
30
+
31
+ + (instancetype)sharedInstance {
32
+ static dispatch_once_t once;
33
+ __strong static RNFBMessagingUNUserNotificationCenter *sharedInstance;
34
+ dispatch_once(&once, ^{
35
+ sharedInstance = [[RNFBMessagingUNUserNotificationCenter alloc] init];
36
+ sharedInstance.initialNotification = nil;
37
+ sharedInstance.didOpenSettingsForNotification = NO;
38
+ });
39
+ return sharedInstance;
40
+ }
41
+
42
+ - (void)observe {
43
+ static dispatch_once_t once;
44
+ __weak RNFBMessagingUNUserNotificationCenter *weakSelf = self;
45
+ dispatch_once(&once, ^{
46
+ RNFBMessagingUNUserNotificationCenter *strongSelf = weakSelf;
47
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
48
+ if (center.delegate != nil) {
49
+ _originalDelegate = center.delegate;
50
+ originalDelegateRespondsTo.openSettingsForNotification = (unsigned int)[_originalDelegate
51
+ respondsToSelector:@selector(userNotificationCenter:openSettingsForNotification:)];
52
+ originalDelegateRespondsTo.willPresentNotification = (unsigned int)[_originalDelegate
53
+ respondsToSelector:@selector(userNotificationCenter:
54
+ willPresentNotification:withCompletionHandler:)];
55
+ originalDelegateRespondsTo.didReceiveNotificationResponse = (unsigned int)[_originalDelegate
56
+ respondsToSelector:@selector(userNotificationCenter:
57
+ didReceiveNotificationResponse:withCompletionHandler:)];
58
+ }
59
+ center.delegate = strongSelf;
60
+ });
61
+ }
62
+
63
+ - (nullable NSDictionary *)getInitialNotification {
64
+ if (_initialNotification != nil) {
65
+ NSDictionary *initialNotificationCopy = [_initialNotification copy];
66
+ _initialNotification = nil;
67
+ return initialNotificationCopy;
68
+ }
69
+
70
+ return nil;
71
+ }
72
+
73
+ - (NSNumber *)getDidOpenSettingsForNotification {
74
+ if (_didOpenSettingsForNotification != NO) {
75
+ _didOpenSettingsForNotification = NO;
76
+ return @YES;
77
+ }
78
+
79
+ return @NO;
80
+ }
81
+
82
+ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
83
+ willPresentNotification:(UNNotification *)notification
84
+ withCompletionHandler:
85
+ (void (^)(UNNotificationPresentationOptions options))completionHandler {
86
+ NSArray *presentationOptionsConfig =
87
+ [[RNFBJSON shared] getArrayValue:@"messaging_ios_foreground_presentation_options"
88
+ defaultValue:@[]];
89
+
90
+ UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionNone;
91
+
92
+ BOOL badge = [presentationOptionsConfig containsObject:@"badge"];
93
+ BOOL sound = [presentationOptionsConfig containsObject:@"sound"];
94
+ BOOL alert = [presentationOptionsConfig containsObject:@"alert"];
95
+ BOOL list = [presentationOptionsConfig containsObject:@"list"];
96
+ BOOL banner = [presentationOptionsConfig containsObject:@"banner"];
97
+
98
+ if (badge) {
99
+ presentationOptions |= UNNotificationPresentationOptionBadge;
100
+ }
101
+
102
+ if (sound) {
103
+ presentationOptions |= UNNotificationPresentationOptionSound;
104
+ }
105
+
106
+ // if list or banner is true, ignore `alert` property
107
+ if (banner || list) {
108
+ if (banner) {
109
+ if (@available(iOS 14, *)) {
110
+ presentationOptions |= UNNotificationPresentationOptionBanner;
111
+ } else {
112
+ // for iOS 13 we need to set `alert`
113
+ presentationOptions |= UNNotificationPresentationOptionAlert;
114
+ }
115
+ }
116
+
117
+ if (list) {
118
+ if (@available(iOS 14, *)) {
119
+ presentationOptions |= UNNotificationPresentationOptionList;
120
+ } else {
121
+ // for iOS 13 we need to set `alert`
122
+ presentationOptions |= UNNotificationPresentationOptionAlert;
123
+ }
124
+ }
125
+ } else if (alert) {
126
+ // TODO: Remove `alert` once iOS 14 becomes the minimum deployment target
127
+ presentationOptions |= UNNotificationPresentationOptionAlert;
128
+ }
129
+
130
+ if (notification.request.content.userInfo[@"gcm.message_id"]) {
131
+ NSDictionary *notificationDict = [RNFBMessagingSerializer notificationToDict:notification];
132
+
133
+ // Don't send an event if contentAvailable is true - application:didReceiveRemoteNotification
134
+ // will send the event for us, we don't want to duplicate them
135
+ if (!notificationDict[@"contentAvailable"]) {
136
+ [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_message_received"
137
+ body:notificationDict];
138
+ }
139
+ completionHandler(presentationOptions);
140
+ }
141
+
142
+ if (_originalDelegate != nil && originalDelegateRespondsTo.willPresentNotification) {
143
+ [_originalDelegate userNotificationCenter:center
144
+ willPresentNotification:notification
145
+ withCompletionHandler:completionHandler];
146
+ } else {
147
+ completionHandler(presentationOptions);
148
+ }
149
+ }
150
+
151
+ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
152
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
153
+ withCompletionHandler:(void (^)(void))completionHandler {
154
+ NSDictionary *remoteNotification = response.notification.request.content.userInfo;
155
+ if (remoteNotification[@"gcm.message_id"]) {
156
+ NSDictionary *notificationDict =
157
+ [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification];
158
+ [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened"
159
+ body:notificationDict];
160
+ _initialNotification = notificationDict;
161
+ }
162
+
163
+ if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) {
164
+ [_originalDelegate userNotificationCenter:center
165
+ didReceiveNotificationResponse:response
166
+ withCompletionHandler:completionHandler];
167
+ } else {
168
+ completionHandler();
169
+ }
170
+ }
171
+
172
+ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
173
+ openSettingsForNotification:(nullable UNNotification *)notification {
174
+ if (_originalDelegate != nil && originalDelegateRespondsTo.openSettingsForNotification) {
175
+ [_originalDelegate userNotificationCenter:center openSettingsForNotification:notification];
176
+ } else {
177
+ NSDictionary *notificationDict = [RNFBMessagingSerializer notificationToDict:notification];
178
+ [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_settings_for_notification_opened"
179
+ body:notificationDict];
180
+
181
+ _didOpenSettingsForNotification = YES;
182
+ }
183
+ }
184
+
185
+ @end
@@ -0,0 +1,26 @@
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
+ #import <React/RCTBridgeModule.h>
20
+
21
+ @interface RNFBMessagingModule : NSObject <RCTBridgeModule>
22
+ + (NSDictionary *_Nonnull)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps
23
+ withLaunchOptions:(NSDictionary *_Nullable)launchOptions;
24
+ @property BOOL isDeliveryMetricsExportToBigQueryEnabled;
25
+
26
+ @end
@@ -0,0 +1,431 @@
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 <RNFBApp/RNFBSharedUtils.h>
20
+ #import <React/RCTConvert.h>
21
+ #import <React/RCTUtils.h>
22
+
23
+ #import "RNFBMessaging+AppDelegate.h"
24
+ #import "RNFBMessaging+NSNotificationCenter.h"
25
+ #import "RNFBMessaging+UNUserNotificationCenter.h"
26
+ #import "RNFBMessagingModule.h"
27
+ #import "RNFBMessagingSerializer.h"
28
+
29
+ @implementation RNFBMessagingModule
30
+ #pragma mark -
31
+ #pragma mark Module Setup
32
+
33
+ RCT_EXPORT_MODULE();
34
+
35
+ - (id)init {
36
+ self = [super init];
37
+ return self;
38
+ }
39
+
40
+ - (dispatch_queue_t)methodQueue {
41
+ return dispatch_get_main_queue();
42
+ }
43
+
44
+ + (BOOL)requiresMainQueueSetup {
45
+ return YES;
46
+ }
47
+
48
+ + (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps
49
+ withLaunchOptions:(NSDictionary *_Nullable)launchOptions {
50
+ NSMutableDictionary *appProperties =
51
+ userProps != nil ? [userProps mutableCopy] : [NSMutableDictionary dictionary];
52
+ appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
53
+
54
+ if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
55
+ if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
56
+ appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
57
+ }
58
+ }
59
+
60
+ return [NSDictionary dictionaryWithDictionary:appProperties];
61
+ }
62
+
63
+ - (NSDictionary *)constantsToExport {
64
+ NSMutableDictionary *constants = [NSMutableDictionary new];
65
+ constants[@"isAutoInitEnabled"] =
66
+ @([RCTConvert BOOL:@([FIRMessaging messaging].autoInitEnabled)]);
67
+ constants[@"isRegisteredForRemoteNotifications"] = @(
68
+ [RCTConvert BOOL:@([[UIApplication sharedApplication] isRegisteredForRemoteNotifications])]);
69
+ constants[@"isDeliveryMetricsExportToBigQueryEnabled"] =
70
+ @([RCTConvert BOOL:@(_isDeliveryMetricsExportToBigQueryEnabled)]);
71
+ return constants;
72
+ }
73
+
74
+ #pragma mark -
75
+ #pragma mark Firebase Messaging Methods
76
+
77
+ RCT_EXPORT_METHOD(getInitialNotification
78
+ : (RCTPromiseResolveBlock)resolve
79
+ : (RCTPromiseRejectBlock)reject) {
80
+ resolve([[RNFBMessagingUNUserNotificationCenter sharedInstance] getInitialNotification]);
81
+ }
82
+
83
+ RCT_EXPORT_METHOD(getDidOpenSettingsForNotification
84
+ : (RCTPromiseResolveBlock)resolve
85
+ : (RCTPromiseRejectBlock)reject) {
86
+ resolve(
87
+ [[RNFBMessagingUNUserNotificationCenter sharedInstance] getDidOpenSettingsForNotification]);
88
+ }
89
+
90
+ RCT_EXPORT_METHOD(setAutoInitEnabled
91
+ : (BOOL)enabled
92
+ : (RCTPromiseResolveBlock)resolve
93
+ : (RCTPromiseRejectBlock)reject) {
94
+ @try {
95
+ [FIRMessaging messaging].autoInitEnabled = enabled;
96
+ } @catch (NSException *exception) {
97
+ return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
98
+ }
99
+
100
+ return resolve([NSNull null]);
101
+ }
102
+
103
+ RCT_EXPORT_METHOD(signalBackgroundMessageHandlerSet) {
104
+ DLog(@"signalBackgroundMessageHandlerSet called");
105
+ @try {
106
+ [[RNFBMessagingAppDelegate sharedInstance] signalBackgroundMessageHandlerSet];
107
+ } @catch (NSException *exception) {
108
+ ELog(@"signalBackgroundMessageHandlerSet failed");
109
+ }
110
+ }
111
+
112
+ RCT_EXPORT_METHOD(getToken
113
+ : (NSString *)appName
114
+ : (NSString *)senderId
115
+ : (RCTPromiseResolveBlock)resolve
116
+ : (RCTPromiseRejectBlock)reject) {
117
+ if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
118
+ [RNFBSharedUtils
119
+ rejectPromiseWithUserInfo:reject
120
+ userInfo:(NSMutableDictionary *)@{
121
+ @"code" : @"unregistered",
122
+ @"message" :
123
+ @"You must be registered for remote messages before calling "
124
+ @"getToken, see messaging().registerDeviceForRemoteMessages().",
125
+ }];
126
+ return;
127
+ }
128
+
129
+ // As of firebase-ios-sdk 10.4.0, an APNS token is strictly required for getToken to work
130
+ NSData *apnsToken = [FIRMessaging messaging].APNSToken;
131
+ if (apnsToken == nil) {
132
+ DLog(@"RNFBMessaging getToken - no APNS token is available. Firebase requires an APNS token to "
133
+ @"vend an FCM token in firebase-ios-sdk 10.4.0 and higher. See documentation on "
134
+ @"setAPNSToken and getAPNSToken.")
135
+ }
136
+
137
+ [[FIRMessaging messaging]
138
+ retrieveFCMTokenForSenderID:senderId
139
+ completion:^(NSString *_Nullable token, NSError *_Nullable error) {
140
+ if (error) {
141
+ [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
142
+ } else {
143
+ resolve(token);
144
+ }
145
+ }];
146
+ }
147
+
148
+ RCT_EXPORT_METHOD(deleteToken
149
+ : (NSString *)appName
150
+ : (NSString *)senderId
151
+ : (RCTPromiseResolveBlock)resolve
152
+ : (RCTPromiseRejectBlock)reject) {
153
+ [[FIRMessaging messaging] deleteFCMTokenForSenderID:senderId
154
+ completion:^(NSError *_Nullable error) {
155
+ if (error) {
156
+ [RNFBSharedUtils rejectPromiseWithNSError:reject
157
+ error:error];
158
+ } else {
159
+ resolve([NSNull null]);
160
+ }
161
+ }];
162
+ }
163
+
164
+ RCT_EXPORT_METHOD(getAPNSToken : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
165
+ NSData *apnsToken = [FIRMessaging messaging].APNSToken;
166
+ if (apnsToken) {
167
+ resolve([RNFBMessagingSerializer APNSTokenFromNSData:apnsToken]);
168
+ } else {
169
+ #if TARGET_IPHONE_SIMULATOR
170
+ #if !TARGET_CPU_ARM64
171
+ DLog(@"RNFBMessaging getAPNSToken - Simulator without APNS support detected, with no token "
172
+ @"set. Use setAPNSToken with an arbitrary string if needed for testing.")
173
+ resolve([NSNull null]);
174
+ return;
175
+ #endif
176
+ DLog(@"RNFBMessaging getAPNSToken - ARM64 Simulator detected, but no APNS token available. "
177
+ @"APNS token may be possible. macOS13+ / iOS16+ / M1 mac required for assumption to be "
178
+ @"valid. "
179
+ @"Use setAPNSToken in testing if needed.");
180
+ #endif
181
+ if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
182
+ [RNFBSharedUtils
183
+ rejectPromiseWithUserInfo:reject
184
+ userInfo:(NSMutableDictionary *)@{
185
+ @"code" : @"unregistered",
186
+ @"message" : @"You must be registered for remote messages before "
187
+ @"calling getAPNSToken, see "
188
+ @"messaging().registerDeviceForRemoteMessages().",
189
+ }];
190
+ return;
191
+ }
192
+ resolve([NSNull null]);
193
+ }
194
+ }
195
+
196
+ RCT_EXPORT_METHOD(setAPNSToken
197
+ : (NSString *)token
198
+ : (NSString *)type
199
+ : (RCTPromiseResolveBlock)resolve
200
+ : (RCTPromiseRejectBlock)reject) {
201
+ // Default to unknown (determined by provisioning profile) type, but user may have passed type as
202
+ // param
203
+ FIRMessagingAPNSTokenType tokenType = FIRMessagingAPNSTokenTypeUnknown;
204
+ if (type != nil && [@"prod" isEqualToString:type]) {
205
+ tokenType = FIRMessagingAPNSTokenTypeProd;
206
+ } else if (type != nil && [@"sandbox" isEqualToString:type]) {
207
+ tokenType = FIRMessagingAPNSTokenTypeSandbox;
208
+ }
209
+
210
+ [[FIRMessaging messaging] setAPNSToken:[RNFBMessagingSerializer APNSTokenDataFromNSString:token]
211
+ type:tokenType];
212
+ resolve([NSNull null]);
213
+ }
214
+
215
+ RCT_EXPORT_METHOD(getIsHeadless : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
216
+ RNFBMessagingNSNotificationCenter *notifCenter =
217
+ [RNFBMessagingNSNotificationCenter sharedInstance];
218
+
219
+ return resolve(@([RCTConvert BOOL:@(notifCenter.isHeadless)]));
220
+ }
221
+
222
+ RCT_EXPORT_METHOD(completeNotificationProcessing) {
223
+ dispatch_get_main_queue(), ^{
224
+ RNFBMessagingAppDelegate *appDelegate = [RNFBMessagingAppDelegate sharedInstance];
225
+ if (appDelegate.completionHandler) {
226
+ appDelegate.completionHandler(UIBackgroundFetchResultNewData);
227
+ appDelegate.completionHandler = nil;
228
+ }
229
+ if (appDelegate.backgroundTaskId != UIBackgroundTaskInvalid) {
230
+ [[UIApplication sharedApplication] endBackgroundTask:appDelegate.backgroundTaskId];
231
+ appDelegate.backgroundTaskId = UIBackgroundTaskInvalid;
232
+ }
233
+ };
234
+ }
235
+
236
+ RCT_EXPORT_METHOD(requestPermission
237
+ : (NSDictionary *)permissions
238
+ : (RCTPromiseResolveBlock)resolve
239
+ : (RCTPromiseRejectBlock)reject) {
240
+ if (RCTRunningInAppExtension()) {
241
+ [RNFBSharedUtils
242
+ rejectPromiseWithUserInfo:reject
243
+ userInfo:[@{
244
+ @"code" : @"unavailable-in-extension",
245
+ @"message" : @"requestPermission can not be called in App Extensions"
246
+ } mutableCopy]];
247
+ return;
248
+ }
249
+
250
+ UNAuthorizationOptions options = UNAuthorizationOptionNone;
251
+
252
+ if ([permissions[@"alert"] isEqual:@(YES)]) {
253
+ options |= UNAuthorizationOptionAlert;
254
+ }
255
+
256
+ if ([permissions[@"badge"] isEqual:@(YES)]) {
257
+ options |= UNAuthorizationOptionBadge;
258
+ }
259
+
260
+ if ([permissions[@"sound"] isEqual:@(YES)]) {
261
+ options |= UNAuthorizationOptionSound;
262
+ }
263
+
264
+ if ([permissions[@"criticalAlert"] isEqual:@(YES)]) {
265
+ options |= UNAuthorizationOptionCriticalAlert;
266
+ }
267
+
268
+ if ([permissions[@"provisional"] isEqual:@(YES)]) {
269
+ options |= UNAuthorizationOptionProvisional;
270
+ }
271
+
272
+ if ([permissions[@"announcement"] isEqual:@(YES)]) {
273
+ options |= UNAuthorizationOptionAnnouncement;
274
+ }
275
+
276
+ if ([permissions[@"carPlay"] isEqual:@(YES)]) {
277
+ options |= UNAuthorizationOptionCarPlay;
278
+ }
279
+
280
+ if ([permissions[@"providesAppNotificationSettings"] isEqual:@(YES)]) {
281
+ options |= UNAuthorizationOptionProvidesAppNotificationSettings;
282
+ }
283
+
284
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
285
+ [center requestAuthorizationWithOptions:options
286
+ completionHandler:^(BOOL granted, NSError *_Nullable error) {
287
+ if (error) {
288
+ [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
289
+ } else {
290
+ // if we do not attempt to register immediately, registration fails
291
+ // later unknown reason why, but this was the only difference between
292
+ // using a react-native-permissions vs built-in permissions request in
293
+ // a sequence of "request permissions" --> "register for messages" you
294
+ // only want to request permission if you want to register for
295
+ // messages, so we register directly now - see #7272
296
+ dispatch_async(dispatch_get_main_queue(), ^{
297
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
298
+ });
299
+ [self hasPermission:resolve:reject];
300
+ }
301
+ }];
302
+ }
303
+
304
+ RCT_EXPORT_METHOD(registerForRemoteNotifications
305
+ : (RCTPromiseResolveBlock)resolve
306
+ : (RCTPromiseRejectBlock)reject) {
307
+ #if TARGET_IPHONE_SIMULATOR
308
+ #if !TARGET_CPU_ARM64
309
+ // Register on this unsupported simulator, but no waiting for a token that won't arrive
310
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
311
+ resolve(@([RCTConvert BOOL:@(YES)]));
312
+ return;
313
+ #endif
314
+ DLog(@"RNFBMessaging registerForRemoteNotifications ARM64 Simulator detected, attempting real "
315
+ @"registration. macOS13+ / iOS16+ / M1 mac required or will timeout.")
316
+ #endif
317
+ if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == YES) {
318
+ DLog(@"RNFBMessaging registerForRemoteNotifications - already registered.");
319
+ resolve(@([RCTConvert BOOL:@(YES)]));
320
+ return;
321
+ }
322
+ else {
323
+ [[RNFBMessagingAppDelegate sharedInstance] setPromiseResolve:resolve andPromiseReject:reject];
324
+ }
325
+
326
+ // Apple docs recommend that registerForRemoteNotifications is always called on app start
327
+ // regardless of current status
328
+ dispatch_async(dispatch_get_main_queue(), ^{
329
+ // Sometimes the registration never completes, which deserves separate attention in other
330
+ // areas. This area should protect itself against hanging forever regardless. Just in case,
331
+ // check in after a delay and cleanup if required
332
+ dispatch_after(
333
+ dispatch_time(DISPATCH_TIME_NOW, 10.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
334
+ if ([RNFBMessagingAppDelegate sharedInstance].registerPromiseResolver != nil) {
335
+ // if we got here and resolve/reject are still set, unset, log failure, reject
336
+ DLog(@"RNFBMessaging dispatch_after block: we appear to have timed out. Rejecting");
337
+ [[RNFBMessagingAppDelegate sharedInstance] setPromiseResolve:nil andPromiseReject:nil];
338
+
339
+ [RNFBSharedUtils
340
+ rejectPromiseWithUserInfo:reject
341
+ userInfo:[@{
342
+ @"code" : @"unknown-error",
343
+ @"message" :
344
+ @"registerDeviceForRemoteMessages requested but "
345
+ @"system did not respond. Possibly missing permission."
346
+ } mutableCopy]];
347
+ return;
348
+ } else {
349
+ DLog(@"RNFBMessaging dispatch_after: registerDeviceForRemoteMessages handled.");
350
+ return;
351
+ }
352
+ });
353
+
354
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
355
+ });
356
+ }
357
+
358
+ RCT_EXPORT_METHOD(unregisterForRemoteNotifications
359
+ : (RCTPromiseResolveBlock)resolve
360
+ : (RCTPromiseRejectBlock)reject) {
361
+ [[UIApplication sharedApplication] unregisterForRemoteNotifications];
362
+ resolve(nil);
363
+ }
364
+
365
+ RCT_EXPORT_METHOD(hasPermission : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
366
+ [[UNUserNotificationCenter currentNotificationCenter]
367
+ getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) {
368
+ NSNumber *authorizedStatus = @-1;
369
+ if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
370
+ authorizedStatus = @-1;
371
+ } else if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
372
+ authorizedStatus = @0;
373
+ } else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
374
+ authorizedStatus = @1;
375
+ } else if (settings.authorizationStatus == UNAuthorizationStatusProvisional) {
376
+ authorizedStatus = @2;
377
+ }
378
+
379
+ if (@available(iOS 14.0, macCatalyst 14.0, *)) {
380
+ if (settings.authorizationStatus == UNAuthorizationStatusEphemeral) {
381
+ authorizedStatus = @3;
382
+ }
383
+ }
384
+
385
+ resolve(authorizedStatus);
386
+ }];
387
+ }
388
+
389
+ RCT_EXPORT_METHOD(subscribeToTopic
390
+ : (NSString *)topic
391
+ : (RCTPromiseResolveBlock)resolve
392
+ : (RCTPromiseRejectBlock)reject) {
393
+ [[FIRMessaging messaging] subscribeToTopic:topic
394
+ completion:^(NSError *error) {
395
+ if (error) {
396
+ [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
397
+ } else {
398
+ resolve(nil);
399
+ }
400
+ }];
401
+ }
402
+
403
+ RCT_EXPORT_METHOD(unsubscribeFromTopic
404
+ : (NSString *)topic
405
+ : (RCTPromiseResolveBlock)resolve
406
+ : (RCTPromiseRejectBlock)reject) {
407
+ [[FIRMessaging messaging] unsubscribeFromTopic:topic
408
+ completion:^(NSError *error) {
409
+ if (error) {
410
+ [RNFBSharedUtils rejectPromiseWithNSError:reject
411
+ error:error];
412
+ } else {
413
+ resolve(nil);
414
+ }
415
+ }];
416
+ }
417
+
418
+ RCT_EXPORT_METHOD(setDeliveryMetricsExportToBigQuery
419
+ : (BOOL)enabled
420
+ : (RCTPromiseResolveBlock)resolve
421
+ : (RCTPromiseRejectBlock)reject) {
422
+ @try {
423
+ _isDeliveryMetricsExportToBigQueryEnabled = enabled;
424
+ } @catch (NSException *exception) {
425
+ return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
426
+ }
427
+
428
+ return resolve([NSNull null]);
429
+ }
430
+
431
+ @end
@@ -0,0 +1,32 @@
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
+ #import <React/RCTBridgeModule.h>
21
+
22
+ @interface RNFBMessagingSerializer : NSObject
23
+
24
+ + (NSData *)APNSTokenDataFromNSString:(NSString *)token;
25
+
26
+ + (NSString *)APNSTokenFromNSData:(NSData *)tokenData;
27
+
28
+ + (NSDictionary *)notificationToDict:(UNNotification *)notification;
29
+
30
+ + (NSDictionary *)remoteMessageUserInfoToDict:(NSDictionary *)userInfo;
31
+
32
+ @end