@react-native-firebase/app 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 +1547 -0
- package/RNFBApp.podspec +49 -0
- package/android/.editorconfig +10 -0
- package/android/build.gradle +129 -0
- package/android/firebase-json.gradle +73 -0
- package/android/gradle.properties +2 -0
- package/android/lint.xml +5 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +24 -0
- package/android/src/main/java/io/invertase/firebase/app/.gitkeep +0 -0
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +124 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +62 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +91 -0
- package/android/src/main/java/io/invertase/firebase/interfaces/.gitkeep +0 -0
- package/android/src/reactnative/AndroidManifest.xml +2 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +46 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppInitProvider.java +22 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppModule.java +186 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +49 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +35 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +22 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +191 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +53 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +151 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseInitProvider.java +78 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +107 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +93 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +146 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +88 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +440 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/ContextProvider.java +30 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/NativeError.java +32 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/NativeEvent.java +28 -0
- package/android/src/reactnative/java/io/invertase/firebase/utils/ReactNativeFirebaseUtilsModule.java +191 -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/modular.d.ts +1 -1
- package/dist/typescript/commonjs/lib/version.d.ts +1 -1
- package/dist/typescript/module/lib/modular.d.ts +1 -1
- package/dist/typescript/module/lib/version.d.ts +1 -1
- package/firebase-schema.json +149 -0
- package/firebase_json.rb +72 -0
- package/ios/RNFBApp/RCTConvert+FIRApp.h +23 -0
- package/ios/RNFBApp/RCTConvert+FIRApp.m +31 -0
- package/ios/RNFBApp/RCTConvert+FIROptions.h +23 -0
- package/ios/RNFBApp/RCTConvert+FIROptions.m +36 -0
- package/ios/RNFBApp/RNFBAppModule.h +28 -0
- package/ios/RNFBApp/RNFBAppModule.m +305 -0
- package/ios/RNFBApp/RNFBJSON.h +36 -0
- package/ios/RNFBApp/RNFBJSON.m +99 -0
- package/ios/RNFBApp/RNFBMeta.h +30 -0
- package/ios/RNFBApp/RNFBMeta.m +61 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +47 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +74 -0
- package/ios/RNFBApp/RNFBPreferences.h +44 -0
- package/ios/RNFBApp/RNFBPreferences.m +94 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.h +73 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.m +151 -0
- package/ios/RNFBApp/RNFBSharedUtils.h +67 -0
- package/ios/RNFBApp/RNFBSharedUtils.m +285 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +30 -0
- package/ios/RNFBApp/RNFBUtilsModule.m +100 -0
- package/ios/RNFBApp/RNFBVersion.h +20 -0
- package/ios/RNFBApp/RNFBVersion.m +21 -0
- package/ios/RNFBApp.xcodeproj/project.pbxproj +411 -0
- package/ios/RNFBApp.xcodeproj/xcshareddata/IDETemplateMacros.plist +24 -0
- package/ios_config.sh +269 -0
- package/lib/version.ts +1 -1
- package/package.json +4 -11
- package/plugin/build/android/applyPlugin.d.ts +6 -0
- package/plugin/build/android/applyPlugin.js +29 -0
- package/plugin/build/android/buildscriptDependency.d.ts +6 -0
- package/plugin/build/android/buildscriptDependency.js +31 -0
- package/plugin/build/android/constants.d.ts +4 -0
- package/plugin/build/android/constants.js +8 -0
- package/plugin/build/android/copyGoogleServices.d.ts +5 -0
- package/plugin/build/android/copyGoogleServices.js +33 -0
- package/plugin/build/android/index.d.ts +4 -0
- package/plugin/build/android/index.js +9 -0
- package/plugin/build/index.d.ts +3 -0
- package/plugin/build/index.js +21 -0
- package/plugin/build/ios/appDelegate.d.ts +6 -0
- package/plugin/build/ios/appDelegate.js +116 -0
- package/plugin/build/ios/googleServicesPlist.d.ts +7 -0
- package/plugin/build/ios/googleServicesPlist.js +42 -0
- package/plugin/build/ios/index.d.ts +3 -0
- package/plugin/build/ios/index.js +7 -0
- package/plugin/src/android/applyPlugin.ts +30 -0
- package/plugin/src/android/buildscriptDependency.ts +33 -0
- package/plugin/src/android/constants.ts +7 -0
- package/plugin/src/android/copyGoogleServices.ts +36 -0
- package/plugin/src/android/index.ts +5 -0
- package/plugin/src/index.ts +27 -0
- package/plugin/src/ios/appDelegate.ts +140 -0
- package/plugin/src/ios/googleServicesPlist.ts +55 -0
- package/plugin/src/ios/index.ts +4 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/react-native.config.js +19 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,94 @@
|
|
|
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 "RNFBPreferences.h"
|
|
19
|
+
|
|
20
|
+
@interface RNFBPreferences ()
|
|
21
|
+
@property(nonatomic, strong) NSUserDefaults *userDefaults;
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
static NSString *const RNFBDomainIdentifier = @"io.invertase.firebase";
|
|
25
|
+
|
|
26
|
+
@implementation RNFBPreferences
|
|
27
|
+
|
|
28
|
+
static RNFBPreferences *sharedInstance;
|
|
29
|
+
|
|
30
|
+
+ (void)load {
|
|
31
|
+
sharedInstance = [[RNFBPreferences alloc] init];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (instancetype)init {
|
|
35
|
+
self = [super init];
|
|
36
|
+
|
|
37
|
+
if (self) {
|
|
38
|
+
_userDefaults = [[NSUserDefaults alloc] initWithSuiteName:RNFBDomainIdentifier];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return self;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (BOOL)contains:(NSString *)key {
|
|
45
|
+
return [_userDefaults objectForKey:key] != nil;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (BOOL)getBooleanValue:(NSString *)key defaultValue:(BOOL)defaultValue {
|
|
49
|
+
if ([_userDefaults objectForKey:key] == nil) return defaultValue;
|
|
50
|
+
return [_userDefaults boolForKey:key];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (void)setBooleanValue:(NSString *)key boolValue:(BOOL)boolValue {
|
|
54
|
+
[_userDefaults setBool:boolValue forKey:key];
|
|
55
|
+
[_userDefaults synchronize];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (void)setIntegerValue:(NSString *)key integerValue:(NSInteger)integerValue {
|
|
59
|
+
[_userDefaults setInteger:(NSInteger)integerValue forKey:key];
|
|
60
|
+
[_userDefaults synchronize];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (NSInteger)getIntegerValue:(NSString *)key defaultValue:(NSInteger)defaultValue {
|
|
64
|
+
if ([_userDefaults objectForKey:key] == nil) return defaultValue;
|
|
65
|
+
return [_userDefaults integerForKey:key];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
- (NSString *)getStringValue:(NSString *)key defaultValue:(NSString *)defaultValue {
|
|
69
|
+
if ([_userDefaults objectForKey:key] == nil) return defaultValue;
|
|
70
|
+
return [_userDefaults stringForKey:key];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
- (void)setStringValue:(NSString *)key stringValue:(NSString *)stringValue {
|
|
74
|
+
[_userDefaults setValue:stringValue forKey:key];
|
|
75
|
+
[_userDefaults synchronize];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
- (NSDictionary *)getAll {
|
|
79
|
+
return [_userDefaults dictionaryRepresentation];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- (void)clearAll {
|
|
83
|
+
[_userDefaults removePersistentDomainForName:RNFBDomainIdentifier];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
- (void)remove:(NSString *)key {
|
|
87
|
+
[_userDefaults removeObjectForKey:key];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
+ (RNFBPreferences *)shared {
|
|
91
|
+
return sharedInstance;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@end
|
|
@@ -0,0 +1,73 @@
|
|
|
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/RCTEventEmitter.h>
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Listeners for Firebase events and emits them to the JS layer
|
|
23
|
+
*/
|
|
24
|
+
@interface RNFBRCTEventEmitter : NSObject
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The RCTBridge. Assigned by `RNFBAppModule`
|
|
28
|
+
*/
|
|
29
|
+
@property(nonatomic, weak) RCTBridge *bridge;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns the shared instance
|
|
33
|
+
*
|
|
34
|
+
* @returns RNFBRCTEventEmitter.
|
|
35
|
+
*/
|
|
36
|
+
+ (RNFBRCTEventEmitter *)shared;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Invalidate
|
|
40
|
+
*/
|
|
41
|
+
- (void)invalidate;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Add an event listener
|
|
45
|
+
*
|
|
46
|
+
* @param eventName NSString event name.
|
|
47
|
+
*/
|
|
48
|
+
- (void)addListener:(NSString *)eventName;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Removes event listeners
|
|
52
|
+
*/
|
|
53
|
+
- (void)removeListeners:(NSString *)eventName all:(BOOL)all;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Send an event to JS with the specified name and body
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
- (void)sendEventWithName:(NSString *)eventName body:(id)body;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Notify the event emitter that JS has loaded and is ready to receive events.
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
- (void)notifyJsReady:(BOOL)ready;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns a dictionary of all registered events & counts. Mainly for testing.
|
|
69
|
+
*
|
|
70
|
+
* @return NSDictionary
|
|
71
|
+
*/
|
|
72
|
+
- (NSDictionary *)getListenersDictionary;
|
|
73
|
+
@end
|
|
@@ -0,0 +1,151 @@
|
|
|
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 "RNFBRCTEventEmitter.h"
|
|
19
|
+
|
|
20
|
+
@interface RNFBRCTEventEmitter ()
|
|
21
|
+
@property(atomic, assign) BOOL jsReady;
|
|
22
|
+
@property(atomic, assign) NSInteger jsListenerCount;
|
|
23
|
+
@property(nonatomic, strong) NSMutableDictionary *jsListeners;
|
|
24
|
+
@property(nonatomic, strong) NSMutableArray *queuedEvents;
|
|
25
|
+
@property(readonly) BOOL isObserving;
|
|
26
|
+
@end
|
|
27
|
+
|
|
28
|
+
NSString *const RNFBRCTEventNameKey = @"name";
|
|
29
|
+
NSString *const RNFBRCTEventBodyKey = @"body";
|
|
30
|
+
|
|
31
|
+
@implementation RNFBRCTEventEmitter
|
|
32
|
+
|
|
33
|
+
- (void)invalidate {
|
|
34
|
+
self.jsReady = FALSE;
|
|
35
|
+
self.queuedEvents = [NSMutableArray array];
|
|
36
|
+
self.jsListeners = [NSMutableDictionary dictionary];
|
|
37
|
+
self.jsListenerCount = 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
+ (instancetype)shared {
|
|
41
|
+
static dispatch_once_t once;
|
|
42
|
+
static RNFBRCTEventEmitter *sharedInstance;
|
|
43
|
+
dispatch_once(&once, ^{
|
|
44
|
+
sharedInstance = [[RNFBRCTEventEmitter alloc] init];
|
|
45
|
+
});
|
|
46
|
+
return sharedInstance;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (instancetype)init {
|
|
50
|
+
self = [super init];
|
|
51
|
+
|
|
52
|
+
if (self) {
|
|
53
|
+
self.jsReady = FALSE;
|
|
54
|
+
self.queuedEvents = [NSMutableArray array];
|
|
55
|
+
self.jsListeners = [NSMutableDictionary dictionary];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return self;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)notifyJsReady:(BOOL)jsReady {
|
|
62
|
+
@synchronized(self.jsListeners) {
|
|
63
|
+
self.jsReady = jsReady;
|
|
64
|
+
if (jsReady) {
|
|
65
|
+
for (id event in [self.queuedEvents copy]) {
|
|
66
|
+
[self sendEventWithName:event[RNFBRCTEventNameKey] body:event[RNFBRCTEventBodyKey]];
|
|
67
|
+
@synchronized(self.queuedEvents) {
|
|
68
|
+
[self.queuedEvents removeObject:event];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
- (void)sendEventWithName:(NSString *)eventName body:(id)body {
|
|
76
|
+
@synchronized(self.jsListeners) {
|
|
77
|
+
if (self.bridge && self.isObserving && self.jsListeners[eventName] != nil) {
|
|
78
|
+
NSString *prefixedEventName = [@"rnfb_" stringByAppendingString:eventName];
|
|
79
|
+
[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter"
|
|
80
|
+
method:@"emit"
|
|
81
|
+
args:body ? @[ prefixedEventName, body ] : @[ prefixedEventName ]
|
|
82
|
+
completion:NULL];
|
|
83
|
+
} else {
|
|
84
|
+
@synchronized(self.queuedEvents) {
|
|
85
|
+
[self.queuedEvents
|
|
86
|
+
addObject:@{RNFBRCTEventNameKey : eventName, RNFBRCTEventBodyKey : body}];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
- (void)addListener:(NSString *)eventName {
|
|
93
|
+
@synchronized(self.jsListeners) {
|
|
94
|
+
self.jsListenerCount++;
|
|
95
|
+
|
|
96
|
+
if (self.jsListeners[eventName] == nil) {
|
|
97
|
+
self.jsListeners[eventName] = @([@1 integerValue]);
|
|
98
|
+
} else {
|
|
99
|
+
self.jsListeners[eventName] =
|
|
100
|
+
@([self.jsListeners[eventName] integerValue] + [@1 integerValue]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (id event in [self.queuedEvents copy]) {
|
|
104
|
+
if ([event[RNFBRCTEventNameKey] isEqualToString:eventName]) {
|
|
105
|
+
[self sendEventWithName:event[RNFBRCTEventNameKey] body:event[RNFBRCTEventBodyKey]];
|
|
106
|
+
@synchronized(self.queuedEvents) {
|
|
107
|
+
[self.queuedEvents removeObject:event];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
- (void)removeListeners:(NSString *)eventName all:(BOOL)all {
|
|
115
|
+
@synchronized(self.jsListeners) {
|
|
116
|
+
if (self.jsListeners[eventName] != nil) {
|
|
117
|
+
NSInteger listenersForEvent = [self.jsListeners[eventName] integerValue];
|
|
118
|
+
|
|
119
|
+
if (listenersForEvent <= 1 || all) {
|
|
120
|
+
@synchronized(self.jsListeners) {
|
|
121
|
+
[self.jsListeners removeObjectForKey:eventName];
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
@synchronized(self.jsListeners) {
|
|
125
|
+
self.jsListeners[eventName] =
|
|
126
|
+
@([self.jsListeners[eventName] integerValue] - [@1 integerValue]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (all) {
|
|
131
|
+
self.jsListenerCount = self.jsListenerCount - listenersForEvent;
|
|
132
|
+
} else {
|
|
133
|
+
self.jsListenerCount = self.jsListenerCount - [@1 integerValue];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
- (NSDictionary *)getListenersDictionary {
|
|
140
|
+
NSMutableDictionary *listenersDictionary = [NSMutableDictionary new];
|
|
141
|
+
listenersDictionary[@"listeners"] = @(self.jsListenerCount);
|
|
142
|
+
listenersDictionary[@"queued"] = @([self.queuedEvents count]);
|
|
143
|
+
listenersDictionary[@"events"] = [self.jsListeners copy];
|
|
144
|
+
return listenersDictionary;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
- (BOOL)isObserving {
|
|
148
|
+
return self.jsReady && self.jsListenerCount > 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@end
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
#ifndef RNFBSharedUtils_h
|
|
19
|
+
#define RNFBSharedUtils_h
|
|
20
|
+
|
|
21
|
+
#import <FirebaseCore/FirebaseCore.h>
|
|
22
|
+
#import <React/RCTBridgeModule.h>
|
|
23
|
+
|
|
24
|
+
#ifdef DEBUG
|
|
25
|
+
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
|
26
|
+
#else
|
|
27
|
+
#define DLog(...)
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#define ELog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
|
31
|
+
|
|
32
|
+
#pragma mark -
|
|
33
|
+
#pragma mark Constants
|
|
34
|
+
|
|
35
|
+
extern NSString *const DEFAULT_APP_DISPLAY_NAME;
|
|
36
|
+
extern NSString *const DEFAULT_APP_NAME;
|
|
37
|
+
|
|
38
|
+
@interface RNFBSharedUtils : NSObject
|
|
39
|
+
|
|
40
|
+
#pragma mark -
|
|
41
|
+
#pragma mark Methods
|
|
42
|
+
|
|
43
|
+
+ (NSString *)getAppJavaScriptName:(NSString *)appDisplayName;
|
|
44
|
+
|
|
45
|
+
+ (NSDictionary *)firAppToDictionary:(FIRApp *)firApp;
|
|
46
|
+
|
|
47
|
+
+ (void)sendJSEventForApp:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body;
|
|
48
|
+
|
|
49
|
+
+ (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject
|
|
50
|
+
exception:(NSException *)exception;
|
|
51
|
+
|
|
52
|
+
+ (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error;
|
|
53
|
+
|
|
54
|
+
+ (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
|
|
55
|
+
userInfo:(NSMutableDictionary *)userInfo;
|
|
56
|
+
|
|
57
|
+
+ (NSString *)getISO8601String:(NSDate *)date;
|
|
58
|
+
|
|
59
|
+
+ (BOOL)configContains:(NSString *)key;
|
|
60
|
+
|
|
61
|
+
+ (BOOL)getConfigBooleanValue:(NSString *)tag key:(NSString *)key defaultValue:(BOOL)defaultValue;
|
|
62
|
+
|
|
63
|
+
+ (id)decodeNullSentinels:(id)value;
|
|
64
|
+
|
|
65
|
+
@end
|
|
66
|
+
|
|
67
|
+
#endif
|
|
@@ -0,0 +1,285 @@
|
|
|
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 "RNFBSharedUtils.h"
|
|
19
|
+
#import "RNFBAppModule.h"
|
|
20
|
+
#import "RNFBJSON.h"
|
|
21
|
+
#import "RNFBMeta.h"
|
|
22
|
+
#import "RNFBPreferences.h"
|
|
23
|
+
#import "RNFBRCTEventEmitter.h"
|
|
24
|
+
|
|
25
|
+
#pragma mark -
|
|
26
|
+
#pragma mark Constants
|
|
27
|
+
|
|
28
|
+
NSString *const DEFAULT_APP_DISPLAY_NAME = @"[DEFAULT]";
|
|
29
|
+
NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
|
|
30
|
+
|
|
31
|
+
@implementation RNFBSharedUtils
|
|
32
|
+
static NSString *const RNFBErrorDomain = @"RNFBErrorDomain";
|
|
33
|
+
|
|
34
|
+
#pragma mark -
|
|
35
|
+
#pragma mark Methods
|
|
36
|
+
|
|
37
|
+
+ (NSString *)getAppJavaScriptName:(NSString *)appDisplayName {
|
|
38
|
+
if ([appDisplayName isEqualToString:DEFAULT_APP_NAME]) {
|
|
39
|
+
return DEFAULT_APP_DISPLAY_NAME;
|
|
40
|
+
}
|
|
41
|
+
return appDisplayName;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
+ (NSDictionary *)firAppToDictionary:(FIRApp *)firApp {
|
|
45
|
+
FIROptions *firOptions = [firApp options];
|
|
46
|
+
NSMutableDictionary *firAppDictionary = [NSMutableDictionary new];
|
|
47
|
+
NSMutableDictionary *firAppOptions = [NSMutableDictionary new];
|
|
48
|
+
NSMutableDictionary *firAppConfig = [NSMutableDictionary new];
|
|
49
|
+
|
|
50
|
+
NSString *name = [firApp name];
|
|
51
|
+
if ([name isEqualToString:DEFAULT_APP_NAME]) {
|
|
52
|
+
name = DEFAULT_APP_DISPLAY_NAME;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
firAppConfig[@"name"] = name;
|
|
56
|
+
firAppConfig[@"automaticDataCollectionEnabled"] = @([firApp isDataCollectionDefaultEnabled]);
|
|
57
|
+
|
|
58
|
+
firAppOptions[@"apiKey"] = firOptions.APIKey;
|
|
59
|
+
firAppOptions[@"appId"] = firOptions.googleAppID;
|
|
60
|
+
firAppOptions[@"projectId"] = firOptions.projectID;
|
|
61
|
+
firAppOptions[@"databaseURL"] = firOptions.databaseURL;
|
|
62
|
+
firAppOptions[@"storageBucket"] = firOptions.storageBucket;
|
|
63
|
+
firAppOptions[@"messagingSenderId"] = firOptions.GCMSenderID;
|
|
64
|
+
// missing from android sdk - ios only:
|
|
65
|
+
firAppOptions[@"clientId"] = firOptions.clientID;
|
|
66
|
+
// not in FIROptions API but in JS SDK and project config JSON
|
|
67
|
+
if ([RNFBAppModule getCustomDomain:name] != nil) {
|
|
68
|
+
firAppOptions[@"authDomain"] = [RNFBAppModule getCustomDomain:name];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
firAppDictionary[@"options"] = firAppOptions;
|
|
72
|
+
firAppDictionary[@"appConfig"] = firAppConfig;
|
|
73
|
+
|
|
74
|
+
return firAppDictionary;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
+ (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject
|
|
78
|
+
exception:(NSException *)exception {
|
|
79
|
+
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
|
80
|
+
|
|
81
|
+
[userInfo setValue:@(YES) forKey:@"fatal"];
|
|
82
|
+
[userInfo setValue:@"unknown" forKey:@"code"];
|
|
83
|
+
[userInfo setValue:exception.reason forKey:@"message"];
|
|
84
|
+
[userInfo setValue:exception.name forKey:@"nativeErrorCode"];
|
|
85
|
+
[userInfo setValue:exception.reason forKey:@"nativeErrorMessage"];
|
|
86
|
+
|
|
87
|
+
NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
|
|
88
|
+
|
|
89
|
+
reject(exception.name, exception.reason, error);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
+ (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error {
|
|
93
|
+
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
|
94
|
+
|
|
95
|
+
[userInfo setValue:@(NO) forKey:@"fatal"];
|
|
96
|
+
[userInfo setValue:@"unknown" forKey:@"code"];
|
|
97
|
+
[userInfo setValue:error.localizedDescription forKey:@"message"];
|
|
98
|
+
[userInfo setValue:@(error.code) forKey:@"nativeErrorCode"];
|
|
99
|
+
[userInfo setValue:error.localizedDescription forKey:@"nativeErrorMessage"];
|
|
100
|
+
|
|
101
|
+
NSError *newErrorWithUserInfo = [NSError errorWithDomain:RNFBErrorDomain
|
|
102
|
+
code:666
|
|
103
|
+
userInfo:userInfo];
|
|
104
|
+
reject(@"unknown", error.localizedDescription, newErrorWithUserInfo);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
+ (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
|
|
108
|
+
userInfo:(NSMutableDictionary *)userInfo {
|
|
109
|
+
NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
|
|
110
|
+
reject(userInfo[@"code"], userInfo[@"message"], error);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// for easier v5 migration
|
|
114
|
+
+ (void)sendJSEventForApp:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body {
|
|
115
|
+
NSMutableDictionary *newBody = [body mutableCopy];
|
|
116
|
+
newBody[@"appName"] = [self getAppJavaScriptName:app.name];
|
|
117
|
+
[[RNFBRCTEventEmitter shared] sendEventWithName:name body:newBody];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
+ (NSString *)getISO8601String:(NSDate *)date {
|
|
121
|
+
static NSDateFormatter *formatter = nil;
|
|
122
|
+
|
|
123
|
+
if (!formatter) {
|
|
124
|
+
formatter = [[NSDateFormatter alloc] init];
|
|
125
|
+
[formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
|
|
126
|
+
formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
|
|
127
|
+
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
NSString *iso8601String = [formatter stringFromDate:date];
|
|
131
|
+
|
|
132
|
+
return [iso8601String stringByAppendingString:@"Z"];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
+ (BOOL)configContains:(NSString *)key {
|
|
136
|
+
return [[RNFBPreferences shared] contains:key] || [[RNFBJSON shared] contains:key] ||
|
|
137
|
+
[RNFBMeta contains:key];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
+ (BOOL)getConfigBooleanValue:(NSString *)tag key:(NSString *)key defaultValue:(BOOL)defaultValue {
|
|
141
|
+
BOOL enabled;
|
|
142
|
+
|
|
143
|
+
if ([[RNFBPreferences shared] contains:key]) {
|
|
144
|
+
enabled = [[RNFBPreferences shared] getBooleanValue:key defaultValue:defaultValue];
|
|
145
|
+
DLog(@"%@ %@ via "
|
|
146
|
+
@"RNFBPreferences: %d",
|
|
147
|
+
tag, key, enabled);
|
|
148
|
+
} else if ([[RNFBJSON shared] contains:key]) {
|
|
149
|
+
enabled = [[RNFBJSON shared] getBooleanValue:key defaultValue:defaultValue];
|
|
150
|
+
DLog(@"%@ %@ via "
|
|
151
|
+
@"RNFBJSON: %d",
|
|
152
|
+
tag, key, enabled);
|
|
153
|
+
} else {
|
|
154
|
+
// Note that if we're here, and the key is not set on the app's bundle, our final default is the
|
|
155
|
+
// one passed in
|
|
156
|
+
enabled = [RNFBMeta getBooleanValue:key defaultValue:defaultValue];
|
|
157
|
+
DLog(@"%@ %@ via "
|
|
158
|
+
@"RNFBMeta: %d",
|
|
159
|
+
tag, key, enabled);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
DLog(@"%@ %@ final value: %d", tag, key, enabled);
|
|
163
|
+
|
|
164
|
+
return enabled;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Decodes null sentinel objects back to NSNull values.
|
|
169
|
+
* Uses iterative stack-based traversal to avoid stack overflow on deeply nested structures.
|
|
170
|
+
*
|
|
171
|
+
* This reverses the encoding done on the JavaScript side where null values in object
|
|
172
|
+
* properties are replaced with {__rnfbNull: true} sentinel objects to survive iOS
|
|
173
|
+
* TurboModule serialization.
|
|
174
|
+
*
|
|
175
|
+
* Process:
|
|
176
|
+
* 1. Detects sentinel objects: dictionaries with single key "__rnfbNull" set to true
|
|
177
|
+
* 2. Replaces sentinels with NSNull in object properties and arrays
|
|
178
|
+
* 3. Preserves regular NSNull values that were in arrays (never encoded as sentinels)
|
|
179
|
+
* 4. Deep processes all nested objects and arrays using a stack-based iteration
|
|
180
|
+
*
|
|
181
|
+
* @param value - The value to decode (dictionary, array, or primitive)
|
|
182
|
+
* @return The decoded value with sentinels replaced by NSNull
|
|
183
|
+
*/
|
|
184
|
+
+ (id)decodeNullSentinels:(id)value {
|
|
185
|
+
// Non-container values are returned as-is
|
|
186
|
+
if (![value isKindOfClass:[NSDictionary class]] && ![value isKindOfClass:[NSArray class]]) {
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Helper to detect the sentinel
|
|
191
|
+
BOOL (^isNullSentinel)(NSDictionary *) = ^BOOL(NSDictionary *dict) {
|
|
192
|
+
id flag = dict[@"__rnfbNull"];
|
|
193
|
+
return (dict.count == 1 && flag != nil && [flag boolValue]);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Helper to process a child element and add it to the parent container
|
|
197
|
+
void (^processChild)(id, id, id, BOOL, NSMutableArray *) =
|
|
198
|
+
^void(id child, id parentMutable, id keyOrNil, BOOL isParentDict, NSMutableArray *stack) {
|
|
199
|
+
id processedValue = nil;
|
|
200
|
+
|
|
201
|
+
if ([child isKindOfClass:[NSDictionary class]]) {
|
|
202
|
+
NSDictionary *childDict = (NSDictionary *)child;
|
|
203
|
+
|
|
204
|
+
if (isNullSentinel(childDict)) {
|
|
205
|
+
// Replace sentinel with NSNull
|
|
206
|
+
processedValue = [NSNull null];
|
|
207
|
+
} else {
|
|
208
|
+
// Process nested dictionary
|
|
209
|
+
NSMutableDictionary *childMut =
|
|
210
|
+
[NSMutableDictionary dictionaryWithCapacity:childDict.count];
|
|
211
|
+
processedValue = childMut;
|
|
212
|
+
[stack addObject:@{@"original" : childDict, @"mutable" : childMut}];
|
|
213
|
+
}
|
|
214
|
+
} else if ([child isKindOfClass:[NSArray class]]) {
|
|
215
|
+
// Process nested array
|
|
216
|
+
NSArray *childArray = (NSArray *)child;
|
|
217
|
+
NSMutableArray *childMut = [NSMutableArray arrayWithCapacity:childArray.count];
|
|
218
|
+
processedValue = childMut;
|
|
219
|
+
[stack addObject:@{@"original" : childArray, @"mutable" : childMut}];
|
|
220
|
+
} else {
|
|
221
|
+
// Preserve primitive values
|
|
222
|
+
processedValue = child ?: [NSNull null];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Add to parent container based on type
|
|
226
|
+
if (isParentDict) {
|
|
227
|
+
NSMutableDictionary *mutDict = (NSMutableDictionary *)parentMutable;
|
|
228
|
+
if (processedValue) {
|
|
229
|
+
mutDict[keyOrNil] = processedValue;
|
|
230
|
+
}
|
|
231
|
+
// NSDictionary can't store nil, and original code wouldn't see nil values either.
|
|
232
|
+
} else {
|
|
233
|
+
NSMutableArray *mutArray = (NSMutableArray *)parentMutable;
|
|
234
|
+
[mutArray addObject:processedValue];
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Root-level sentinel case
|
|
239
|
+
if ([value isKindOfClass:[NSDictionary class]] && isNullSentinel((NSDictionary *)value)) {
|
|
240
|
+
return [NSNull null];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
id rootOriginal = value;
|
|
244
|
+
id rootMutable = nil;
|
|
245
|
+
|
|
246
|
+
if ([value isKindOfClass:[NSDictionary class]]) {
|
|
247
|
+
NSDictionary *dict = (NSDictionary *)value;
|
|
248
|
+
rootMutable = [NSMutableDictionary dictionaryWithCapacity:dict.count];
|
|
249
|
+
} else {
|
|
250
|
+
NSArray *array = (NSArray *)value;
|
|
251
|
+
rootMutable = [NSMutableArray arrayWithCapacity:array.count];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Stack-based iteration to process nested structures without recursion
|
|
255
|
+
// Stack frames: { @"original": container, @"mutable": mutableContainer }
|
|
256
|
+
NSMutableArray<NSDictionary *> *stack = [NSMutableArray array];
|
|
257
|
+
[stack addObject:@{@"original" : rootOriginal, @"mutable" : rootMutable}];
|
|
258
|
+
|
|
259
|
+
while (stack.count > 0) {
|
|
260
|
+
NSDictionary *frame = [stack lastObject];
|
|
261
|
+
[stack removeLastObject];
|
|
262
|
+
|
|
263
|
+
id original = frame[@"original"];
|
|
264
|
+
id mutable = frame[@"mutable"];
|
|
265
|
+
|
|
266
|
+
if ([original isKindOfClass:[NSDictionary class]]) {
|
|
267
|
+
NSDictionary *origDict = (NSDictionary *)original;
|
|
268
|
+
|
|
269
|
+
for (id key in origDict) {
|
|
270
|
+
id child = origDict[key];
|
|
271
|
+
processChild(child, mutable, key, YES, stack);
|
|
272
|
+
}
|
|
273
|
+
} else if ([original isKindOfClass:[NSArray class]]) {
|
|
274
|
+
NSArray *origArray = (NSArray *)original;
|
|
275
|
+
|
|
276
|
+
for (id child in origArray) {
|
|
277
|
+
processChild(child, mutable, nil, NO, stack);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return rootMutable;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
@end
|
|
@@ -0,0 +1,30 @@
|
|
|
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 <Photos/Photos.h>
|
|
20
|
+
|
|
21
|
+
#import <React/RCTBridgeModule.h>
|
|
22
|
+
|
|
23
|
+
@interface RNFBUtilsModule : NSObject <RCTBridgeModule>
|
|
24
|
+
|
|
25
|
+
+ (BOOL)isRemoteAsset:(NSString *)localFilePath;
|
|
26
|
+
+ (BOOL)unused_isHeic:(NSString *)localFilePath;
|
|
27
|
+
+ (NSString *)valueForKey:(NSString *)key fromQueryItems:(NSArray *)queryItems;
|
|
28
|
+
+ (PHAsset *)fetchAssetForPath:(NSString *)localFilePath;
|
|
29
|
+
|
|
30
|
+
@end
|