@react-native-firebase/messaging 25.1.0 → 26.0.0
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 +29 -0
- package/RNFBMessaging.podspec +20 -6
- package/android/build.gradle +24 -0
- package/android/src/main/java/io/invertase/firebase/messaging/{ReactNativeFirebaseMessagingModule.java → NativeRNFBTurboMessaging.java} +143 -81
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingPackage.java +1 -1
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingReceiver.java +16 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreImpl.java +50 -11
- package/android/src/main/java/io/invertase/firebase/messaging/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboMessagingSpec.java +151 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/CMakeLists.txt +36 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/RNFBMessagingTurboModules-generated.cpp +152 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/RNFBMessagingTurboModules.h +31 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/react/renderer/components/RNFBMessagingTurboModules/RNFBMessagingTurboModulesJSI-generated.cpp +161 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/react/renderer/components/RNFBMessagingTurboModules/RNFBMessagingTurboModulesJSI.h +356 -0
- package/app.plugin.js +1 -1
- package/dist/module/index.js +622 -7
- package/dist/module/index.js.map +1 -1
- package/dist/module/statics.js +1 -1
- package/dist/module/types/internal.js +4 -0
- package/dist/module/types/internal.js.map +1 -0
- package/dist/module/types/messaging.js +0 -15
- package/dist/module/types/messaging.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/index.d.ts +182 -5
- package/dist/typescript/lib/index.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +41 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -0
- package/dist/typescript/lib/types/messaging.d.ts +7 -55
- package/dist/typescript/lib/types/messaging.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h +24 -2
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.m +82 -12
- package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.m +14 -4
- package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +31 -28
- package/ios/RNFBMessaging/RNFBMessagingModule.h +3 -2
- package/ios/RNFBMessaging/RNFBMessagingModule.mm +500 -0
- package/ios/RNFBMessaging.xcodeproj/project.pbxproj +8 -8
- package/ios/generated/RCTAppDependencyProvider.h +25 -0
- package/ios/generated/RCTAppDependencyProvider.mm +55 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.mm +23 -0
- package/ios/generated/RNFBMessagingTurboModules/RNFBMessagingTurboModules-generated.mm +184 -0
- package/ios/generated/RNFBMessagingTurboModules/RNFBMessagingTurboModules.h +222 -0
- package/ios/generated/RNFBMessagingTurboModulesJSI-generated.cpp +161 -0
- package/ios/generated/RNFBMessagingTurboModulesJSI.h +356 -0
- package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
- package/lib/index.ts +821 -15
- package/lib/statics.ts +1 -1
- package/lib/types/internal.ts +59 -0
- package/lib/types/messaging.ts +7 -72
- package/lib/version.ts +1 -1
- package/package.json +30 -5
- package/plugin/build/app.plugin.d.ts +2 -0
- package/plugin/build/app.plugin.js +6 -0
- package/plugin/src/app.plugin.ts +3 -0
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/react-native.config.js +10 -0
- package/specs/NativeRNFBTurboMessaging.ts +46 -0
- package/typedoc.json +2 -19
- package/dist/module/modular.js +0 -396
- package/dist/module/modular.js.map +0 -1
- package/dist/module/namespaced.js +0 -415
- package/dist/module/namespaced.js.map +0 -1
- package/dist/typescript/lib/modular.d.ts +0 -255
- package/dist/typescript/lib/modular.d.ts.map +0 -1
- package/dist/typescript/lib/namespaced.d.ts +0 -12
- package/dist/typescript/lib/namespaced.d.ts.map +0 -1
- package/ios/RNFBMessaging/RNFBMessagingModule.m +0 -439
- package/lib/modular.ts +0 -455
- package/lib/namespaced.ts +0 -593
|
@@ -106,24 +106,13 @@ struct {
|
|
|
106
106
|
// if list or banner is true, ignore `alert` property
|
|
107
107
|
if (banner || list) {
|
|
108
108
|
if (banner) {
|
|
109
|
-
|
|
110
|
-
presentationOptions |= UNNotificationPresentationOptionBanner;
|
|
111
|
-
} else {
|
|
112
|
-
// for iOS 13 we need to set `alert`
|
|
113
|
-
presentationOptions |= UNNotificationPresentationOptionAlert;
|
|
114
|
-
}
|
|
109
|
+
presentationOptions |= UNNotificationPresentationOptionBanner;
|
|
115
110
|
}
|
|
116
111
|
|
|
117
112
|
if (list) {
|
|
118
|
-
|
|
119
|
-
presentationOptions |= UNNotificationPresentationOptionList;
|
|
120
|
-
} else {
|
|
121
|
-
// for iOS 13 we need to set `alert`
|
|
122
|
-
presentationOptions |= UNNotificationPresentationOptionAlert;
|
|
123
|
-
}
|
|
113
|
+
presentationOptions |= UNNotificationPresentationOptionList;
|
|
124
114
|
}
|
|
125
115
|
} else if (alert) {
|
|
126
|
-
// TODO: Remove `alert` once iOS 14 becomes the minimum deployment target
|
|
127
116
|
presentationOptions |= UNNotificationPresentationOptionAlert;
|
|
128
117
|
}
|
|
129
118
|
|
|
@@ -139,22 +128,32 @@ struct {
|
|
|
139
128
|
}
|
|
140
129
|
}
|
|
141
130
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
131
|
+
// completionHandler must be invoked exactly once. If the original delegate
|
|
132
|
+
// implements willPresentNotification, defer to it entirely - it owns the
|
|
133
|
+
// completionHandler contract (and may call it asynchronously). Only fall
|
|
134
|
+
// back to our own presentationOptions when there is no original delegate
|
|
135
|
+
// to hand off to.
|
|
136
|
+
//
|
|
137
|
+
// _originalDelegate is weak, so it is captured into a strong local first -
|
|
138
|
+
// otherwise it could be deallocated between the nil-check and the message
|
|
139
|
+
// send (turning the send into a no-op) and completionHandler would never
|
|
140
|
+
// be called at all.
|
|
141
|
+
id<UNUserNotificationCenterDelegate> strongOriginalDelegate = _originalDelegate;
|
|
142
|
+
if (strongOriginalDelegate != nil && originalDelegateRespondsTo.willPresentNotification) {
|
|
143
|
+
[strongOriginalDelegate userNotificationCenter:center
|
|
144
|
+
willPresentNotification:notification
|
|
145
|
+
withCompletionHandler:completionHandler];
|
|
146
|
+
} else {
|
|
147
|
+
completionHandler(presentationOptions);
|
|
146
148
|
}
|
|
147
|
-
|
|
148
|
-
// Don't consume completionHandler before the _originalDelegate has been
|
|
149
|
-
// processed
|
|
150
|
-
completionHandler(presentationOptions);
|
|
151
149
|
}
|
|
152
150
|
|
|
153
151
|
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|
154
152
|
didReceiveNotificationResponse:(UNNotificationResponse *)response
|
|
155
153
|
withCompletionHandler:(void (^)(void))completionHandler {
|
|
156
154
|
NSDictionary *remoteNotification = response.notification.request.content.userInfo;
|
|
157
|
-
if (
|
|
155
|
+
if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier] &&
|
|
156
|
+
remoteNotification[@"gcm.message_id"]) {
|
|
158
157
|
NSDictionary *notificationDict =
|
|
159
158
|
[RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification];
|
|
160
159
|
[[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened"
|
|
@@ -162,10 +161,13 @@ struct {
|
|
|
162
161
|
_initialNotification = notificationDict;
|
|
163
162
|
}
|
|
164
163
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
// _originalDelegate is weak — capture strong local before nil-check + message
|
|
165
|
+
// (same race as willPresent; otherwise completionHandler may never run).
|
|
166
|
+
id<UNUserNotificationCenterDelegate> strongOriginalDelegate = _originalDelegate;
|
|
167
|
+
if (strongOriginalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) {
|
|
168
|
+
[strongOriginalDelegate userNotificationCenter:center
|
|
169
|
+
didReceiveNotificationResponse:response
|
|
170
|
+
withCompletionHandler:completionHandler];
|
|
169
171
|
} else {
|
|
170
172
|
completionHandler();
|
|
171
173
|
}
|
|
@@ -173,8 +175,9 @@ struct {
|
|
|
173
175
|
|
|
174
176
|
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|
175
177
|
openSettingsForNotification:(nullable UNNotification *)notification {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
id<UNUserNotificationCenterDelegate> strongOriginalDelegate = _originalDelegate;
|
|
179
|
+
if (strongOriginalDelegate != nil && originalDelegateRespondsTo.openSettingsForNotification) {
|
|
180
|
+
[strongOriginalDelegate userNotificationCenter:center openSettingsForNotification:notification];
|
|
178
181
|
} else {
|
|
179
182
|
NSDictionary *notificationDict = [RNFBMessagingSerializer notificationToDict:notification];
|
|
180
183
|
[[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_settings_for_notification_opened"
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
#import <Foundation/Foundation.h>
|
|
19
|
-
#import <React/RCTBridgeModule.h>
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
// Public / AppDelegate-safe: no C++/codegen imports. TurboModule conformance lives in .mm.
|
|
21
|
+
// Kept public for documented isHeadless integration via addCustomPropsToUserProps.
|
|
22
|
+
@interface RNFBMessagingModule : NSObject
|
|
22
23
|
+ (NSDictionary *_Nonnull)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps
|
|
23
24
|
withLaunchOptions:(NSDictionary *_Nullable)launchOptions;
|
|
24
25
|
@property BOOL isDeliveryMetricsExportToBigQueryEnabled;
|
|
@@ -0,0 +1,500 @@
|
|
|
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
|
+
#import "RNFBMessagingTurboModules.h"
|
|
29
|
+
|
|
30
|
+
@interface RNFBMessagingModule () <NativeRNFBTurboMessagingSpec>
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
@implementation RNFBMessagingModule
|
|
34
|
+
#pragma mark -
|
|
35
|
+
#pragma mark Module Setup
|
|
36
|
+
|
|
37
|
+
RCT_EXPORT_MODULE(NativeRNFBTurboMessaging)
|
|
38
|
+
|
|
39
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
40
|
+
return NO;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (id)init {
|
|
44
|
+
self = [super init];
|
|
45
|
+
return self;
|
|
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 *)messagingConstantsDictionary {
|
|
64
|
+
NSMutableDictionary *constants = [NSMutableDictionary new];
|
|
65
|
+
constants[@"isAutoInitEnabled"] =
|
|
66
|
+
@([RCTConvert BOOL:@([FIRMessaging messaging].autoInitEnabled)]);
|
|
67
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
68
|
+
constants[@"isRegisteredForRemoteNotifications"] = @NO;
|
|
69
|
+
#else
|
|
70
|
+
constants[@"isRegisteredForRemoteNotifications"] = @(
|
|
71
|
+
[RCTConvert BOOL:@([[UIApplication sharedApplication] isRegisteredForRemoteNotifications])]);
|
|
72
|
+
#endif
|
|
73
|
+
constants[@"isDeliveryMetricsExportToBigQueryEnabled"] =
|
|
74
|
+
@([RCTConvert BOOL:@(_isDeliveryMetricsExportToBigQueryEnabled)]);
|
|
75
|
+
return constants;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
- (facebook::react::ModuleConstants<JS::NativeRNFBTurboMessaging::Constants::Builder>)
|
|
79
|
+
constantsToExport {
|
|
80
|
+
return [_RCTTypedModuleConstants newWithUnsafeDictionary:[self messagingConstantsDictionary]];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
- (facebook::react::ModuleConstants<JS::NativeRNFBTurboMessaging::Constants::Builder>)getConstants {
|
|
84
|
+
return [self constantsToExport];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
88
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
89
|
+
return std::make_shared<facebook::react::NativeRNFBTurboMessagingSpecJSI>(params);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#pragma mark -
|
|
93
|
+
#pragma mark Firebase Messaging Methods
|
|
94
|
+
|
|
95
|
+
- (void)getInitialNotification:(RCTPromiseResolveBlock)resolve
|
|
96
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
97
|
+
resolve([[RNFBMessagingUNUserNotificationCenter sharedInstance] getInitialNotification]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
- (void)getDidOpenSettingsForNotification:(RCTPromiseResolveBlock)resolve
|
|
101
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
102
|
+
resolve(
|
|
103
|
+
[[RNFBMessagingUNUserNotificationCenter sharedInstance] getDidOpenSettingsForNotification]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)setAutoInitEnabled:(BOOL)enabled
|
|
107
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
108
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
109
|
+
@try {
|
|
110
|
+
[FIRMessaging messaging].autoInitEnabled = enabled;
|
|
111
|
+
} @catch (NSException *exception) {
|
|
112
|
+
return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return resolve([NSNull null]);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
- (void)signalBackgroundMessageHandlerSet {
|
|
119
|
+
DLog(@"signalBackgroundMessageHandlerSet called");
|
|
120
|
+
@try {
|
|
121
|
+
[[RNFBMessagingAppDelegate sharedInstance] signalBackgroundMessageHandlerSet];
|
|
122
|
+
} @catch (NSException *exception) {
|
|
123
|
+
ELog(@"signalBackgroundMessageHandlerSet failed");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
- (void)getToken:(NSString *)appName
|
|
128
|
+
senderId:(NSString *)senderId
|
|
129
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
130
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
131
|
+
if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
|
|
132
|
+
[RNFBSharedUtils
|
|
133
|
+
rejectPromiseWithUserInfo:reject
|
|
134
|
+
userInfo:(NSMutableDictionary *)@{
|
|
135
|
+
@"code" : @"unregistered",
|
|
136
|
+
@"message" : @"You must be registered for remote "
|
|
137
|
+
@"messages before calling "
|
|
138
|
+
@"getToken, see "
|
|
139
|
+
@"registerDeviceForRemoteMessages(getMessaging()).",
|
|
140
|
+
}];
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NSData *apnsToken = [FIRMessaging messaging].APNSToken;
|
|
145
|
+
if (apnsToken == nil) {
|
|
146
|
+
DLog(@"RNFBMessaging getToken - no APNS token is available. Firebase "
|
|
147
|
+
@"requires an APNS token to "
|
|
148
|
+
@"vend an FCM token in firebase-ios-sdk 10.4.0 and higher. See "
|
|
149
|
+
@"documentation on "
|
|
150
|
+
@"setAPNSToken and getAPNSToken.")
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
[[FIRMessaging messaging]
|
|
154
|
+
retrieveFCMTokenForSenderID:senderId
|
|
155
|
+
completion:^(NSString *_Nullable token, NSError *_Nullable error) {
|
|
156
|
+
if (error) {
|
|
157
|
+
[RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
|
|
158
|
+
} else {
|
|
159
|
+
resolve(token);
|
|
160
|
+
}
|
|
161
|
+
}];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
- (void)deleteToken:(NSString *)appName
|
|
165
|
+
senderId:(NSString *)senderId
|
|
166
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
167
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
168
|
+
[[FIRMessaging messaging] deleteFCMTokenForSenderID:senderId
|
|
169
|
+
completion:^(NSError *_Nullable error) {
|
|
170
|
+
if (error) {
|
|
171
|
+
[RNFBSharedUtils rejectPromiseWithNSError:reject
|
|
172
|
+
error:error];
|
|
173
|
+
} else {
|
|
174
|
+
resolve([NSNull null]);
|
|
175
|
+
}
|
|
176
|
+
}];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
- (void)getAPNSToken:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
180
|
+
NSData *apnsToken = [FIRMessaging messaging].APNSToken;
|
|
181
|
+
if (apnsToken) {
|
|
182
|
+
resolve([RNFBMessagingSerializer APNSTokenFromNSData:apnsToken]);
|
|
183
|
+
} else {
|
|
184
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
185
|
+
#if !TARGET_CPU_ARM64
|
|
186
|
+
DLog(@"RNFBMessaging getAPNSToken - Simulator without APNS support "
|
|
187
|
+
@"detected, with no token "
|
|
188
|
+
@"set. Use setAPNSToken with an arbitrary string if needed for "
|
|
189
|
+
@"testing.") resolve([NSNull null]);
|
|
190
|
+
return;
|
|
191
|
+
#endif
|
|
192
|
+
DLog(@"RNFBMessaging getAPNSToken - ARM64 Simulator detected, but no APNS "
|
|
193
|
+
@"token available. "
|
|
194
|
+
@"APNS token may be possible. macOS13+ / iOS16+ / M1 mac required for "
|
|
195
|
+
@"assumption to be "
|
|
196
|
+
@"valid. "
|
|
197
|
+
@"Use setAPNSToken in testing if needed.");
|
|
198
|
+
#endif
|
|
199
|
+
if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
|
|
200
|
+
[RNFBSharedUtils
|
|
201
|
+
rejectPromiseWithUserInfo:reject
|
|
202
|
+
userInfo:(NSMutableDictionary *)@{
|
|
203
|
+
@"code" : @"unregistered",
|
|
204
|
+
@"message" : @"You must be registered for remote "
|
|
205
|
+
@"messages before "
|
|
206
|
+
@"calling getAPNSToken, see "
|
|
207
|
+
@"registerDeviceForRemoteMessages(getMessaging()).",
|
|
208
|
+
}];
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
resolve([NSNull null]);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
- (void)setAPNSToken:(NSString *)token
|
|
216
|
+
type:(NSString *)type
|
|
217
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
218
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
219
|
+
FIRMessagingAPNSTokenType tokenType = FIRMessagingAPNSTokenTypeUnknown;
|
|
220
|
+
if (type != nil && [@"prod" isEqualToString:type]) {
|
|
221
|
+
tokenType = FIRMessagingAPNSTokenTypeProd;
|
|
222
|
+
} else if (type != nil && [@"sandbox" isEqualToString:type]) {
|
|
223
|
+
tokenType = FIRMessagingAPNSTokenTypeSandbox;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
[[FIRMessaging messaging] setAPNSToken:[RNFBMessagingSerializer APNSTokenDataFromNSString:token]
|
|
227
|
+
type:tokenType];
|
|
228
|
+
resolve([NSNull null]);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
- (void)getIsHeadless:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
232
|
+
RNFBMessagingNSNotificationCenter *notifCenter =
|
|
233
|
+
[RNFBMessagingNSNotificationCenter sharedInstance];
|
|
234
|
+
|
|
235
|
+
return resolve(@([RCTConvert BOOL:@(notifCenter.isHeadless)]));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
- (void)completeNotificationProcessing {
|
|
239
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
240
|
+
RNFBMessagingAppDelegate *appDelegate = [RNFBMessagingAppDelegate sharedInstance];
|
|
241
|
+
if (appDelegate.completionHandler) {
|
|
242
|
+
appDelegate.completionHandler(UIBackgroundFetchResultNewData);
|
|
243
|
+
appDelegate.completionHandler = nil;
|
|
244
|
+
}
|
|
245
|
+
if (appDelegate.backgroundTaskId != UIBackgroundTaskInvalid) {
|
|
246
|
+
[[UIApplication sharedApplication] endBackgroundTask:appDelegate.backgroundTaskId];
|
|
247
|
+
appDelegate.backgroundTaskId = UIBackgroundTaskInvalid;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
- (void)requestPermission:(JS::NativeRNFBTurboMessaging::IOSPermissions &)permissions
|
|
253
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
254
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
255
|
+
if (RCTRunningInAppExtension()) {
|
|
256
|
+
[RNFBSharedUtils rejectPromiseWithUserInfo:reject
|
|
257
|
+
userInfo:[@{
|
|
258
|
+
@"code" : @"unavailable-in-extension",
|
|
259
|
+
@"message" : @"requestPermission can not be called "
|
|
260
|
+
@"in App Extensions"
|
|
261
|
+
} mutableCopy]];
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
UNAuthorizationOptions options = UNAuthorizationOptionNone;
|
|
266
|
+
|
|
267
|
+
if (permissions.alert().has_value() && permissions.alert().value()) {
|
|
268
|
+
options |= UNAuthorizationOptionAlert;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (permissions.announcement().has_value() && permissions.announcement().value()) {
|
|
272
|
+
options |= UNAuthorizationOptionAnnouncement;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (permissions.badge().has_value() && permissions.badge().value()) {
|
|
276
|
+
options |= UNAuthorizationOptionBadge;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (permissions.sound().has_value() && permissions.sound().value()) {
|
|
280
|
+
options |= UNAuthorizationOptionSound;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (permissions.criticalAlert().has_value() && permissions.criticalAlert().value()) {
|
|
284
|
+
options |= UNAuthorizationOptionCriticalAlert;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (permissions.provisional().has_value() && permissions.provisional().value()) {
|
|
288
|
+
options |= UNAuthorizationOptionProvisional;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (permissions.carPlay().has_value() && permissions.carPlay().value()) {
|
|
292
|
+
options |= UNAuthorizationOptionCarPlay;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (permissions.providesAppNotificationSettings().has_value() &&
|
|
296
|
+
permissions.providesAppNotificationSettings().value()) {
|
|
297
|
+
options |= UNAuthorizationOptionProvidesAppNotificationSettings;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
301
|
+
[center requestAuthorizationWithOptions:options
|
|
302
|
+
completionHandler:^(BOOL granted, NSError *_Nullable error) {
|
|
303
|
+
if (error) {
|
|
304
|
+
[RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
|
|
305
|
+
} else {
|
|
306
|
+
#if TARGET_IPHONE_SIMULATOR && TARGET_CPU_ARM64
|
|
307
|
+
// Intentional: do not call UIKit registerForRemoteNotifications on
|
|
308
|
+
// ARM64 Simulator — it can wedge main indefinitely. See
|
|
309
|
+
// registerForRemoteNotifications:reject: for the same policy.
|
|
310
|
+
DLog(@"RNFBMessaging requestPermission - ARM64 Simulator detected, "
|
|
311
|
+
@"skipping UIKit registerForRemoteNotifications.");
|
|
312
|
+
#else
|
|
313
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
314
|
+
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
315
|
+
});
|
|
316
|
+
#endif
|
|
317
|
+
[self hasPermission:resolve reject:reject];
|
|
318
|
+
}
|
|
319
|
+
}];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
- (void)registerForRemoteNotifications:(RCTPromiseResolveBlock)resolve
|
|
323
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
324
|
+
// Schedule the timeout BEFORE any UIKit work. UIKit getters / registerForRemoteNotifications
|
|
325
|
+
// must run on main; if main is already stalled (ARM64 Simulator APNs), scheduling the timer
|
|
326
|
+
// first guarantees the JS promise cannot hang forever. Reject from a global queue so the
|
|
327
|
+
// timer itself does not depend on main. Overlapping calls supersede the prior promise
|
|
328
|
+
// (registration-superseded) and bump a generation so stale timeouts cannot settle a newer call.
|
|
329
|
+
NSUInteger generation =
|
|
330
|
+
[[RNFBMessagingAppDelegate sharedInstance] beginRegisterPromiseResolve:resolve
|
|
331
|
+
andPromiseReject:reject];
|
|
332
|
+
|
|
333
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)),
|
|
334
|
+
dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
|
|
335
|
+
RCTPromiseResolveBlock pendingResolve = nil;
|
|
336
|
+
RCTPromiseRejectBlock pendingReject = nil;
|
|
337
|
+
if (![[RNFBMessagingAppDelegate sharedInstance]
|
|
338
|
+
claimPendingRegisterPromiseGeneration:generation
|
|
339
|
+
resolve:&pendingResolve
|
|
340
|
+
reject:&pendingReject]) {
|
|
341
|
+
DLog(@"RNFBMessaging registerForRemoteNotifications timeout: already settled "
|
|
342
|
+
@"(generation %lu).",
|
|
343
|
+
(unsigned long)generation);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
DLog(@"RNFBMessaging registerForRemoteNotifications timed out; rejecting.");
|
|
347
|
+
if (pendingReject != nil) {
|
|
348
|
+
[RNFBSharedUtils
|
|
349
|
+
rejectPromiseWithUserInfo:pendingReject
|
|
350
|
+
userInfo:[@{
|
|
351
|
+
@"code" : @"registration-timeout",
|
|
352
|
+
@"message" : @"registerDeviceForRemoteMessages "
|
|
353
|
+
@"timed out waiting for APNs "
|
|
354
|
+
@"device registration. The system "
|
|
355
|
+
@"did not respond — possibly "
|
|
356
|
+
@"missing notification permission, "
|
|
357
|
+
@"or the main thread is blocked "
|
|
358
|
+
@"(common on ARM64 Simulator)."
|
|
359
|
+
} mutableCopy]];
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
364
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
365
|
+
#if !TARGET_CPU_ARM64
|
|
366
|
+
// Intel simulator: APNs unsupported — settle immediately after poking UIKit.
|
|
367
|
+
RCTPromiseResolveBlock pendingResolve = nil;
|
|
368
|
+
RCTPromiseRejectBlock pendingReject = nil;
|
|
369
|
+
if ([[RNFBMessagingAppDelegate sharedInstance]
|
|
370
|
+
claimPendingRegisterPromiseGeneration:generation
|
|
371
|
+
resolve:&pendingResolve
|
|
372
|
+
reject:&pendingReject] &&
|
|
373
|
+
pendingResolve != nil) {
|
|
374
|
+
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
375
|
+
pendingResolve(@([RCTConvert BOOL:@(YES)]));
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
378
|
+
#else
|
|
379
|
+
// ARM64 Simulator (intentional product policy): do NOT call UIKit
|
|
380
|
+
// registerForRemoteNotifications. Calling it can wedge the main thread so
|
|
381
|
+
// the JS bridge cannot observe the global-queue registration-timeout reject
|
|
382
|
+
// even though the timer fires. Leave the promise pending; the 10s
|
|
383
|
+
// global-queue timeout rejects with registration-timeout. Use a physical
|
|
384
|
+
// device for real APNs tokens. Documented in docs/messaging and OKF.
|
|
385
|
+
DLog(@"RNFBMessaging registerForRemoteNotifications ARM64 Simulator "
|
|
386
|
+
@"detected — skipping UIKit registerForRemoteNotifications; "
|
|
387
|
+
@"global-queue timeout will reject with registration-timeout.");
|
|
388
|
+
return;
|
|
389
|
+
#endif
|
|
390
|
+
#endif
|
|
391
|
+
if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == YES) {
|
|
392
|
+
DLog(@"RNFBMessaging registerForRemoteNotifications - already registered.");
|
|
393
|
+
RCTPromiseResolveBlock pendingResolve = nil;
|
|
394
|
+
RCTPromiseRejectBlock pendingReject = nil;
|
|
395
|
+
if ([[RNFBMessagingAppDelegate sharedInstance]
|
|
396
|
+
claimPendingRegisterPromiseGeneration:generation
|
|
397
|
+
resolve:&pendingResolve
|
|
398
|
+
reject:&pendingReject] &&
|
|
399
|
+
pendingResolve != nil) {
|
|
400
|
+
pendingResolve(@([RCTConvert BOOL:@(YES)]));
|
|
401
|
+
}
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
- (void)unregisterForRemoteNotifications:(RCTPromiseResolveBlock)resolve
|
|
410
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
411
|
+
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
|
|
412
|
+
resolve(nil);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
- (void)hasPermission:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
416
|
+
[[UNUserNotificationCenter currentNotificationCenter]
|
|
417
|
+
getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) {
|
|
418
|
+
NSNumber *authorizedStatus = @-1;
|
|
419
|
+
if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
|
|
420
|
+
authorizedStatus = @-1;
|
|
421
|
+
} else if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
|
|
422
|
+
authorizedStatus = @0;
|
|
423
|
+
} else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
|
|
424
|
+
authorizedStatus = @1;
|
|
425
|
+
} else if (settings.authorizationStatus == UNAuthorizationStatusProvisional) {
|
|
426
|
+
authorizedStatus = @2;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (@available(iOS 14.0, macCatalyst 14.0, *)) {
|
|
430
|
+
if (settings.authorizationStatus == UNAuthorizationStatusEphemeral) {
|
|
431
|
+
authorizedStatus = @3;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
resolve(authorizedStatus);
|
|
436
|
+
}];
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
- (void)sendMessage:(NSDictionary *)remoteMessageMap
|
|
440
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
441
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
442
|
+
[RNFBSharedUtils rejectPromiseWithUserInfo:reject
|
|
443
|
+
userInfo:[@{
|
|
444
|
+
@"code" : @"unimplemented",
|
|
445
|
+
@"message" : @"sendMessage is only supported on "
|
|
446
|
+
@"Android devices."
|
|
447
|
+
} mutableCopy]];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
- (void)subscribeToTopic:(NSString *)topic
|
|
451
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
452
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
453
|
+
[[FIRMessaging messaging] subscribeToTopic:topic
|
|
454
|
+
completion:^(NSError *error) {
|
|
455
|
+
if (error) {
|
|
456
|
+
[RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
|
|
457
|
+
} else {
|
|
458
|
+
resolve(nil);
|
|
459
|
+
}
|
|
460
|
+
}];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
- (void)unsubscribeFromTopic:(NSString *)topic
|
|
464
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
465
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
466
|
+
[[FIRMessaging messaging] unsubscribeFromTopic:topic
|
|
467
|
+
completion:^(NSError *error) {
|
|
468
|
+
if (error) {
|
|
469
|
+
[RNFBSharedUtils rejectPromiseWithNSError:reject
|
|
470
|
+
error:error];
|
|
471
|
+
} else {
|
|
472
|
+
resolve(nil);
|
|
473
|
+
}
|
|
474
|
+
}];
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
- (void)setDeliveryMetricsExportToBigQuery:(BOOL)enabled
|
|
478
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
479
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
480
|
+
@try {
|
|
481
|
+
_isDeliveryMetricsExportToBigQueryEnabled = enabled;
|
|
482
|
+
} @catch (NSException *exception) {
|
|
483
|
+
return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return resolve([NSNull null]);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
- (void)setNotificationDelegationEnabled:(BOOL)enabled
|
|
490
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
491
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
492
|
+
resolve([NSNull null]);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
- (void)isNotificationDelegationEnabled:(RCTPromiseResolveBlock)resolve
|
|
496
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
497
|
+
resolve(@NO);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
@end
|