From a971038ef24c85a608a3bea31959bd4f07d74eb9 Mon Sep 17 00:00:00 2001 From: Jean Silva Date: Thu, 17 Nov 2016 20:27:59 -0500 Subject: [PATCH] Added RemoteConfig API --- ios/Firestack.xcodeproj/project.pbxproj | 6 ++ ios/Firestack/FirestackRemoteConfig.h | 24 +++++++ ios/Firestack/FirestackRemoteConfig.m | 87 +++++++++++++++++++++++++ lib/firestack.js | 16 ++--- lib/modules/remoteConfig.js | 25 ++++--- 5 files changed, 135 insertions(+), 23 deletions(-) create mode 100644 ios/Firestack/FirestackRemoteConfig.h create mode 100644 ios/Firestack/FirestackRemoteConfig.m diff --git a/ios/Firestack.xcodeproj/project.pbxproj b/ios/Firestack.xcodeproj/project.pbxproj index ba05903..b35d12f 100644 --- a/ios/Firestack.xcodeproj/project.pbxproj +++ b/ios/Firestack.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 544B47041DDE64610057E78B /* FirestackRemoteConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B47031DDE64610057E78B /* FirestackRemoteConfig.m */; }; D90882D61D89C18C00FB6742 /* FirestackCloudMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = D90882D51D89C18C00FB6742 /* FirestackCloudMessaging.m */; }; D950369E1D19C77400F7094D /* Firestack.m in Sources */ = {isa = PBXBuildFile; fileRef = D950369D1D19C77400F7094D /* Firestack.m */; }; D962903F1D6D15B00099A3EC /* FirestackErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = D962903E1D6D15B00099A3EC /* FirestackErrors.m */; }; @@ -30,6 +31,8 @@ /* Begin PBXFileReference section */ 134814201AA4EA6300B7C361 /* libFirestack.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFirestack.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 544B47031DDE64610057E78B /* FirestackRemoteConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirestackRemoteConfig.m; path = Firestack/FirestackRemoteConfig.m; sourceTree = ""; }; + 544B47051DDE647E0057E78B /* FirestackRemoteConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirestackRemoteConfig.h; path = Firestack/FirestackRemoteConfig.h; sourceTree = ""; }; D90882D41D89C18C00FB6742 /* FirestackCloudMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirestackCloudMessaging.h; path = Firestack/FirestackCloudMessaging.h; sourceTree = ""; }; D90882D51D89C18C00FB6742 /* FirestackCloudMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirestackCloudMessaging.m; path = Firestack/FirestackCloudMessaging.m; sourceTree = ""; }; D950369C1D19C77400F7094D /* Firestack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Firestack.h; path = Firestack/Firestack.h; sourceTree = ""; }; @@ -92,6 +95,8 @@ D96290841D6D28B80099A3EC /* FirestackDatabase.m */, D9D62E7A1D6D86FD003D826D /* FirestackStorage.h */, D9D62E7B1D6D86FD003D826D /* FirestackStorage.m */, + 544B47031DDE64610057E78B /* FirestackRemoteConfig.m */, + 544B47051DDE647E0057E78B /* FirestackRemoteConfig.h */, ); name = Modules; sourceTree = ""; @@ -158,6 +163,7 @@ D962903F1D6D15B00099A3EC /* FirestackErrors.m in Sources */, D950369E1D19C77400F7094D /* Firestack.m in Sources */, D90882D61D89C18C00FB6742 /* FirestackCloudMessaging.m in Sources */, + 544B47041DDE64610057E78B /* FirestackRemoteConfig.m in Sources */, D96290851D6D28B80099A3EC /* FirestackDatabase.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/Firestack/FirestackRemoteConfig.h b/ios/Firestack/FirestackRemoteConfig.h new file mode 100644 index 0000000..ae59163 --- /dev/null +++ b/ios/Firestack/FirestackRemoteConfig.h @@ -0,0 +1,24 @@ +// +// FirestackRemoteConfig.h +// Firestack +// +// Created by Jean Silva on 11/17/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#ifndef FirestackRemoteConfig_h +#define FirestackRemoteConfig_h + +#import "Firebase.h" +#import "RCTBridgeModule.h" +#import "RCTEventEmitter.h" + +@interface FirestackRemoteConfig : RCTEventEmitter { + +} + +@property (nonatomic, strong) FIRRemoteConfig *remoteConfigInstance; + +@end + +#endif /* FirestackRemoteConfig_h */ diff --git a/ios/Firestack/FirestackRemoteConfig.m b/ios/Firestack/FirestackRemoteConfig.m new file mode 100644 index 0000000..df86a2d --- /dev/null +++ b/ios/Firestack/FirestackRemoteConfig.m @@ -0,0 +1,87 @@ +// +// FirestackRemoteConfig.m +// Firestack +// +// Created by Jean Silva on 11/17/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#import "FirestackRemoteConfig.h" + +@implementation FirestackRemoteConfig + +RCT_EXPORT_MODULE(FirestackRemoteConfig); + + +RCT_EXPORT_METHOD(setDefaultRemoteConfig:(NSDictionary *)props + isDev:(BOOL) devMode + callback:(RCTResponseSenderBlock) callback) +{ + if (!self.remoteConfigInstance) { + // Create remote Config instance + self.remoteConfigInstance = [FIRRemoteConfig remoteConfig]; + } + FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] initWithDeveloperModeEnabled:devMode]; + + self.remoteConfigInstance.configSettings = remoteConfigSettings; + [self.remoteConfigInstance setDefaults: props]; + callback(@[[NSNull null], props]); +} + +RCT_EXPORT_METHOD(configValueForKey:(NSString *)name + callback:(RCTResponseSenderBlock) callback) +{ + if (!self.remoteConfigInstance) { + NSDictionary *err = @{ + @"error": @"No configuration instance", + @"msg": @"No configuration instance set. Please call setDefaultRemoteConfig before using this feature" + }; + callback(@[err]); + } + + + FIRRemoteConfigValue *value = [self.remoteConfigInstance configValueForKey:name]; + NSString *valueStr = value.stringValue; + + if (valueStr == nil) { + valueStr = @""; + } + callback(@[[NSNull null], valueStr]); +} + +RCT_EXPORT_METHOD(fetchWithExpiration:(nonnull NSNumber*)expirationSeconds + callback:(RCTResponseSenderBlock) callback) +{ + if (!self.remoteConfigInstance) { + NSDictionary *err = @{ + @"error": @"No configuration instance", + @"msg": @"No configuration instance set. Please call setDefaultRemoteConfig before using this feature" + }; + callback(@[err]); + } + + NSTimeInterval expirationDuration = [expirationSeconds doubleValue]; + + [self.remoteConfigInstance fetchWithExpirationDuration:expirationDuration completionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) { + if (status == FIRRemoteConfigFetchStatusSuccess) { + NSLog(@"Config fetched!"); + [self.remoteConfigInstance activateFetched]; + callback(@[[NSNull null], @(YES)]); + } else { + NSLog(@"Error %@", error.localizedDescription); + + NSDictionary *err = @{ + @"error": @"No configuration instance", + @"msg": [error localizedDescription] + }; + + callback(@[err]); + } + }]; +} + +- (NSArray *)supportedEvents { + return @[]; +} + +@end diff --git a/lib/firestack.js b/lib/firestack.js index 8bcbbfa..64426a0 100644 --- a/lib/firestack.js +++ b/lib/firestack.js @@ -19,7 +19,7 @@ const FirestackModuleEvt = new NativeEventEmitter(FirestackModule); import promisify from './utils/promisify' import Singleton from './utils/singleton' -import RemoteConfig from './modules/remoteConfig' +import {RemoteConfig} from './modules/remoteConfig' import {Authentication} from './modules/authentication' import {Database} from './modules/database' import {Analytics} from './modules/analytics' @@ -41,8 +41,8 @@ export class Firestack extends Singleton { log.info('Creating new firestack instance'); - instance._remoteConfig = instance.options.remoteConfig || {}; - delete instance.options.remoteConfig; + this._remoteConfigOpts = instance._remoteConfigOpts = instance.options.defaultConfig || {}; + delete instance.options.defaultConfig; instance.configured = instance.options.configure || false; instance.auth = null; @@ -122,14 +122,10 @@ export class Firestack extends Singleton { return promisify('serverValue', FirestackModule)(); } - /** - * remote config - */ + // RemoteConfig get remoteConfig() { - if (!this.remoteConfig) { - this.remoteConfig = new RemoteConfig(this._remoteConfig); - } - return this.remoteConfig; + if (!this._remoteConfig) { this._remoteConfig = new RemoteConfig(this._remoteConfigOpts);} + return this._remoteConfig; } /** diff --git a/lib/modules/remoteConfig.js b/lib/modules/remoteConfig.js index 385caf5..0e6a0e4 100644 --- a/lib/modules/remoteConfig.js +++ b/lib/modules/remoteConfig.js @@ -1,30 +1,29 @@ +import {NativeModules, NativeAppEventEmitter} from 'react-native'; +const FirestackRemoteConfig = NativeModules.FirestackRemoteConfig; + +import promisify from '../utils/promisify'; /** * Configuration class */ const defaultExpiration = 60 * 60 * 24; // one day export class RemoteConfig { - constructor(options) { - this.config = options || {}; - - this.setDefaultRemoteConfig(options) + constructor(defaultConfig) { + this.defaultConfig = defaultConfig || {}; + this.setDefaultRemoteConfig(defaultConfig, process.env.NODE_ENV === 'development') .then(() => this.configured = true); } - setDefaultRemoteConfig(options) { - return promisify('setDefaultRemoteConfig')(options); + setDefaultRemoteConfig(options, devMode=false) { + return promisify('setDefaultRemoteConfig', FirestackRemoteConfig)(options, devMode) } fetchWithExpiration(expirationSeconds=defaultExpiration) { - return promisify('fetchWithExpiration')(expirationSeconds) + return promisify('fetchWithExpiration', FirestackRemoteConfig)(expirationSeconds) } config(name) { - return promisify('configValueForKey')(name); - } - - setDev() { - return promisify('setDev')(); + return promisify('configValueForKey', FirestackRemoteConfig)(name); } } -export default RemoteConfig; \ No newline at end of file +export default RemoteConfig;