@react-native-firebase/remote-config 25.1.0 → 26.1.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/RNFBRemoteConfig.podspec +9 -7
  3. package/android/build.gradle +19 -0
  4. package/android/src/reactnative/java/io/invertase/firebase/config/{ReactNativeFirebaseConfigModule.java → NativeRNFBTurboConfig.java} +53 -40
  5. package/android/src/reactnative/java/io/invertase/firebase/config/ReactNativeFirebaseConfigPackage.java +1 -1
  6. package/android/src/reactnative/java/io/invertase/firebase/config/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboConfigSpec.java +115 -0
  7. package/android/src/reactnative/java/io/invertase/firebase/config/generated/jni/CMakeLists.txt +36 -0
  8. package/android/src/reactnative/java/io/invertase/firebase/config/generated/jni/RNFBRemoteConfigTurboModules-generated.cpp +98 -0
  9. package/android/src/reactnative/java/io/invertase/firebase/config/generated/jni/RNFBRemoteConfigTurboModules.h +31 -0
  10. package/android/src/reactnative/java/io/invertase/firebase/config/generated/jni/react/renderer/components/RNFBRemoteConfigTurboModules/RNFBRemoteConfigTurboModulesJSI-generated.cpp +110 -0
  11. package/android/src/reactnative/java/io/invertase/firebase/config/generated/jni/react/renderer/components/RNFBRemoteConfigTurboModules/RNFBRemoteConfigTurboModulesJSI.h +471 -0
  12. package/dist/module/index.js +499 -5
  13. package/dist/module/index.js.map +1 -1
  14. package/dist/module/version.js +1 -1
  15. package/dist/typescript/lib/index.d.ts +83 -5
  16. package/dist/typescript/lib/index.d.ts.map +1 -1
  17. package/dist/typescript/lib/types/internal.d.ts +25 -24
  18. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  19. package/dist/typescript/lib/types/remote-config.d.ts +24 -3
  20. package/dist/typescript/lib/types/remote-config.d.ts.map +1 -1
  21. package/dist/typescript/lib/version.d.ts +1 -1
  22. package/ios/RNFBConfig/RNFBConfigHelper.h +89 -0
  23. package/ios/RNFBConfig/{RNFBConfigModule.m → RNFBConfigHelper.m} +176 -165
  24. package/ios/RNFBConfig/RNFBConfigModule.h +3 -2
  25. package/ios/RNFBConfig/RNFBConfigModule.mm +134 -0
  26. package/ios/RNFBConfig.xcodeproj/project.pbxproj +8 -8
  27. package/ios/generated/RCTAppDependencyProvider.h +25 -0
  28. package/ios/generated/RCTAppDependencyProvider.mm +55 -0
  29. package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
  30. package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
  31. package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
  32. package/ios/generated/RCTThirdPartyComponentsProvider.mm +23 -0
  33. package/ios/generated/RNFBRemoteConfigTurboModules/RNFBRemoteConfigTurboModules-generated.mm +121 -0
  34. package/ios/generated/RNFBRemoteConfigTurboModules/RNFBRemoteConfigTurboModules.h +172 -0
  35. package/ios/generated/RNFBRemoteConfigTurboModulesJSI-generated.cpp +110 -0
  36. package/ios/generated/RNFBRemoteConfigTurboModulesJSI.h +471 -0
  37. package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
  38. package/lib/index.ts +683 -8
  39. package/lib/types/internal.ts +25 -44
  40. package/lib/types/remote-config.ts +28 -3
  41. package/lib/version.ts +1 -1
  42. package/package.json +23 -5
  43. package/react-native.config.js +10 -0
  44. package/specs/NativeRNFBTurboConfig.ts +60 -0
  45. package/typedoc.json +1 -1
  46. package/dist/module/modular.js +0 -155
  47. package/dist/module/modular.js.map +0 -1
  48. package/dist/module/namespaced.js +0 -400
  49. package/dist/module/namespaced.js.map +0 -1
  50. package/dist/module/types/namespaced.js +0 -24
  51. package/dist/module/types/namespaced.js.map +0 -1
  52. package/dist/typescript/lib/modular.d.ts +0 -76
  53. package/dist/typescript/lib/modular.d.ts.map +0 -1
  54. package/dist/typescript/lib/namespaced.d.ts +0 -11
  55. package/dist/typescript/lib/namespaced.d.ts.map +0 -1
  56. package/dist/typescript/lib/types/namespaced.d.ts +0 -124
  57. package/dist/typescript/lib/types/namespaced.d.ts.map +0 -1
  58. package/lib/modular.ts +0 -197
  59. package/lib/namespaced.ts +0 -552
  60. package/lib/types/namespaced.ts +0 -163
@@ -15,22 +15,23 @@
15
15
  *
16
16
  */
17
17
 
18
+ #if __has_include(<Firebase/Firebase.h>)
18
19
  #import <Firebase/Firebase.h>
20
+ #else
21
+ @import FirebaseCore;
22
+ @import FirebaseRemoteConfig;
23
+ #endif
19
24
  #import <React/RCTConvert.h>
20
- #import <React/RCTUtils.h>
21
25
 
22
- #import "RNFBConfigModule.h"
23
- #import "RNFBSharedUtils.h"
26
+ #import "RNFBApp/RCTConvert+FIRApp.h"
27
+ #import "RNFBApp/RNFBSharedUtils.h"
28
+ #import "RNFBConfigHelper.h"
24
29
 
25
30
  static NSString *const ON_CONFIG_UPDATED_EVENT = @"on_config_updated";
26
31
 
27
32
  static __strong NSMutableDictionary *configUpdateHandlers;
28
33
 
29
- @implementation RNFBConfigModule
30
- #pragma mark -
31
- #pragma mark Converters
32
-
33
- NSString *convertFIRRemoteConfigFetchStatusToNSString(FIRRemoteConfigFetchStatus value) {
34
+ static NSString *convertFIRRemoteConfigFetchStatusToNSString(FIRRemoteConfigFetchStatus value) {
34
35
  switch (value) {
35
36
  case FIRRemoteConfigFetchStatusNoFetchYet:
36
37
  return @"no_fetch_yet";
@@ -45,7 +46,8 @@ NSString *convertFIRRemoteConfigFetchStatusToNSString(FIRRemoteConfigFetchStatus
45
46
  }
46
47
  }
47
48
 
48
- NSString *convertFIRRemoteConfigFetchStatusToNSStringDescription(FIRRemoteConfigFetchStatus value) {
49
+ static NSString *convertFIRRemoteConfigFetchStatusToNSStringDescription(
50
+ FIRRemoteConfigFetchStatus value) {
49
51
  switch (value) {
50
52
  case FIRRemoteConfigFetchStatusThrottled:
51
53
  return @"fetch() operation cannot be completed successfully, due to throttling.";
@@ -55,7 +57,7 @@ NSString *convertFIRRemoteConfigFetchStatusToNSStringDescription(FIRRemoteConfig
55
57
  }
56
58
  }
57
59
 
58
- NSString *convertFIRRemoteConfigSourceToNSString(FIRRemoteConfigSource value) {
60
+ static NSString *convertFIRRemoteConfigSourceToNSString(FIRRemoteConfigSource value) {
59
61
  switch (value) {
60
62
  case FIRRemoteConfigSourceDefault:
61
63
  return @"default";
@@ -68,7 +70,7 @@ NSString *convertFIRRemoteConfigSourceToNSString(FIRRemoteConfigSource value) {
68
70
  }
69
71
  }
70
72
 
71
- NSString *convertFIRRemoteConfigUpdateErrorToNSString(FIRRemoteConfigUpdateError value) {
73
+ static NSString *convertFIRRemoteConfigUpdateErrorToNSString(FIRRemoteConfigUpdateError value) {
72
74
  switch (value) {
73
75
  case FIRRemoteConfigUpdateErrorStreamError:
74
76
  return @"config_update_stream_error";
@@ -83,55 +85,77 @@ NSString *convertFIRRemoteConfigUpdateErrorToNSString(FIRRemoteConfigUpdateError
83
85
  }
84
86
  }
85
87
 
86
- NSDictionary *convertFIRRemoteConfigValueToNSDictionary(FIRRemoteConfigValue *value) {
88
+ static NSDictionary *convertFIRRemoteConfigValueToNSDictionary(FIRRemoteConfigValue *value) {
87
89
  return @{
88
90
  @"value" : (id)value.stringValue ?: [NSNull null],
89
91
  @"source" : convertFIRRemoteConfigSourceToNSString(value.source)
90
92
  };
91
93
  }
92
94
 
93
- #pragma mark -
94
- #pragma mark Module Setup
95
+ static FIRApp *firebaseAppForName(NSString *appName) {
96
+ return [RCTConvert firAppFromString:appName];
97
+ }
95
98
 
96
- RCT_EXPORT_MODULE();
99
+ @implementation RNFBConfigHelper
97
100
 
98
- - (dispatch_queue_t)methodQueue {
99
- return dispatch_get_main_queue();
101
+ + (NSDictionary *)getConstantsForAppName:(NSString *)appName {
102
+ FIRApp *firebaseApp = firebaseAppForName(appName);
103
+ return [self getConstantsForApp:firebaseApp];
100
104
  }
101
105
 
102
- + (BOOL)requiresMainQueueSetup {
103
- return YES;
104
- }
106
+ + (NSDictionary *)getConstantsForApp:(FIRApp *)firebaseApp {
107
+ FIRRemoteConfig *remoteConfig = [FIRRemoteConfig remoteConfigWithApp:firebaseApp];
105
108
 
106
- - (id)init {
107
- self = [super init];
108
- static dispatch_once_t onceToken;
109
- dispatch_once(&onceToken, ^{
110
- configUpdateHandlers = [[NSMutableDictionary alloc] init];
111
- });
112
- return self;
113
- }
109
+ NSDate *lastFetchTime = remoteConfig.lastFetchTime;
110
+ NSString *lastFetchStatus =
111
+ convertFIRRemoteConfigFetchStatusToNSString(remoteConfig.lastFetchStatus);
112
+ double minimumFetchInterval =
113
+ [RCTConvert double:@([remoteConfig configSettings].minimumFetchInterval)];
114
+ double fetchTimeout = [RCTConvert double:@([remoteConfig configSettings].fetchTimeout)];
114
115
 
115
- - (void)dealloc {
116
- [self invalidate];
117
- }
116
+ NSMutableDictionary *values = [NSMutableDictionary new];
117
+ NSSet *keys = [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] keysWithPrefix:nil];
118
+ for (NSString *key in keys) {
119
+ FIRRemoteConfigValue *value =
120
+ [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] configValueForKey:key];
121
+ values[key] = convertFIRRemoteConfigValueToNSDictionary(value);
122
+ }
118
123
 
119
- - (void)invalidate {
120
- for (NSString *key in configUpdateHandlers) {
121
- FIRConfigUpdateListenerRegistration *registration = [configUpdateHandlers objectForKey:key];
122
- [registration remove];
124
+ NSArray *defaultKeys = [remoteConfig allKeysFromSource:FIRRemoteConfigSourceDefault];
125
+ for (NSString *key in defaultKeys) {
126
+ if ([values valueForKey:key] == nil) {
127
+ FIRRemoteConfigValue *value =
128
+ [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] configValueForKey:key];
129
+ values[key] = convertFIRRemoteConfigValueToNSDictionary(value);
130
+ }
123
131
  }
124
132
 
125
- [configUpdateHandlers removeAllObjects];
133
+ return @{
134
+ @"values" : values,
135
+ @"lastFetchStatus" : lastFetchStatus,
136
+ @"lastFetchTime" : @(round([lastFetchTime timeIntervalSince1970] * 1000.0)),
137
+ @"minimumFetchInterval" : @(minimumFetchInterval),
138
+ @"fetchTimeout" : @(fetchTimeout)
139
+ };
140
+ }
141
+
142
+ + (NSDictionary *)resultWithConstants:(id)result firebaseApp:(FIRApp *)firebaseApp {
143
+ NSMutableDictionary *responseDict = [NSMutableDictionary new];
144
+ responseDict[@"result"] = result;
145
+ responseDict[@"constants"] = [self getConstantsForApp:firebaseApp];
146
+ return responseDict;
126
147
  }
127
148
 
128
- #pragma mark -
129
- #pragma mark Firebase Config Methods
149
+ + (NSDictionary *)resultWithVoidConstantsForApp:(FIRApp *)firebaseApp {
150
+ NSMutableDictionary *responseDict = [NSMutableDictionary new];
151
+ responseDict[@"constants"] = [self getConstantsForApp:firebaseApp];
152
+ return responseDict;
153
+ }
130
154
 
131
- RCT_EXPORT_METHOD(ensureInitialized
132
- : (FIRApp *)firebaseApp
133
- : (RCTPromiseResolveBlock)resolve
134
- : (RCTPromiseRejectBlock)reject) {
155
+ + (void)ensureInitialized:(NSString *)appName
156
+ resolve:(RCTPromiseResolveBlock)resolve
157
+ reject:(RCTPromiseRejectBlock)reject {
158
+ FIRApp *firebaseApp = firebaseAppForName(appName);
135
159
  FIRRemoteConfigInitializationCompletion completionHandler = ^(NSError *__nullable error) {
136
160
  if (error) {
137
161
  [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
@@ -144,11 +168,11 @@ RCT_EXPORT_METHOD(ensureInitialized
144
168
  ensureInitializedWithCompletionHandler:completionHandler];
145
169
  }
146
170
 
147
- RCT_EXPORT_METHOD(fetch
148
- : (FIRApp *)firebaseApp
149
- : (nonnull NSNumber *)expirationDuration
150
- : (RCTPromiseResolveBlock)resolve
151
- : (RCTPromiseRejectBlock)reject) {
171
+ + (void)fetch:(NSString *)appName
172
+ expirationDurationSeconds:(double)expirationDurationSeconds
173
+ resolve:(RCTPromiseResolveBlock)resolve
174
+ reject:(RCTPromiseRejectBlock)reject {
175
+ FIRApp *firebaseApp = firebaseAppForName(appName);
152
176
  FIRRemoteConfigFetchCompletion completionHandler =
153
177
  ^(FIRRemoteConfigFetchStatus status, NSError *__nullable error) {
154
178
  if (error) {
@@ -164,46 +188,23 @@ RCT_EXPORT_METHOD(fetch
164
188
  }
165
189
  };
166
190
 
167
- if (expirationDuration.integerValue == -1) {
191
+ if (expirationDurationSeconds == -1) {
168
192
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp]
169
193
  fetchWithCompletionHandler:completionHandler];
170
194
  } else {
171
195
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp]
172
- fetchWithExpirationDuration:expirationDuration.doubleValue
196
+ fetchWithExpirationDuration:expirationDurationSeconds
173
197
  completionHandler:completionHandler];
174
198
  }
175
199
  }
176
200
 
177
- RCT_EXPORT_METHOD(fetchAndActivate
178
- : (FIRApp *)firebaseApp
179
- : (RCTPromiseResolveBlock)resolve
180
- : (RCTPromiseRejectBlock)reject) {
181
- FIRRemoteConfigFetchAndActivateCompletion completionHandler =
182
- ^(FIRRemoteConfigFetchAndActivateStatus status, NSError *__nullable error) {
183
- if (error) {
184
- if (error.userInfo && error.userInfo[@"ActivationFailureReason"] != nil &&
185
- [error.userInfo[@"ActivationFailureReason"] containsString:@"already activated"]) {
186
- resolve([self resultWithConstants:@([RCTConvert BOOL:@(YES)]) firebaseApp:firebaseApp]);
187
- } else {
188
- [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
189
- }
190
- } else {
191
- if (status == FIRRemoteConfigFetchAndActivateStatusSuccessFetchedFromRemote) {
192
- resolve([self resultWithConstants:@([RCTConvert BOOL:@(YES)]) firebaseApp:firebaseApp]);
193
- return;
194
- }
195
- // if no data fetched remotely, return false
196
- resolve([self resultWithConstants:@([RCTConvert BOOL:@(NO)]) firebaseApp:firebaseApp]);
197
- }
198
- };
199
-
200
- [[FIRRemoteConfig remoteConfig] fetchAndActivateWithCompletionHandler:completionHandler];
201
- }
202
-
203
- RCT_EXPORT_METHOD(activate
204
- : (FIRApp *)firebaseApp
205
- : (RCTPromiseResolveBlock)resolve
206
- : (RCTPromiseRejectBlock)reject) {
201
+ // Shared by `activate:` and `fetchAndActivate:` below - resolves with the `changed` BOOL from
202
+ // `-[FIRRemoteConfig activateWithCompletion:]`, treating the SDK's "already activated" error as a
203
+ // non-error `false` result rather than a rejection, since it just means there was nothing new to
204
+ // activate.
205
+ + (void)rnfb_activateRemoteConfig:(FIRApp *)firebaseApp
206
+ resolve:(RCTPromiseResolveBlock)resolve
207
+ reject:(RCTPromiseRejectBlock)reject {
207
208
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] activateWithCompletion:^(
208
209
  BOOL changed, NSError *_Nullable error) {
209
210
  if (error) {
@@ -219,41 +220,78 @@ RCT_EXPORT_METHOD(activate
219
220
  }];
220
221
  }
221
222
 
222
- RCT_EXPORT_METHOD(setConfigSettings
223
- : (FIRApp *)firebaseApp
224
- : (NSDictionary *)configSettings
225
- : (RCTPromiseResolveBlock)resolve
226
- : (RCTPromiseRejectBlock)reject) {
227
- FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] init];
223
+ + (void)fetchAndActivate:(NSString *)appName
224
+ resolve:(RCTPromiseResolveBlock)resolve
225
+ reject:(RCTPromiseRejectBlock)reject {
226
+ // NOTE: We deliberately do not use `-[FIRRemoteConfig fetchAndActivateWithCompletionHandler:]`
227
+ // here. Its `FIRRemoteConfigFetchAndActivateStatus` result only reflects whether the fetch
228
+ // succeeded (`SuccessFetchedFromRemote`) vs fell back to previously fetched data
229
+ // (`SuccessUsingPreFetchedData`) - it does NOT reflect whether activation actually changed any
230
+ // config values, so it reports `SuccessFetchedFromRemote` (=> we'd resolve `true`) even when the
231
+ // fetched values are identical to what's already active. See
232
+ // https://github.com/invertase/react-native-firebase/issues/7779
233
+ //
234
+ // Instead we perform the fetch ourselves and hand off to the same activation + resolution logic
235
+ // `activate()` uses, so `fetchAndActivate()` resolves `true` only when activation changed the
236
+ // in-use config values - matching `activate()`'s own semantics as well as the Android
237
+ // implementation.
238
+ FIRApp *firebaseApp = firebaseAppForName(appName);
239
+ FIRRemoteConfigFetchCompletion fetchCompletion =
240
+ ^(FIRRemoteConfigFetchStatus status, NSError *__nullable error) {
241
+ if (error) {
242
+ [RNFBSharedUtils
243
+ rejectPromiseWithUserInfo:reject
244
+ userInfo:[@{
245
+ @"code" : convertFIRRemoteConfigFetchStatusToNSString(status),
246
+ @"message" :
247
+ convertFIRRemoteConfigFetchStatusToNSStringDescription(status)
248
+ } mutableCopy]];
249
+ return;
250
+ }
228
251
 
229
- if ([configSettings objectForKey:@"minimumFetchInterval"]) {
230
- remoteConfigSettings.minimumFetchInterval =
231
- [configSettings[@"minimumFetchInterval"] doubleValue];
232
- }
252
+ [self rnfb_activateRemoteConfig:firebaseApp resolve:resolve reject:reject];
253
+ };
233
254
 
234
- if ([configSettings objectForKey:@"fetchTimeout"]) {
235
- remoteConfigSettings.fetchTimeout = [configSettings[@"fetchTimeout"] doubleValue];
236
- }
255
+ [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] fetchWithCompletionHandler:fetchCompletion];
256
+ }
257
+
258
+ + (void)activate:(NSString *)appName
259
+ resolve:(RCTPromiseResolveBlock)resolve
260
+ reject:(RCTPromiseRejectBlock)reject {
261
+ FIRApp *firebaseApp = firebaseAppForName(appName);
262
+ [self rnfb_activateRemoteConfig:firebaseApp resolve:resolve reject:reject];
263
+ }
264
+
265
+ + (void)setConfigSettings:(NSString *)appName
266
+ minimumFetchInterval:(double)minimumFetchInterval
267
+ fetchTimeout:(double)fetchTimeout
268
+ resolve:(RCTPromiseResolveBlock)resolve
269
+ reject:(RCTPromiseRejectBlock)reject {
270
+ FIRApp *firebaseApp = firebaseAppForName(appName);
271
+ FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] init];
272
+ remoteConfigSettings.minimumFetchInterval = minimumFetchInterval;
273
+ remoteConfigSettings.fetchTimeout = fetchTimeout;
237
274
 
238
275
  [FIRRemoteConfig remoteConfigWithApp:firebaseApp].configSettings = remoteConfigSettings;
239
276
  resolve([self resultWithVoidConstantsForApp:firebaseApp]);
240
277
  }
241
278
 
242
- RCT_EXPORT_METHOD(setDefaults
243
- : (FIRApp *)firebaseApp
244
- : (NSDictionary *)defaults
245
- : (RCTPromiseResolveBlock)resolve
246
- : (RCTPromiseRejectBlock)reject) {
279
+ + (void)setDefaults:(NSString *)appName
280
+ defaults:(NSDictionary *)defaults
281
+ resolve:(RCTPromiseResolveBlock)resolve
282
+ reject:(RCTPromiseRejectBlock)reject {
283
+ FIRApp *firebaseApp = firebaseAppForName(appName);
247
284
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] setDefaults:defaults];
248
285
  resolve([self resultWithConstants:[NSNull null] firebaseApp:firebaseApp]);
249
286
  }
250
- RCT_EXPORT_METHOD(setDefaultsFromResource
251
- : (FIRApp *)firebaseApp
252
- : (NSString *)fileName
253
- : (RCTPromiseResolveBlock)resolve
254
- : (RCTPromiseRejectBlock)reject) {
255
- if ([[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"] != nil) {
256
- [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] setDefaultsFromPlistFileName:fileName];
287
+
288
+ + (void)setDefaultsFromResource:(NSString *)appName
289
+ resourceName:(NSString *)resourceName
290
+ resolve:(RCTPromiseResolveBlock)resolve
291
+ reject:(RCTPromiseRejectBlock)reject {
292
+ FIRApp *firebaseApp = firebaseAppForName(appName);
293
+ if ([[NSBundle mainBundle] pathForResource:resourceName ofType:@"plist"] != nil) {
294
+ [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] setDefaultsFromPlistFileName:resourceName];
257
295
  resolve([self resultWithConstants:[NSNull null] firebaseApp:firebaseApp]);
258
296
  } else {
259
297
  [RNFBSharedUtils rejectPromiseWithUserInfo:reject
@@ -264,7 +302,20 @@ RCT_EXPORT_METHOD(setDefaultsFromResource
264
302
  }
265
303
  }
266
304
 
267
- RCT_EXPORT_METHOD(onConfigUpdated : (FIRApp *)firebaseApp) {
305
+ + (void)reset:(NSString *)appName
306
+ resolve:(RCTPromiseResolveBlock)resolve
307
+ reject:(RCTPromiseRejectBlock)reject {
308
+ FIRApp *firebaseApp = firebaseAppForName(appName);
309
+ resolve([self resultWithVoidConstantsForApp:firebaseApp]);
310
+ }
311
+
312
+ + (void)onConfigUpdated:(NSString *)appName {
313
+ static dispatch_once_t onceToken;
314
+ dispatch_once(&onceToken, ^{
315
+ configUpdateHandlers = [[NSMutableDictionary alloc] init];
316
+ });
317
+
318
+ FIRApp *firebaseApp = firebaseAppForName(appName);
268
319
  if (![configUpdateHandlers valueForKey:firebaseApp.name]) {
269
320
  FIRConfigUpdateListenerRegistration *newRegistration =
270
321
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp]
@@ -274,7 +325,8 @@ RCT_EXPORT_METHOD(onConfigUpdated : (FIRApp *)firebaseApp) {
274
325
  NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
275
326
 
276
327
  [userInfo setValue:@"error" forKey:@"resultType"];
277
- [userInfo setValue:convertFIRRemoteConfigUpdateErrorToNSString(error.code)
328
+ [userInfo setValue:convertFIRRemoteConfigUpdateErrorToNSString(
329
+ (FIRRemoteConfigUpdateError)error.code)
278
330
  forKey:@"code"];
279
331
  [userInfo setValue:error.localizedDescription forKey:@"message"];
280
332
  [userInfo setValue:error.localizedDescription forKey:@"nativeErrorMessage"];
@@ -298,20 +350,31 @@ RCT_EXPORT_METHOD(onConfigUpdated : (FIRApp *)firebaseApp) {
298
350
  }
299
351
  }
300
352
 
301
- RCT_EXPORT_METHOD(removeConfigUpdateRegistration : (FIRApp *)firebaseApp) {
353
+ + (void)removeConfigUpdateRegistration:(NSString *)appName {
354
+ FIRApp *firebaseApp = firebaseAppForName(appName);
302
355
  if ([configUpdateHandlers valueForKey:firebaseApp.name]) {
303
356
  [[configUpdateHandlers objectForKey:firebaseApp.name] remove];
304
357
  [configUpdateHandlers removeObjectForKey:firebaseApp.name];
305
358
  }
306
359
  }
307
360
 
308
- RCT_EXPORT_METHOD(setCustomSignals
309
- : (FIRApp *)firebaseApp
310
- : (NSDictionary *)customSignals
311
- : (RCTPromiseResolveBlock)resolve
312
- : (RCTPromiseRejectBlock)reject) {
361
+ + (void)removeAllConfigUpdateRegistrations {
362
+ for (NSString *key in [configUpdateHandlers allKeys]) {
363
+ FIRConfigUpdateListenerRegistration *registration = [configUpdateHandlers objectForKey:key];
364
+ [registration remove];
365
+ }
366
+
367
+ [configUpdateHandlers removeAllObjects];
368
+ }
369
+
370
+ + (void)setCustomSignals:(NSString *)appName
371
+ customSignals:(NSDictionary *)customSignals
372
+ resolve:(RCTPromiseResolveBlock)resolve
373
+ reject:(RCTPromiseRejectBlock)reject {
374
+ FIRApp *firebaseApp = firebaseAppForName(appName);
375
+ NSDictionary *decodedCustomSignals = [RNFBSharedUtils decodeNullSentinels:customSignals];
313
376
  [[FIRRemoteConfig remoteConfigWithApp:firebaseApp]
314
- setCustomSignals:customSignals
377
+ setCustomSignals:decodedCustomSignals
315
378
  withCompletion:^(NSError *_Nullable error) {
316
379
  if (error != nil) {
317
380
  [RNFBSharedUtils rejectPromiseWithNSError:reject error:error];
@@ -321,56 +384,4 @@ RCT_EXPORT_METHOD(setCustomSignals
321
384
  }];
322
385
  }
323
386
 
324
- #pragma mark -
325
- #pragma mark Internal Helper Methods
326
-
327
- - (NSDictionary *)resultWithConstants:(id)result firebaseApp:(FIRApp *)firebaseApp {
328
- NSMutableDictionary *responseDict = [NSMutableDictionary new];
329
- responseDict[@"result"] = result;
330
- responseDict[@"constants"] = [self getConstantsForApp:firebaseApp];
331
- return responseDict;
332
- }
333
-
334
- - (NSDictionary *)resultWithVoidConstantsForApp:(FIRApp *)firebaseApp {
335
- NSMutableDictionary *responseDict = [NSMutableDictionary new];
336
- responseDict[@"constants"] = [self getConstantsForApp:firebaseApp];
337
- return responseDict;
338
- }
339
-
340
- - (NSDictionary *)getConstantsForApp:(FIRApp *)firebaseApp {
341
- FIRRemoteConfig *remoteConfig = [FIRRemoteConfig remoteConfigWithApp:firebaseApp];
342
-
343
- NSDate *lastFetchTime = remoteConfig.lastFetchTime;
344
- NSString *lastFetchStatus =
345
- convertFIRRemoteConfigFetchStatusToNSString(remoteConfig.lastFetchStatus);
346
- double minimumFetchInterval =
347
- [RCTConvert double:@([remoteConfig configSettings].minimumFetchInterval)];
348
- double fetchTimeout = [RCTConvert double:@([remoteConfig configSettings].fetchTimeout)];
349
-
350
- NSMutableDictionary *values = [NSMutableDictionary new];
351
- NSSet *keys = [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] keysWithPrefix:nil];
352
- for (NSString *key in keys) {
353
- FIRRemoteConfigValue *value =
354
- [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] configValueForKey:key];
355
- values[key] = convertFIRRemoteConfigValueToNSDictionary(value);
356
- }
357
-
358
- NSArray *defaultKeys = [remoteConfig allKeysFromSource:FIRRemoteConfigSourceDefault];
359
- for (NSString *key in defaultKeys) {
360
- if ([values valueForKey:key] == nil) {
361
- FIRRemoteConfigValue *value =
362
- [[FIRRemoteConfig remoteConfigWithApp:firebaseApp] configValueForKey:key];
363
- values[key] = convertFIRRemoteConfigValueToNSDictionary(value);
364
- }
365
- }
366
-
367
- return @{
368
- @"values" : values,
369
- @"lastFetchStatus" : lastFetchStatus,
370
- @"lastFetchTime" : @(round([lastFetchTime timeIntervalSince1970] * 1000.0)),
371
- @"minimumFetchInterval" : @(minimumFetchInterval),
372
- @"fetchTimeout" : @(fetchTimeout)
373
- };
374
- }
375
-
376
387
  @end
@@ -17,8 +17,9 @@
17
17
 
18
18
  #import <Foundation/Foundation.h>
19
19
 
20
- #import <React/RCTBridgeModule.h>
20
+ #import <React/RCTInvalidating.h>
21
+ #import "RNFBRemoteConfigTurboModules.h"
21
22
 
22
- @interface RNFBConfigModule : NSObject <RCTBridgeModule>
23
+ @interface RNFBConfigModule : NSObject <NativeRNFBTurboConfigSpec, RCTInvalidating>
23
24
 
24
25
  @end
@@ -0,0 +1,134 @@
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 "RNFBConfigModule.h"
19
+ #import "RNFBApp/RNFBSharedUtils.h"
20
+ #import "RNFBConfigHelper.h"
21
+
22
+ @implementation RNFBConfigModule
23
+ #pragma mark -
24
+ #pragma mark Module Setup
25
+
26
+ RCT_EXPORT_MODULE(NativeRNFBTurboConfig)
27
+
28
+ + (BOOL)requiresMainQueueSetup {
29
+ return NO;
30
+ }
31
+
32
+ - (void)invalidate {
33
+ [RNFBConfigHelper removeAllConfigUpdateRegistrations];
34
+ }
35
+
36
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
37
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
38
+ return std::make_shared<facebook::react::NativeRNFBTurboConfigSpecJSI>(params);
39
+ }
40
+
41
+ - (facebook::react::ModuleConstants<JS::NativeRNFBTurboConfig::Constants::Builder>)
42
+ constantsToExport {
43
+ return [_RCTTypedModuleConstants
44
+ newWithUnsafeDictionary:[RNFBConfigHelper getConstantsForAppName:DEFAULT_APP_DISPLAY_NAME]];
45
+ }
46
+
47
+ - (facebook::react::ModuleConstants<JS::NativeRNFBTurboConfig::Constants::Builder>)getConstants {
48
+ return [self constantsToExport];
49
+ }
50
+
51
+ #pragma mark -
52
+ #pragma mark Firebase Config Methods
53
+
54
+ - (void)ensureInitialized:(NSString *)appName
55
+ resolve:(RCTPromiseResolveBlock)resolve
56
+ reject:(RCTPromiseRejectBlock)reject {
57
+ [RNFBConfigHelper ensureInitialized:appName resolve:resolve reject:reject];
58
+ }
59
+
60
+ - (void)fetch:(NSString *)appName
61
+ expirationDurationSeconds:(double)expirationDurationSeconds
62
+ resolve:(RCTPromiseResolveBlock)resolve
63
+ reject:(RCTPromiseRejectBlock)reject {
64
+ [RNFBConfigHelper fetch:appName
65
+ expirationDurationSeconds:expirationDurationSeconds
66
+ resolve:resolve
67
+ reject:reject];
68
+ }
69
+
70
+ - (void)fetchAndActivate:(NSString *)appName
71
+ resolve:(RCTPromiseResolveBlock)resolve
72
+ reject:(RCTPromiseRejectBlock)reject {
73
+ [RNFBConfigHelper fetchAndActivate:appName resolve:resolve reject:reject];
74
+ }
75
+
76
+ - (void)activate:(NSString *)appName
77
+ resolve:(RCTPromiseResolveBlock)resolve
78
+ reject:(RCTPromiseRejectBlock)reject {
79
+ [RNFBConfigHelper activate:appName resolve:resolve reject:reject];
80
+ }
81
+
82
+ - (void)setConfigSettings:(NSString *)appName
83
+ settings:(JS::NativeRNFBTurboConfig::ConfigSettings &)configSettings
84
+ resolve:(RCTPromiseResolveBlock)resolve
85
+ reject:(RCTPromiseRejectBlock)reject {
86
+ [RNFBConfigHelper setConfigSettings:appName
87
+ minimumFetchInterval:configSettings.minimumFetchInterval()
88
+ fetchTimeout:configSettings.fetchTimeout()
89
+ resolve:resolve
90
+ reject:reject];
91
+ }
92
+
93
+ - (void)setDefaults:(NSString *)appName
94
+ defaults:(NSDictionary *)defaults
95
+ resolve:(RCTPromiseResolveBlock)resolve
96
+ reject:(RCTPromiseRejectBlock)reject {
97
+ [RNFBConfigHelper setDefaults:appName defaults:defaults resolve:resolve reject:reject];
98
+ }
99
+
100
+ - (void)setDefaultsFromResource:(NSString *)appName
101
+ resourceName:(NSString *)resourceName
102
+ resolve:(RCTPromiseResolveBlock)resolve
103
+ reject:(RCTPromiseRejectBlock)reject {
104
+ [RNFBConfigHelper setDefaultsFromResource:appName
105
+ resourceName:resourceName
106
+ resolve:resolve
107
+ reject:reject];
108
+ }
109
+
110
+ - (void)reset:(NSString *)appName
111
+ resolve:(RCTPromiseResolveBlock)resolve
112
+ reject:(RCTPromiseRejectBlock)reject {
113
+ [RNFBConfigHelper reset:appName resolve:resolve reject:reject];
114
+ }
115
+
116
+ - (void)onConfigUpdated:(NSString *)appName {
117
+ [RNFBConfigHelper onConfigUpdated:appName];
118
+ }
119
+
120
+ - (void)removeConfigUpdateRegistration:(NSString *)appName {
121
+ [RNFBConfigHelper removeConfigUpdateRegistration:appName];
122
+ }
123
+
124
+ - (void)setCustomSignals:(NSString *)appName
125
+ customSignals:(NSDictionary *)customSignals
126
+ resolve:(RCTPromiseResolveBlock)resolve
127
+ reject:(RCTPromiseRejectBlock)reject {
128
+ [RNFBConfigHelper setCustomSignals:appName
129
+ customSignals:customSignals
130
+ resolve:resolve
131
+ reject:reject];
132
+ }
133
+
134
+ @end