From a971038ef24c85a608a3bea31959bd4f07d74eb9 Mon Sep 17 00:00:00 2001
From: Jean Silva <jeanmsilva89@gmail.com>
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 = "<group>"; };
+		544B47051DDE647E0057E78B /* FirestackRemoteConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirestackRemoteConfig.h; path = Firestack/FirestackRemoteConfig.h; sourceTree = "<group>"; };
 		D90882D41D89C18C00FB6742 /* FirestackCloudMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirestackCloudMessaging.h; path = Firestack/FirestackCloudMessaging.h; sourceTree = "<group>"; };
 		D90882D51D89C18C00FB6742 /* FirestackCloudMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirestackCloudMessaging.m; path = Firestack/FirestackCloudMessaging.m; sourceTree = "<group>"; };
 		D950369C1D19C77400F7094D /* Firestack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Firestack.h; path = Firestack/Firestack.h; sourceTree = "<group>"; };
@@ -92,6 +95,8 @@
 				D96290841D6D28B80099A3EC /* FirestackDatabase.m */,
 				D9D62E7A1D6D86FD003D826D /* FirestackStorage.h */,
 				D9D62E7B1D6D86FD003D826D /* FirestackStorage.m */,
+				544B47031DDE64610057E78B /* FirestackRemoteConfig.m */,
+				544B47051DDE647E0057E78B /* FirestackRemoteConfig.h */,
 			);
 			name = Modules;
 			sourceTree = "<group>";
@@ -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 <RCTBridgeModule> {
+    
+}
+
+@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<NSString *> *)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;