@react-native-firebase/app 26.4.0 → 27.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 +48 -0
- package/README.md +10 -27
- package/RNFBApp.podspec +13 -5
- package/android/build.gradle +3 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
- package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
- package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
- package/dist/module/FirebaseApp.js +10 -0
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/deeps.js +3 -0
- package/dist/module/common/deeps.js.map +1 -1
- package/dist/module/internal/FirebaseModule.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/SharedEventEmitter.js +3 -1
- package/dist/module/internal/SharedEventEmitter.js.map +1 -1
- package/dist/module/internal/index.js +1 -0
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/registry/app.js +7 -1
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +2 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
- package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
- package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -0
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +10 -3
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +12 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +4 -0
- package/firebase_spm.rb +552 -96
- package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
- package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
- package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
- package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
- package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
- package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
- package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
- package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
- package/ios/RNFBApp/RNFBAppModule.h +6 -2
- package/ios/RNFBApp/RNFBAppModule.mm +65 -228
- package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
- package/ios/RNFBApp/RNFBHandleMap.m +27 -56
- package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
- package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
- package/ios/RNFBApp/RNFBJSON.m +22 -38
- package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
- package/ios/RNFBApp/RNFBMeta.m +24 -26
- package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
- package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
- package/ios/RNFBApp/RNFBPreferences.m +22 -20
- package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
- package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
- package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
- package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
- package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
- package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
- package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
- package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
- package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
- package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
- package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
- package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
- package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
- package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
- package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
- package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
- package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
- package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
- package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
- package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
- package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
- package/ios/RNFBFirebase/Package.swift +53 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
- package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
- package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
- package/ios_config.sh +50 -22
- package/lib/FirebaseApp.ts +10 -0
- package/lib/common/deeps.ts +3 -0
- package/lib/internal/FirebaseModule.ts +6 -3
- package/lib/internal/NativeModules.ts +4 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
- package/lib/internal/SharedEventEmitter.ts +5 -1
- package/lib/internal/index.ts +1 -0
- package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
- package/lib/internal/registry/app.ts +7 -1
- package/lib/types/app.ts +10 -3
- package/lib/types/internal.ts +19 -0
- package/lib/version.ts +1 -1
- package/package.json +8 -8
- package/plugin/build/ios/appDelegate.js +2 -2
- package/plugin/build/ios/podfile.js +16 -16
- package/plugin/build/pluginConfig.d.ts +4 -2
- package/plugin/src/ios/appDelegate.ts +2 -2
- package/plugin/src/ios/podfile.ts +20 -23
- package/plugin/src/pluginConfig.ts +4 -2
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import Foundation
|
|
18
|
+
|
|
19
|
+
/// Bridge-present check previously hard-wired to `self.bridge != nil`.
|
|
20
|
+
public typealias RNFBRCTEventEmitterBridgePresent = () -> Bool
|
|
21
|
+
|
|
22
|
+
/// Bridge emit previously hard-wired to `enqueueJSCall` (unprefixed event name + body).
|
|
23
|
+
public typealias RNFBRCTEventEmitterEmitHandler = (String, Any?) -> Void
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Queue / listener state previously inline in `RNFBRCTEventEmitter.m`.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors pre-port:
|
|
29
|
+
* - `isObserving` = `jsReady && jsListenerCount > 0`
|
|
30
|
+
* - emit when bridge present && observing && listener registered; else queue `{name,body}`
|
|
31
|
+
* - `notifyJsReady(true)` / `addListener` flush matching queued events via `sendEvent`
|
|
32
|
+
* - `@synchronized(jsListeners)` / `@synchronized(queuedEvents)` via `objc_sync_*`
|
|
33
|
+
*/
|
|
34
|
+
@objc(RNFBRCTEventEmitterCore)
|
|
35
|
+
public final class RNFBRCTEventEmitterCore: NSObject {
|
|
36
|
+
@objc public static let eventNameKey = "name"
|
|
37
|
+
@objc public static let eventBodyKey = "body"
|
|
38
|
+
|
|
39
|
+
private var jsReady = false
|
|
40
|
+
private var jsListenerCount = 0
|
|
41
|
+
private var jsListeners = NSMutableDictionary()
|
|
42
|
+
private var queuedEvents = NSMutableArray()
|
|
43
|
+
|
|
44
|
+
private let isBridgePresent: RNFBRCTEventEmitterBridgePresent
|
|
45
|
+
private let emitHandler: RNFBRCTEventEmitterEmitHandler
|
|
46
|
+
|
|
47
|
+
@objc(initWithIsBridgePresent:emitHandler:)
|
|
48
|
+
public init(
|
|
49
|
+
isBridgePresent: @escaping RNFBRCTEventEmitterBridgePresent,
|
|
50
|
+
emitHandler: @escaping RNFBRCTEventEmitterEmitHandler
|
|
51
|
+
) {
|
|
52
|
+
self.isBridgePresent = isBridgePresent
|
|
53
|
+
self.emitHandler = emitHandler
|
|
54
|
+
super.init()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@objc public func invalidate() {
|
|
58
|
+
jsReady = false
|
|
59
|
+
queuedEvents = NSMutableArray()
|
|
60
|
+
jsListeners = NSMutableDictionary()
|
|
61
|
+
jsListenerCount = 0
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc(notifyJsReady:)
|
|
65
|
+
public func notifyJsReady(_ ready: Bool) {
|
|
66
|
+
objc_sync_enter(jsListeners)
|
|
67
|
+
defer { objc_sync_exit(jsListeners) }
|
|
68
|
+
|
|
69
|
+
jsReady = ready
|
|
70
|
+
if ready {
|
|
71
|
+
for case let event as NSDictionary in queuedEvents.copy() as! NSArray {
|
|
72
|
+
let name = event[Self.eventNameKey] as! String
|
|
73
|
+
let body = event[Self.eventBodyKey]
|
|
74
|
+
sendEvent(name: name, body: body)
|
|
75
|
+
objc_sync_enter(queuedEvents)
|
|
76
|
+
queuedEvents.remove(event)
|
|
77
|
+
objc_sync_exit(queuedEvents)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@objc(sendEventWithName:body:)
|
|
83
|
+
public func sendEvent(name eventName: String, body: Any?) {
|
|
84
|
+
objc_sync_enter(jsListeners)
|
|
85
|
+
defer { objc_sync_exit(jsListeners) }
|
|
86
|
+
|
|
87
|
+
if isBridgePresent(), isObserving, jsListeners[eventName] != nil {
|
|
88
|
+
emitHandler(eventName, body)
|
|
89
|
+
} else {
|
|
90
|
+
objc_sync_enter(queuedEvents)
|
|
91
|
+
let entry = NSMutableDictionary()
|
|
92
|
+
entry[Self.eventNameKey] = eventName
|
|
93
|
+
entry[Self.eventBodyKey] = body
|
|
94
|
+
queuedEvents.add(entry)
|
|
95
|
+
objc_sync_exit(queuedEvents)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc(addListener:)
|
|
100
|
+
public func addListener(_ eventName: String) {
|
|
101
|
+
objc_sync_enter(jsListeners)
|
|
102
|
+
defer { objc_sync_exit(jsListeners) }
|
|
103
|
+
|
|
104
|
+
jsListenerCount += 1
|
|
105
|
+
|
|
106
|
+
if jsListeners[eventName] == nil {
|
|
107
|
+
jsListeners[eventName] = NSNumber(value: 1)
|
|
108
|
+
} else {
|
|
109
|
+
let current = (jsListeners[eventName] as! NSNumber).intValue
|
|
110
|
+
jsListeners[eventName] = NSNumber(value: current + 1)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for case let event as NSDictionary in queuedEvents.copy() as! NSArray {
|
|
114
|
+
if (event[Self.eventNameKey] as? String) == eventName {
|
|
115
|
+
let body = event[Self.eventBodyKey]
|
|
116
|
+
sendEvent(name: eventName, body: body)
|
|
117
|
+
objc_sync_enter(queuedEvents)
|
|
118
|
+
queuedEvents.remove(event)
|
|
119
|
+
objc_sync_exit(queuedEvents)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@objc(removeListeners:all:)
|
|
125
|
+
public func removeListeners(_ eventName: String, all: Bool) {
|
|
126
|
+
objc_sync_enter(jsListeners)
|
|
127
|
+
defer { objc_sync_exit(jsListeners) }
|
|
128
|
+
|
|
129
|
+
if jsListeners[eventName] != nil {
|
|
130
|
+
let listenersForEvent = (jsListeners[eventName] as! NSNumber).intValue
|
|
131
|
+
|
|
132
|
+
if listenersForEvent <= 1 || all {
|
|
133
|
+
objc_sync_enter(jsListeners)
|
|
134
|
+
jsListeners.removeObject(forKey: eventName)
|
|
135
|
+
objc_sync_exit(jsListeners)
|
|
136
|
+
} else {
|
|
137
|
+
objc_sync_enter(jsListeners)
|
|
138
|
+
jsListeners[eventName] = NSNumber(value: listenersForEvent - 1)
|
|
139
|
+
objc_sync_exit(jsListeners)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if all {
|
|
143
|
+
jsListenerCount -= listenersForEvent
|
|
144
|
+
} else {
|
|
145
|
+
jsListenerCount -= 1
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@objc public func getListenersDictionary() -> NSDictionary {
|
|
151
|
+
let listenersDictionary = NSMutableDictionary()
|
|
152
|
+
listenersDictionary["listeners"] = NSNumber(value: jsListenerCount)
|
|
153
|
+
listenersDictionary["queued"] = NSNumber(value: queuedEvents.count)
|
|
154
|
+
listenersDictionary["events"] = jsListeners.copy()
|
|
155
|
+
return listenersDictionary
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private var isObserving: Bool {
|
|
159
|
+
jsReady && jsListenerCount > 0
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -18,13 +18,10 @@
|
|
|
18
18
|
#ifndef RNFBSharedUtils_h
|
|
19
19
|
#define RNFBSharedUtils_h
|
|
20
20
|
|
|
21
|
-
#if __has_include(<FirebaseCore/FirebaseCore.h>)
|
|
22
|
-
#import <FirebaseCore/FirebaseCore.h>
|
|
23
|
-
#else
|
|
24
|
-
@import FirebaseCore;
|
|
25
|
-
#endif
|
|
26
21
|
#import <React/RCTBridgeModule.h>
|
|
27
22
|
|
|
23
|
+
@class FIRApp;
|
|
24
|
+
|
|
28
25
|
#ifdef DEBUG
|
|
29
26
|
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
|
30
27
|
#else
|
|
@@ -22,146 +22,154 @@
|
|
|
22
22
|
#import "RNFBPreferences.h"
|
|
23
23
|
#import "RNFBRCTEventEmitter.h"
|
|
24
24
|
|
|
25
|
+
#if __has_include(<RNFBApp/RNFBApp-Swift.h>)
|
|
26
|
+
#import <RNFBApp/RNFBApp-Swift.h>
|
|
27
|
+
#elif __has_include("RNFBApp-Swift.h")
|
|
28
|
+
#import "RNFBApp-Swift.h"
|
|
29
|
+
#elif __has_include("RNFBHandleMapStorage-Swift.inc")
|
|
30
|
+
#import "RNFBHandleMapStorage-Swift.inc"
|
|
31
|
+
#else
|
|
32
|
+
#error "RNFBApp Swift interface not found"
|
|
33
|
+
#endif
|
|
34
|
+
|
|
25
35
|
#pragma mark -
|
|
26
36
|
#pragma mark Constants
|
|
27
37
|
|
|
28
38
|
NSString *const DEFAULT_APP_DISPLAY_NAME = @"[DEFAULT]";
|
|
29
39
|
NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
|
|
30
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Adapts `RNFBMeta` class methods to the instance-based config source protocol used by
|
|
43
|
+
* `RNFBSharedUtilsConfig`.
|
|
44
|
+
*/
|
|
45
|
+
@interface RNFBConfigMetaSource : NSObject <RNFBConfigBooleanProviding>
|
|
46
|
+
@end
|
|
47
|
+
|
|
48
|
+
@implementation RNFBConfigMetaSource
|
|
49
|
+
|
|
50
|
+
- (BOOL)contains:(NSString *)key {
|
|
51
|
+
return [RNFBMeta contains:key];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (BOOL)getBooleanValue:(NSString *)key defaultValue:(BOOL)defaultValue {
|
|
55
|
+
return [RNFBMeta getBooleanValue:key defaultValue:defaultValue];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@end
|
|
59
|
+
|
|
60
|
+
static id<RNFBConfigBooleanProviding> RNFBSharedUtilsMetaConfigSource(void) {
|
|
61
|
+
static RNFBConfigMetaSource *sharedSource;
|
|
62
|
+
static dispatch_once_t onceToken;
|
|
63
|
+
dispatch_once(&onceToken, ^{
|
|
64
|
+
sharedSource = [[RNFBConfigMetaSource alloc] init];
|
|
65
|
+
});
|
|
66
|
+
return sharedSource;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Adapts `RNFBAppModule getCustomDomain:` for `RNFBSharedUtilsFIRApp`.
|
|
71
|
+
*/
|
|
72
|
+
@interface RNFBCustomDomainProvider : NSObject <RNFBCustomDomainProviding>
|
|
73
|
+
@end
|
|
74
|
+
|
|
75
|
+
@implementation RNFBCustomDomainProvider
|
|
76
|
+
|
|
77
|
+
- (NSString *)getCustomDomain:(NSString *)appName {
|
|
78
|
+
return [RNFBAppModule getCustomDomain:appName];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@end
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Adapts `RNFBRCTEventEmitter.shared` for `RNFBSharedUtilsFIRApp`.
|
|
85
|
+
*/
|
|
86
|
+
@interface RNFBJSEventSender : NSObject <RNFBJSEventSending>
|
|
87
|
+
@end
|
|
88
|
+
|
|
89
|
+
@implementation RNFBJSEventSender
|
|
90
|
+
|
|
91
|
+
- (void)sendEventWithName:(NSString *)name body:(id)body {
|
|
92
|
+
[[RNFBRCTEventEmitter shared] sendEventWithName:name body:body];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@end
|
|
96
|
+
|
|
97
|
+
static id<RNFBCustomDomainProviding> RNFBSharedUtilsCustomDomainProvider(void) {
|
|
98
|
+
static RNFBCustomDomainProvider *sharedProvider;
|
|
99
|
+
static dispatch_once_t onceToken;
|
|
100
|
+
dispatch_once(&onceToken, ^{
|
|
101
|
+
sharedProvider = [[RNFBCustomDomainProvider alloc] init];
|
|
102
|
+
});
|
|
103
|
+
return sharedProvider;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static id<RNFBJSEventSending> RNFBSharedUtilsJSEventSender(void) {
|
|
107
|
+
static RNFBJSEventSender *sharedSender;
|
|
108
|
+
static dispatch_once_t onceToken;
|
|
109
|
+
dispatch_once(&onceToken, ^{
|
|
110
|
+
sharedSender = [[RNFBJSEventSender alloc] init];
|
|
111
|
+
});
|
|
112
|
+
return sharedSender;
|
|
113
|
+
}
|
|
114
|
+
|
|
31
115
|
@implementation RNFBSharedUtils
|
|
32
|
-
static NSString *const RNFBErrorDomain = @"RNFBErrorDomain";
|
|
33
116
|
|
|
34
117
|
#pragma mark -
|
|
35
118
|
#pragma mark Methods
|
|
36
119
|
|
|
37
120
|
+ (NSString *)getAppJavaScriptName:(NSString *)appDisplayName {
|
|
38
|
-
|
|
39
|
-
return DEFAULT_APP_DISPLAY_NAME;
|
|
40
|
-
}
|
|
41
|
-
return appDisplayName;
|
|
121
|
+
return [RNFBSharedUtilsFormatting getAppJavaScriptName:appDisplayName];
|
|
42
122
|
}
|
|
43
123
|
|
|
44
124
|
+ (NSDictionary *)firAppToDictionary:(FIRApp *)firApp {
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
NSString *customAuthDomain = [RNFBAppModule getCustomDomain:name];
|
|
68
|
-
if (customAuthDomain != nil) {
|
|
69
|
-
firAppOptions[@"authDomain"] = customAuthDomain;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
firAppDictionary[@"options"] = firAppOptions;
|
|
73
|
-
firAppDictionary[@"appConfig"] = firAppConfig;
|
|
74
|
-
|
|
75
|
-
return firAppDictionary;
|
|
125
|
+
return [RNFBSharedUtilsFIRApp firAppToDictionaryFromFIRApp:firApp
|
|
126
|
+
customDomainProvider:RNFBSharedUtilsCustomDomainProvider()];
|
|
76
127
|
}
|
|
77
128
|
|
|
78
129
|
+ (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject
|
|
79
130
|
exception:(NSException *)exception {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
[userInfo setValue:@(YES) forKey:@"fatal"];
|
|
83
|
-
[userInfo setValue:@"unknown" forKey:@"code"];
|
|
84
|
-
[userInfo setValue:exception.reason forKey:@"message"];
|
|
85
|
-
[userInfo setValue:exception.name forKey:@"nativeErrorCode"];
|
|
86
|
-
[userInfo setValue:exception.reason forKey:@"nativeErrorMessage"];
|
|
87
|
-
|
|
88
|
-
NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
|
|
89
|
-
|
|
90
|
-
reject(exception.name, exception.reason, error);
|
|
131
|
+
[RNFBSharedUtilsPromiseRejection rejectPromiseWithException:reject exception:exception];
|
|
91
132
|
}
|
|
92
133
|
|
|
93
134
|
+ (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
[userInfo setValue:@(NO) forKey:@"fatal"];
|
|
97
|
-
[userInfo setValue:@"unknown" forKey:@"code"];
|
|
98
|
-
[userInfo setValue:error.localizedDescription forKey:@"message"];
|
|
99
|
-
[userInfo setValue:@(error.code) forKey:@"nativeErrorCode"];
|
|
100
|
-
[userInfo setValue:error.localizedDescription forKey:@"nativeErrorMessage"];
|
|
101
|
-
|
|
102
|
-
NSError *newErrorWithUserInfo = [NSError errorWithDomain:RNFBErrorDomain
|
|
103
|
-
code:666
|
|
104
|
-
userInfo:userInfo];
|
|
105
|
-
reject(@"unknown", error.localizedDescription, newErrorWithUserInfo);
|
|
135
|
+
[RNFBSharedUtilsPromiseRejection rejectPromiseWithNSError:reject error:error];
|
|
106
136
|
}
|
|
107
137
|
|
|
108
138
|
+ (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
|
|
109
139
|
userInfo:(NSMutableDictionary *)userInfo {
|
|
110
|
-
|
|
111
|
-
reject(userInfo[@"code"], userInfo[@"message"], error);
|
|
140
|
+
[RNFBSharedUtilsPromiseRejection rejectPromiseWithUserInfo:reject userInfo:userInfo];
|
|
112
141
|
}
|
|
113
142
|
|
|
114
143
|
// for easier v5 migration
|
|
115
144
|
+ (void)sendJSEventForApp:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
145
|
+
[RNFBSharedUtilsFIRApp sendJSEventForFIRApp:app
|
|
146
|
+
name:name
|
|
147
|
+
body:body
|
|
148
|
+
eventSender:RNFBSharedUtilsJSEventSender()];
|
|
119
149
|
}
|
|
120
150
|
|
|
121
151
|
+ (NSString *)getISO8601String:(NSDate *)date {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!formatter) {
|
|
125
|
-
formatter = [[NSDateFormatter alloc] init];
|
|
126
|
-
[formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
|
|
127
|
-
formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
|
|
128
|
-
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
NSString *iso8601String = [formatter stringFromDate:date];
|
|
132
|
-
|
|
133
|
-
return [iso8601String stringByAppendingString:@"Z"];
|
|
152
|
+
return [RNFBSharedUtilsFormatting getISO8601String:date];
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
+ (BOOL)configContains:(NSString *)key {
|
|
137
|
-
return [
|
|
138
|
-
|
|
156
|
+
return [RNFBSharedUtilsConfig
|
|
157
|
+
configContainsKey:key
|
|
158
|
+
preferences:(id<RNFBConfigBooleanProviding>)[RNFBPreferences shared]
|
|
159
|
+
json:(id<RNFBConfigBooleanProviding>)[RNFBJSON shared]
|
|
160
|
+
meta:RNFBSharedUtilsMetaConfigSource()];
|
|
139
161
|
}
|
|
140
162
|
|
|
141
163
|
+ (BOOL)getConfigBooleanValue:(NSString *)tag key:(NSString *)key defaultValue:(BOOL)defaultValue {
|
|
142
|
-
BOOL enabled
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
enabled = [[RNFBJSON shared] getBooleanValue:key defaultValue:defaultValue];
|
|
151
|
-
DLog(@"%@ %@ via "
|
|
152
|
-
@"RNFBJSON: %d",
|
|
153
|
-
tag, key, enabled);
|
|
154
|
-
} else {
|
|
155
|
-
// Note that if we're here, and the key is not set on the app's bundle, our final default is the
|
|
156
|
-
// one passed in
|
|
157
|
-
enabled = [RNFBMeta getBooleanValue:key defaultValue:defaultValue];
|
|
158
|
-
DLog(@"%@ %@ via "
|
|
159
|
-
@"RNFBMeta: %d",
|
|
160
|
-
tag, key, enabled);
|
|
161
|
-
}
|
|
162
|
-
|
|
164
|
+
BOOL enabled = [RNFBSharedUtilsConfig
|
|
165
|
+
getConfigBooleanValueForKey:key
|
|
166
|
+
defaultValue:defaultValue
|
|
167
|
+
preferences:(id<RNFBConfigBooleanProviding>)[RNFBPreferences shared]
|
|
168
|
+
json:(id<RNFBConfigBooleanProviding>)[RNFBJSON shared]
|
|
169
|
+
meta:RNFBSharedUtilsMetaConfigSource()];
|
|
170
|
+
// Branch-specific "via Preferences/JSON/Meta" DLogs lived in the pre-port body; keep the
|
|
171
|
+
// final-value log on the ObjC façade (DLog is an ObjC macro; return value unchanged).
|
|
163
172
|
DLog(@"%@ %@ final value: %d", tag, key, enabled);
|
|
164
|
-
|
|
165
173
|
return enabled;
|
|
166
174
|
}
|
|
167
175
|
|
|
@@ -183,104 +191,7 @@ static NSString *const RNFBErrorDomain = @"RNFBErrorDomain";
|
|
|
183
191
|
* @return The decoded value with sentinels replaced by NSNull
|
|
184
192
|
*/
|
|
185
193
|
+ (id)decodeNullSentinels:(id)value {
|
|
186
|
-
|
|
187
|
-
if (![value isKindOfClass:[NSDictionary class]] && ![value isKindOfClass:[NSArray class]]) {
|
|
188
|
-
return value;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Helper to detect the sentinel
|
|
192
|
-
BOOL (^isNullSentinel)(NSDictionary *) = ^BOOL(NSDictionary *dict) {
|
|
193
|
-
id flag = dict[@"__rnfbNull"];
|
|
194
|
-
return (dict.count == 1 && flag != nil && [flag boolValue]);
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// Helper to process a child element and add it to the parent container
|
|
198
|
-
void (^processChild)(id, id, id, BOOL, NSMutableArray *) =
|
|
199
|
-
^void(id child, id parentMutable, id keyOrNil, BOOL isParentDict, NSMutableArray *stack) {
|
|
200
|
-
id processedValue = nil;
|
|
201
|
-
|
|
202
|
-
if ([child isKindOfClass:[NSDictionary class]]) {
|
|
203
|
-
NSDictionary *childDict = (NSDictionary *)child;
|
|
204
|
-
|
|
205
|
-
if (isNullSentinel(childDict)) {
|
|
206
|
-
// Replace sentinel with NSNull
|
|
207
|
-
processedValue = [NSNull null];
|
|
208
|
-
} else {
|
|
209
|
-
// Process nested dictionary
|
|
210
|
-
NSMutableDictionary *childMut =
|
|
211
|
-
[NSMutableDictionary dictionaryWithCapacity:childDict.count];
|
|
212
|
-
processedValue = childMut;
|
|
213
|
-
[stack addObject:@{@"original" : childDict, @"mutable" : childMut}];
|
|
214
|
-
}
|
|
215
|
-
} else if ([child isKindOfClass:[NSArray class]]) {
|
|
216
|
-
// Process nested array
|
|
217
|
-
NSArray *childArray = (NSArray *)child;
|
|
218
|
-
NSMutableArray *childMut = [NSMutableArray arrayWithCapacity:childArray.count];
|
|
219
|
-
processedValue = childMut;
|
|
220
|
-
[stack addObject:@{@"original" : childArray, @"mutable" : childMut}];
|
|
221
|
-
} else {
|
|
222
|
-
// Preserve primitive values
|
|
223
|
-
processedValue = child ?: [NSNull null];
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Add to parent container based on type
|
|
227
|
-
if (isParentDict) {
|
|
228
|
-
NSMutableDictionary *mutDict = (NSMutableDictionary *)parentMutable;
|
|
229
|
-
if (processedValue) {
|
|
230
|
-
mutDict[keyOrNil] = processedValue;
|
|
231
|
-
}
|
|
232
|
-
// NSDictionary can't store nil, and original code wouldn't see nil values either.
|
|
233
|
-
} else {
|
|
234
|
-
NSMutableArray *mutArray = (NSMutableArray *)parentMutable;
|
|
235
|
-
[mutArray addObject:processedValue];
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
// Root-level sentinel case
|
|
240
|
-
if ([value isKindOfClass:[NSDictionary class]] && isNullSentinel((NSDictionary *)value)) {
|
|
241
|
-
return [NSNull null];
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
id rootOriginal = value;
|
|
245
|
-
id rootMutable = nil;
|
|
246
|
-
|
|
247
|
-
if ([value isKindOfClass:[NSDictionary class]]) {
|
|
248
|
-
NSDictionary *dict = (NSDictionary *)value;
|
|
249
|
-
rootMutable = [NSMutableDictionary dictionaryWithCapacity:dict.count];
|
|
250
|
-
} else {
|
|
251
|
-
NSArray *array = (NSArray *)value;
|
|
252
|
-
rootMutable = [NSMutableArray arrayWithCapacity:array.count];
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Stack-based iteration to process nested structures without recursion
|
|
256
|
-
// Stack frames: { @"original": container, @"mutable": mutableContainer }
|
|
257
|
-
NSMutableArray<NSDictionary *> *stack = [NSMutableArray array];
|
|
258
|
-
[stack addObject:@{@"original" : rootOriginal, @"mutable" : rootMutable}];
|
|
259
|
-
|
|
260
|
-
while (stack.count > 0) {
|
|
261
|
-
NSDictionary *frame = [stack lastObject];
|
|
262
|
-
[stack removeLastObject];
|
|
263
|
-
|
|
264
|
-
id original = frame[@"original"];
|
|
265
|
-
id mutable = frame[@"mutable"];
|
|
266
|
-
|
|
267
|
-
if ([original isKindOfClass:[NSDictionary class]]) {
|
|
268
|
-
NSDictionary *origDict = (NSDictionary *)original;
|
|
269
|
-
|
|
270
|
-
for (id key in origDict) {
|
|
271
|
-
id child = origDict[key];
|
|
272
|
-
processChild(child, mutable, key, YES, stack);
|
|
273
|
-
}
|
|
274
|
-
} else if ([original isKindOfClass:[NSArray class]]) {
|
|
275
|
-
NSArray *origArray = (NSArray *)original;
|
|
276
|
-
|
|
277
|
-
for (id child in origArray) {
|
|
278
|
-
processChild(child, mutable, nil, NO, stack);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return rootMutable;
|
|
194
|
+
return [RNFBNullSentinelDecoder decodeNullSentinels:value];
|
|
284
195
|
}
|
|
285
196
|
|
|
286
197
|
@end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import Foundation
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Boolean config source used by the SharedUtils config waterfall.
|
|
21
|
+
*
|
|
22
|
+
* Production passes `RNFBPreferences` / `RNFBJSON` instances and a Meta adapter;
|
|
23
|
+
* unit tests inject recording stubs to assert precedence and `||` short-circuit.
|
|
24
|
+
*/
|
|
25
|
+
@objc public protocol RNFBConfigBooleanProviding: AnyObject {
|
|
26
|
+
@objc(contains:)
|
|
27
|
+
func contains(_ key: String) -> Bool
|
|
28
|
+
|
|
29
|
+
@objc(getBooleanValue:defaultValue:)
|
|
30
|
+
func getBooleanValue(_ key: String, defaultValue: Bool) -> Bool
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Config waterfall previously inline in `RNFBSharedUtils.m`.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors pre-port:
|
|
37
|
+
* - `configContains` is Preferences.contains || JSON.contains || Meta.contains
|
|
38
|
+
* (left-to-right short-circuit, same as ObjC `||`)
|
|
39
|
+
* - `getConfigBooleanValue` prefers Preferences if contains, else JSON if contains,
|
|
40
|
+
* else Meta (Meta path always used as final, with the passed-in `defaultValue`)
|
|
41
|
+
*/
|
|
42
|
+
@objc(RNFBSharedUtilsConfig)
|
|
43
|
+
public final class RNFBSharedUtilsConfig: NSObject {
|
|
44
|
+
@objc(configContainsKey:preferences:json:meta:)
|
|
45
|
+
public static func configContains(
|
|
46
|
+
_ key: String,
|
|
47
|
+
preferences: RNFBConfigBooleanProviding,
|
|
48
|
+
json: RNFBConfigBooleanProviding,
|
|
49
|
+
meta: RNFBConfigBooleanProviding
|
|
50
|
+
) -> Bool {
|
|
51
|
+
preferences.contains(key) || json.contains(key) || meta.contains(key)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@objc(getConfigBooleanValueForKey:defaultValue:preferences:json:meta:)
|
|
55
|
+
public static func getConfigBooleanValue(
|
|
56
|
+
forKey key: String,
|
|
57
|
+
defaultValue: Bool,
|
|
58
|
+
preferences: RNFBConfigBooleanProviding,
|
|
59
|
+
json: RNFBConfigBooleanProviding,
|
|
60
|
+
meta: RNFBConfigBooleanProviding
|
|
61
|
+
) -> Bool {
|
|
62
|
+
if preferences.contains(key) {
|
|
63
|
+
return preferences.getBooleanValue(key, defaultValue: defaultValue)
|
|
64
|
+
}
|
|
65
|
+
if json.contains(key) {
|
|
66
|
+
return json.getBooleanValue(key, defaultValue: defaultValue)
|
|
67
|
+
}
|
|
68
|
+
// Note that if we're here, and the key is not set on the app's bundle, our final
|
|
69
|
+
// default is the one passed in (pre-port Meta path behaviour).
|
|
70
|
+
return meta.getBooleanValue(key, defaultValue: defaultValue)
|
|
71
|
+
}
|
|
72
|
+
}
|