diff --git a/android/src/main/java/io/invertase/firebase/RNFirebaseModule.java b/android/src/main/java/io/invertase/firebase/RNFirebaseModule.java index 04589a15..c28255e6 100644 --- a/android/src/main/java/io/invertase/firebase/RNFirebaseModule.java +++ b/android/src/main/java/io/invertase/firebase/RNFirebaseModule.java @@ -7,6 +7,7 @@ import java.util.HashMap; // react import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.LifecycleEventListener; @@ -17,6 +18,8 @@ import com.facebook.react.bridge.ReactMethod; // play services import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; @SuppressWarnings("WeakerAccess") public class RNFirebaseModule extends ReactContextBaseJavaModule implements LifecycleEventListener { @@ -45,9 +48,22 @@ public class RNFirebaseModule extends ReactContextBaseJavaModule implements Life } @ReactMethod - public void initializeApp(String name, ReadableMap options) { - // todo https://firebase.google.com/docs/reference/android/com/google/firebase/FirebaseOptions + public void initializeApp(String name, ReadableMap options, Callback callback) { + FirebaseOptions.Builder builder = new FirebaseOptions.Builder(); + builder.setApplicationId(options.getString("androidAppId")); + builder.setGcmSenderId(options.getString("messagingSenderId")); + builder.setApiKey(options.getString("apiKey")); + builder.setProjectId(options.getString("projectId")); + builder.setDatabaseUrl(options.getString("databaseURL")); + builder.setStorageBucket(options.getString("storageBucket")); + + FirebaseApp.initializeApp(getReactApplicationContext(), builder.build(), name); + + // todo expand on callback result + WritableMap response = Arguments.createMap(); + response.putString("result", "success"); + callback.invoke(null, response); } private WritableMap getPlayServicesStatus() { diff --git a/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java b/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java index 3aa2b8c5..682d76e5 100644 --- a/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java +++ b/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java @@ -4,8 +4,8 @@ import android.util.Log; import android.net.Uri; import android.support.annotation.NonNull; +import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -24,6 +24,7 @@ import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; +import com.google.firebase.FirebaseApp; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException; @@ -46,14 +47,16 @@ import io.invertase.firebase.Utils; class RNFirebaseAuth extends ReactContextBaseJavaModule { private static final String TAG = "RNFirebaseAuth"; + // itts been a while ;p + + private ReactContext mReactContext; - private FirebaseAuth mAuth; - private Map mAuthListeners; + private HashMap mAuthListeners = new HashMap<>(); + RNFirebaseAuth(ReactApplicationContext reactContext) { super(reactContext); mReactContext = reactContext; - mAuth = FirebaseAuth.getInstance(); Log.d(TAG, "RNFirebaseAuth:initialized"); } @@ -68,6 +71,10 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { @ReactMethod public void addAuthStateListener(final String appName) { Log.d(TAG, "addAuthStateListener"); + + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + FirebaseAuth.AuthStateListener mAuthListener = mAuthListeners.get(appName); if (mAuthListener == null) { FirebaseAuth.AuthStateListener newAuthListener = new FirebaseAuth.AuthStateListener() { @@ -87,7 +94,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { } }; - mAuth.addAuthStateListener(newAuthListener); + firebaseAuth.addAuthStateListener(newAuthListener); mAuthListeners.put(appName, newAuthListener); } } @@ -98,10 +105,15 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { @ReactMethod public void removeAuthStateListener(String appName) { Log.d(TAG, "removeAuthStateListener"); + + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + FirebaseAuth.AuthStateListener mAuthListener = mAuthListeners.get(appName); if (mAuthListener != null) { - mAuth.removeAuthStateListener(mAuthListener); + firebaseAuth.removeAuthStateListener(mAuthListener); + mAuthListeners.remove(appName); } } @@ -111,12 +123,15 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void signOut(final Promise promise) { + public void signOut(String appName, Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + Log.d(TAG, "signOut"); - if (mAuth == null || mAuth.getCurrentUser() == null) { + if (firebaseAuth == null || firebaseAuth.getCurrentUser() == null) { promiseNoUser(promise, true); } else { - mAuth.signOut(); + firebaseAuth.signOut(); promiseNoUser(promise, false); } } @@ -127,9 +142,12 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void signInAnonymously(final Promise promise) { + public void signInAnonymously(String appName, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + Log.d(TAG, "signInAnonymously"); - mAuth.signInAnonymously() + firebaseAuth.signInAnonymously() .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(AuthResult authResult) { @@ -154,9 +172,12 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void createUserWithEmailAndPassword(final String email, final String password, final Promise promise) { + public void createUserWithEmailAndPassword(String appName, final String email, final String password, final Promise promise) { Log.d(TAG, "createUserWithEmailAndPassword"); - mAuth.createUserWithEmailAndPassword(email, password) + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + firebaseAuth.createUserWithEmailAndPassword(email, password) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(AuthResult authResult) { @@ -181,9 +202,12 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void signInWithEmailAndPassword(final String email, final String password, final Promise promise) { + public void signInWithEmailAndPassword(String appName, final String email, final String password, final Promise promise) { Log.d(TAG, "signInWithEmailAndPassword"); - mAuth.signInWithEmailAndPassword(email, password) + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + firebaseAuth.signInWithEmailAndPassword(email, password) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(AuthResult authResult) { @@ -208,9 +232,12 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void signInWithCustomToken(final String token, final Promise promise) { + public void signInWithCustomToken(String appName, final String token, final Promise promise) { Log.d(TAG, "signInWithCustomToken"); - mAuth.signInWithCustomToken(token) + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + firebaseAuth.signInWithCustomToken(token) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(AuthResult authResult) { @@ -234,9 +261,12 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void sendPasswordResetEmail(final String email, final Promise promise) { + public void sendPasswordResetEmail(String appName, final String email, final Promise promise) { Log.d(TAG, "sendPasswordResetEmail"); - mAuth.sendPasswordResetEmail(email) + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + firebaseAuth.sendPasswordResetEmail(email) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -259,8 +289,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void getCurrentUser(final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void getCurrentUser(String appName, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "getCurrentUser"); if (user == null) { promiseNoUser(promise, false); @@ -279,8 +312,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void delete(final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void delete(String appName, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "delete"); if (user != null) { user.delete() @@ -309,8 +345,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void reload(final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void reload(String appName, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "reload"); if (user == null) { @@ -323,7 +362,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "reload:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "reload:onComplete:failure", exception); @@ -340,8 +379,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void sendEmailVerification(final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void sendEmailVerification(String appName, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "sendEmailVerification"); if (user == null) { @@ -354,7 +396,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "sendEmailVerification:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "sendEmailVerification:onComplete:failure", exception); @@ -372,8 +414,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void updateEmail(final String email, final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void updateEmail(String appName, final String email, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "updateEmail"); if (user == null) { @@ -386,7 +431,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "updateEmail:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "updateEmail:onComplete:failure", exception); @@ -404,8 +449,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void updatePassword(final String password, final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void updatePassword(String appName, final String password, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "updatePassword"); if (user == null) { @@ -418,7 +466,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "updatePassword:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "updatePassword:onComplete:failure", exception); @@ -436,8 +484,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void updateProfile(ReadableMap props, final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); + public void updateProfile(String appName, ReadableMap props, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "updateProfile"); if (user == null) { @@ -465,7 +516,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "updateProfile:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "updateProfile:onComplete:failure", exception); @@ -485,14 +536,17 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void signInWithCredential(final String provider, final String authToken, final String authSecret, final Promise promise) { + public void signInWithCredential(String appName, String provider, String authToken, String authSecret, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + AuthCredential credential = getCredentialForProvider(provider, authToken, authSecret); if (credential == null) { promise.reject("auth/invalid-credential", "The supplied auth credential is malformed, has expired or is not currently supported."); } else { Log.d(TAG, "signInWithCredential"); - mAuth.signInWithCredential(credential) + firebaseAuth.signInWithCredential(credential) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -518,13 +572,16 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void link(final String provider, final String authToken, final String authSecret, final Promise promise) { + public void link(String appName, String provider, String authToken, String authSecret, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + AuthCredential credential = getCredentialForProvider(provider, authToken, authSecret); if (credential == null) { promise.reject("auth/invalid-credential", "The supplied auth credential is malformed, has expired or is not currently supported."); } else { - FirebaseUser user = mAuth.getCurrentUser(); + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "link"); if (user != null) { @@ -557,13 +614,16 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void reauthenticate(final String provider, final String authToken, final String authSecret, final Promise promise) { + public void reauthenticate(String appName, String provider, String authToken, String authSecret, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + AuthCredential credential = getCredentialForProvider(provider, authToken, authSecret); if (credential == null) { promise.reject("auth/invalid-credential", "The supplied auth credential is malformed, has expired or is not currently supported."); } else { - FirebaseUser user = mAuth.getCurrentUser(); + FirebaseUser user = firebaseAuth.getCurrentUser(); Log.d(TAG, "reauthenticate"); if (user != null) { @@ -573,7 +633,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "reauthenticate:onComplete:success"); - promiseWithUser(mAuth.getCurrentUser(), promise); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); } else { Exception exception = task.getException(); Log.e(TAG, "reauthenticate:onComplete:failure", exception); @@ -595,7 +655,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param authSecret * @return */ - public AuthCredential getCredentialForProvider(String provider, String authToken, String authSecret) { + private AuthCredential getCredentialForProvider(String provider, String authToken, String authSecret) { switch (provider) { case "facebook": return FacebookAuthProvider.getCredential(authToken); @@ -618,12 +678,15 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void getToken(final Boolean forceRefresh, final Promise promise) { - FirebaseUser user = mAuth.getCurrentUser(); - Log.d(TAG, "getToken"); + public void getToken(String appName, Boolean forceRefresh, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + + FirebaseUser user = firebaseAuth.getCurrentUser(); + Log.d(TAG, "getToken/getIdToken"); if (user != null) { - user.getToken(forceRefresh) + user.getIdToken(forceRefresh) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -648,10 +711,13 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void fetchProvidersForEmail(final String email, final Promise promise) { + public void fetchProvidersForEmail(String appName, String email, final Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + Log.d(TAG, "fetchProvidersForEmail"); - mAuth.fetchProvidersForEmail(email) + firebaseAuth.fetchProvidersForEmail(email) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { diff --git a/android/src/main/java/io/invertase/firebase/config/RNFirebaseRemoteConfig.java b/android/src/main/java/io/invertase/firebase/config/RNFirebaseRemoteConfig.java index 3300a2cd..3e1e0c41 100644 --- a/android/src/main/java/io/invertase/firebase/config/RNFirebaseRemoteConfig.java +++ b/android/src/main/java/io/invertase/firebase/config/RNFirebaseRemoteConfig.java @@ -1,33 +1,30 @@ package io.invertase.firebase.config; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.Log; -import com.facebook.react.bridge.Arguments; +import com.google.android.gms.tasks.Task; import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.WritableArray; +import com.google.android.gms.tasks.OnCompleteListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.Task; import com.google.firebase.remoteconfig.FirebaseRemoteConfig; -import com.google.firebase.remoteconfig.FirebaseRemoteConfigFetchException; -import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings; import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue; +import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings; -import java.lang.reflect.Array; -import java.util.List; import java.util.Map; import java.util.Set; +import java.util.List; import io.invertase.firebase.Utils; -public class RNFirebaseRemoteConfig extends ReactContextBaseJavaModule { +class RNFirebaseRemoteConfig extends ReactContextBaseJavaModule { private static final String TAG = "RNFirebaseRemoteConfig"; @@ -37,7 +34,7 @@ public class RNFirebaseRemoteConfig extends ReactContextBaseJavaModule { private static final String NUMBER_VALUE = "numberValue"; private static final String SOURCE = "source"; - public RNFirebaseRemoteConfig(ReactApplicationContext reactContext) { + RNFirebaseRemoteConfig(ReactApplicationContext reactContext) { super(reactContext); Log.d(TAG, "New instance"); } @@ -51,7 +48,7 @@ public class RNFirebaseRemoteConfig extends ReactContextBaseJavaModule { } @ReactMethod - public void enableDeveloperMode() { + public void enableDeveloperMode(String appName) { FirebaseRemoteConfigSettings.Builder settings = new FirebaseRemoteConfigSettings.Builder(); settings.setDeveloperModeEnabled(true); FirebaseRemoteConfig.getInstance().setConfigSettings(settings.build()); diff --git a/ios/RNFirebase/admob/RNFirebaseAdMob.m b/ios/RNFirebase/admob/RNFirebaseAdMob.m index 398f38fd..c8440507 100644 --- a/ios/RNFirebase/admob/RNFirebaseAdMob.m +++ b/ios/RNFirebase/admob/RNFirebaseAdMob.m @@ -2,7 +2,6 @@ #if __has_include() -#import "GoogleMobileAds/GADMobileAds.h" #import "RNFirebaseAdMobInterstitial.h" #import "RNFirebaseAdMobRewardedVideo.h" diff --git a/ios/RNFirebase/auth/RNFirebaseAuth.m b/ios/RNFirebase/auth/RNFirebaseAuth.m index 1126cdf6..923694d1 100644 --- a/ios/RNFirebase/auth/RNFirebaseAuth.m +++ b/ios/RNFirebase/auth/RNFirebaseAuth.m @@ -16,17 +16,17 @@ RCT_EXPORT_METHOD(addAuthStateListener: (NSString *) appName) { FIRApp *firApp = [FIRApp appNamed:appName]; // todo -// FIRAuthStateDidChangeListenerHandle *listenerBlock = [authStateHandlers valueForKey:appName]; -// -// if (!listenerBlock) { -// FIRAuthStateDidChangeListenerHandle *newlistenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) { -// if (user != nil) { -// [self sendJSEventWithAppName:appName title:AUTH_CHANGED_EVENT props:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; -// } else { -// [self sendJSEventWithAppName:appName title:AUTH_CHANGED_EVENT props:@{@"authenticated": @(false)}]; -// } -// }]; -// } + // FIRAuthStateDidChangeListenerHandle *listenerBlock = [authStateHandlers valueForKey:appName]; + // + // if (!listenerBlock) { + // FIRAuthStateDidChangeListenerHandle *newlistenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) { + // if (user != nil) { + // [self sendJSEventWithAppName:appName title:AUTH_CHANGED_EVENT props:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; + // } else { + // [self sendJSEventWithAppName:appName title:AUTH_CHANGED_EVENT props:@{@"authenticated": @(false)}]; + // } + // }]; + // } } /** @@ -42,7 +42,6 @@ RCT_EXPORT_METHOD(removeAuthStateListener: } } -// TODO refactor remaining methods to accept appName arg - just testing listeners for now /** signOut @@ -52,14 +51,18 @@ RCT_EXPORT_METHOD(removeAuthStateListener: @return */ RCT_EXPORT_METHOD(signOut: - (RCTPromiseResolveBlock) resolve + (NSString *) appName + resolver: + (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRUser *user = [FIRAuth auth].currentUser; if (user) { NSError *error; - [[FIRAuth auth] signOut:&error]; + [[FIRAuth authWithApp:firApp] signOut:&error]; if (!error) [self promiseNoUser:resolve rejecter:reject isError:NO]; else [self promiseRejectAuthException:reject error:error]; } else { @@ -76,10 +79,14 @@ RCT_EXPORT_METHOD(signOut: @return */ RCT_EXPORT_METHOD(signInAnonymously: - (RCTPromiseResolveBlock) resolve + (NSString *) appName + resolver: + (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -99,14 +106,18 @@ RCT_EXPORT_METHOD(signInAnonymously: @return return */ RCT_EXPORT_METHOD(signInWithEmailAndPassword: - (NSString *) email + (NSString *) appName + email: + (NSString *) email pass: (NSString *) password resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -125,14 +136,18 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword: @return return */ RCT_EXPORT_METHOD(createUserWithEmailAndPassword: - (NSString *) email + (NSString *) appName + email: + (NSString *) email pass: (NSString *) password resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -149,10 +164,13 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword: @return return */ RCT_EXPORT_METHOD(delete: - (RCTPromiseResolveBlock) resolve + (NSString *) appName + resolver: + (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user deleteWithCompletion:^(NSError *_Nullable error) { @@ -175,17 +193,21 @@ RCT_EXPORT_METHOD(delete: @return return */ RCT_EXPORT_METHOD(reload: - (RCTPromiseResolveBlock) resolve + (NSString *) appName + resolver: + (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user reloadWithCompletion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterReload = [FIRAuth auth].currentUser; + FIRUser *userAfterReload = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterReload]; } }]; @@ -202,17 +224,20 @@ RCT_EXPORT_METHOD(reload: @return return */ RCT_EXPORT_METHOD(sendEmailVerification: - (RCTPromiseResolveBlock) resolve + (NSString *) appName + resolver: + (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user sendEmailVerificationWithCompletion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterUpdate = [FIRAuth auth].currentUser; + FIRUser *userAfterUpdate = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate]; } }]; @@ -230,19 +255,22 @@ RCT_EXPORT_METHOD(sendEmailVerification: @return return */ RCT_EXPORT_METHOD(updateEmail: - (NSString *) email + (NSString *) appName + email: + (NSString *) email resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user updateEmail:email completion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterUpdate = [FIRAuth auth].currentUser; + FIRUser *userAfterUpdate = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate]; } }]; @@ -260,11 +288,15 @@ RCT_EXPORT_METHOD(updateEmail: @return return */ RCT_EXPORT_METHOD(updatePassword: - (NSString *) password + (NSString *) appName + password: + (NSString *) password resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRUser *user = [FIRAuth auth].currentUser; if (user) { @@ -272,7 +304,7 @@ RCT_EXPORT_METHOD(updatePassword: if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterUpdate = [FIRAuth auth].currentUser; + FIRUser *userAfterUpdate = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate]; } }]; @@ -290,12 +322,16 @@ RCT_EXPORT_METHOD(updatePassword: @return return */ RCT_EXPORT_METHOD(updateProfile: - (NSDictionary *) props + (NSString *) appName + props: + (NSDictionary *) props resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { FIRUserProfileChangeRequest *changeRequest = [user profileChangeRequest]; @@ -318,7 +354,7 @@ RCT_EXPORT_METHOD(updateProfile: if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterUpdate = [FIRAuth auth].currentUser; + FIRUser *userAfterUpdate = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate]; } }]; @@ -327,7 +363,6 @@ RCT_EXPORT_METHOD(updateProfile: } } - /** getToken @@ -336,15 +371,19 @@ RCT_EXPORT_METHOD(updateProfile: @return */ RCT_EXPORT_METHOD(getToken: - (BOOL) forceRefresh + (NSString *) appName + forceRefresh: + (BOOL) forceRefresh resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { - [user getTokenForcingRefresh:(BOOL) forceRefresh completion:^(NSString *token, NSError *_Nullable error) { + [user getIDTokenForcingRefresh:(BOOL) forceRefresh completion:^(NSString *token, NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -367,7 +406,9 @@ RCT_EXPORT_METHOD(getToken: @return */ RCT_EXPORT_METHOD(signInWithCredential: - (NSString *) provider + (NSString *) appName + provider: + (NSString *) provider token: (NSString *) authToken secret: @@ -376,13 +417,15 @@ RCT_EXPORT_METHOD(signInWithCredential: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; if (credential == nil) { return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil); } - [[FIRAuth auth] signInWithCredential:credential completion:^(FIRUser *user, NSError *error) { + [[FIRAuth authWithApp:firApp] signInWithCredential:credential completion:^(FIRUser *user, NSError *error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -399,13 +442,15 @@ RCT_EXPORT_METHOD(signInWithCredential: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(sendPasswordResetEmail: - (NSString *) email +RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName + email:(NSString *) email resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] sendPasswordResetWithEmail:email completion:^(NSError *_Nullable error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email completion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -421,11 +466,13 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(getCurrentUser: - (RCTPromiseResolveBlock) resolve +RCT_EXPORT_METHOD(getCurrentUser:(NSString *) appName + resolver:(RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRUser *user = [FIRAuth auth].currentUser; + FIRApp *firApp = [FIRApp appNamed:appName]; + + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:user]; } @@ -437,13 +484,15 @@ RCT_EXPORT_METHOD(getCurrentUser: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(signInWithCustomToken: - (NSString *) customToken +RCT_EXPORT_METHOD(signInWithCustomToken:(NSString *) appName + customToken:(NSString *) customToken resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { @@ -462,8 +511,8 @@ RCT_EXPORT_METHOD(signInWithCustomToken: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(link: - (NSString *) provider +RCT_EXPORT_METHOD(link:(NSString *) appName + provider:(NSString *) provider authToken: (NSString *) authToken authSecret: @@ -472,13 +521,15 @@ RCT_EXPORT_METHOD(link: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; if (credential == nil) { return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil); } - FIRUser *user = [FIRAuth auth].currentUser; + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user linkWithCredential:credential completion:^(FIRUser *_Nullable _user, NSError *_Nullable error) { @@ -503,8 +554,8 @@ RCT_EXPORT_METHOD(link: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(reauthenticate: - (NSString *) provider +RCT_EXPORT_METHOD(reauthenticate:(NSString *) appName + provider:(NSString *) provider authToken: (NSString *) authToken authSecret: @@ -513,20 +564,22 @@ RCT_EXPORT_METHOD(reauthenticate: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { + FIRApp *firApp = [FIRApp appNamed:appName]; + FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; if (credential == nil) { return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil); } - FIRUser *user = [FIRAuth auth].currentUser; + FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { [user reauthenticateWithCredential:credential completion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { - FIRUser *userAfterAuth = [FIRAuth auth].currentUser; + FIRUser *userAfterAuth = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterAuth]; } }]; @@ -543,13 +596,15 @@ RCT_EXPORT_METHOD(reauthenticate: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(fetchProvidersForEmail: - (NSString *) email +RCT_EXPORT_METHOD(fetchProvidersForEmail:(NSString *) appName + email:(NSString *) email resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - [[FIRAuth auth] fetchProvidersForEmail:email completion:^(NSArray *_Nullable providers, NSError *_Nullable error) { + FIRApp *firApp = [FIRApp appNamed:appName]; + + [[FIRAuth authWithApp:firApp] fetchProvidersForEmail:email completion:^(NSArray *_Nullable providers, NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else if (!providers) { diff --git a/lib/firebase.js b/lib/firebase.js index 112b28bd..3ff6d556 100644 --- a/lib/firebase.js +++ b/lib/firebase.js @@ -53,7 +53,10 @@ class FirebaseCore { if (!INTERNALS.APPS[_name]) { INTERNALS.APPS[_name] = new FirebaseApp(_name, options); - INTERNALS.APPS[_name]._initializeApp(); + // only initialize if certain props are available + if (options.databaseURL && options.apiKey) { + INTERNALS.APPS[_name]._initializeApp(); + } } return INTERNALS.APPS[_name]; diff --git a/lib/internals.js b/lib/internals.js index 3d7fd96b..196d0c2a 100644 --- a/lib/internals.js +++ b/lib/internals.js @@ -1,6 +1,7 @@ import EventEmitter from 'EventEmitter'; +import { Platform } from 'react-native'; -const DEFAULT_APP_NAME = 'DEFAULT'; +const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; // am still thinking ;p export default { diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 60cf667b..7eb42123 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -1,5 +1,4 @@ -import { NativeModules, NativeEventEmitter } from 'react-native'; -import { nativeSDKMissing } from './../../utils'; +import ModuleBase from './../../utils/ModuleBase'; import Interstitial from './Interstitial'; import RewardedVideo from './RewardedVideo'; @@ -7,23 +6,17 @@ import AdRequest from './AdRequest'; import VideoOptions from './VideoOptions'; import Banner from './Banner'; import NativeExpress from './NativeExpress'; -import { Base } from './../base'; -const FirebaseAdMob = NativeModules.RNFirebaseAdMob; -const FirebaseAdMobEvt = FirebaseAdMob && new NativeEventEmitter(FirebaseAdMob); -export default class Admob extends Base { - - constructor() { - super(); - if (!FirebaseAdMob) { - return nativeSDKMissing('admob'); - } +export default class Admob extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'AdMob', true); this._initialized = false; this._appId = null; - FirebaseAdMobEvt.addListener('interstitial_event', this._onInterstitialEvent.bind(this)); - FirebaseAdMobEvt.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); + + this._eventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this)); + this._eventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); } _onInterstitialEvent(event) { @@ -51,22 +44,20 @@ export default class Admob extends Base { initialize(appId: string) { if (this._initialized) { this.log.warn('AdMob has already been initialized!'); - return; + } else { + this._initialized = true; + this._appId = appId; + this._native.initialize(appId); } - - this._initialized = true; - this._appId = appId; - return FirebaseAdMob.initialize(appId); } openDebugMenu() { if (!this._initialized) { this.log.warn('AdMob needs to be initialized before opening the dev menu!'); - return; + } else { + this.log.info('Opening debug menu'); + this._native.openDebugMenu(this._appId); } - - this.log.info('Opening debug menu'); - return FirebaseAdMob.openDebugMenu(this._appId); } interstitial(adUnit: string) { @@ -80,10 +71,6 @@ export default class Admob extends Base { static get statics() { return statics; } - - get namespace(): string { - return 'firebase:admob'; - } } export const statics = { diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index 6255eaa8..23bf99da 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -1,8 +1,6 @@ // @flow -import { NativeModules } from 'react-native'; -import { nativeSDKMissing } from './../../utils'; +import ModuleBase from './../../utils/ModuleBase'; -const FirebaseAnalytics = NativeModules.RNFirebaseAnalytics; const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; const ReservedEventNames = [ @@ -21,11 +19,9 @@ const ReservedEventNames = [ 'user_engagement', ]; -export default class Analytics { - constructor() { - if (!FirebaseAnalytics) { - return nativeSDKMissing('analytics'); - } +export default class Analytics extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Analytics'); } /** @@ -54,7 +50,7 @@ export default class Analytics { // types are supported. String parameter values can be up to 36 characters long. The "firebase_" // prefix is reserved and should not be used for parameter names. - return FirebaseAnalytics.logEvent(name, params); + return this._native.logEvent(name, params); } /** @@ -62,7 +58,7 @@ export default class Analytics { * @param enabled */ setAnalyticsCollectionEnabled(enabled: boolean): void { - return FirebaseAnalytics.setAnalyticsCollectionEnabled(enabled); + return this._native.setAnalyticsCollectionEnabled(enabled); } /** @@ -71,7 +67,7 @@ export default class Analytics { * @param screenClassOverride */ setCurrentScreen(screenName: string, screenClassOverride: string): void { - return FirebaseAnalytics.setCurrentScreen(screenName, screenClassOverride); + return this._native.setCurrentScreen(screenName, screenClassOverride); } /** @@ -79,7 +75,7 @@ export default class Analytics { * @param milliseconds */ setMinimumSessionDuration(milliseconds: number = 10000): void { - return FirebaseAnalytics.setMinimumSessionDuration(milliseconds); + return this._native.setMinimumSessionDuration(milliseconds); } /** @@ -87,7 +83,7 @@ export default class Analytics { * @param milliseconds */ setSessionTimeoutDuration(milliseconds: number = 1800000): void { - return FirebaseAnalytics.setSessionTimeoutDuration(milliseconds); + return this._native.setSessionTimeoutDuration(milliseconds); } /** @@ -95,7 +91,7 @@ export default class Analytics { * @param id */ setUserId(id: string): void { - return FirebaseAnalytics.setUserId(id); + return this._native.setUserId(id); } /** @@ -104,20 +100,17 @@ export default class Analytics { * @param value */ setUserProperty(name: string, value: string): void { - return FirebaseAnalytics.setUserProperty(name, value); + return this._native.setUserProperty(name, value); } /** * Sets a user property to a given value. + * @RNFirebaseSpecific * @param object */ setUserProperties(object: Object): void { for (const property of Object.keys(object)) { - FirebaseAnalytics.setUserProperty(property, object[property]); + this._native.setUserProperty(property, object[property]); } } - - get namespace(): string { - return 'firebase:analytics'; - } } diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 706c1ab2..deb77620 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -1,6 +1,4 @@ // @flow -import { NativeModules, NativeEventEmitter } from 'react-native'; - import User from './user'; import ModuleBase from './../../utils/ModuleBase'; @@ -11,15 +9,13 @@ import FacebookAuthProvider from './providers/Facebook'; import TwitterAuthProvider from './providers/Twitter'; import GithubAuthProvider from './providers/Github'; -const FirebaseAuth = NativeModules.RNFirebaseAuth; - export default class Auth extends ModuleBase { _user: User | null; _authResult: AuthResultType | null; authenticated: boolean; constructor(firebaseApp: Object, options: Object = {}) { - super(firebaseApp, options, 'auth'); + super(firebaseApp, options, 'Auth'); this._user = null; this._authResult = null; this.authenticated = false; @@ -39,7 +35,7 @@ export default class Auth extends ModuleBase { if (auth && auth.user && !this._user) this._user = new User(this, auth); else if ((!auth || !auth.user) && this._user) this._user = null; else if (this._user) this._user._updateValues(auth); - if (emit) this.emit('onAuthStateChanged', this._user); + if (emit) this.emit(`${this._appName}-onAuthStateChanged`, this._user); return auth ? this._user : null; } @@ -89,7 +85,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ signOut(): Promise { - return this._interceptUserValue(FirebaseAuth.signOut()); + return this._interceptUserValue(this._native.signOut()); } /** @@ -97,7 +93,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise resolved upon completion */ signInAnonymously(): Promise { - return this._interceptUserValue(FirebaseAuth.signInAnonymously()); + return this._interceptUserValue(this._native.signInAnonymously()); } /** @@ -107,7 +103,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise indicating the completion */ createUserWithEmailAndPassword(email: string, password: string): Promise { - return this._interceptUserValue(FirebaseAuth.createUserWithEmailAndPassword(email, password)); + return this._interceptUserValue(this._native.createUserWithEmailAndPassword(email, password)); } /** @@ -117,7 +113,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise that is resolved upon completion */ signInWithEmailAndPassword(email: string, password: string): Promise { - return this._interceptUserValue(FirebaseAuth.signInWithEmailAndPassword(email, password)); + return this._interceptUserValue(this._native.signInWithEmailAndPassword(email, password)); } /** @@ -126,7 +122,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise resolved upon completion */ signInWithCustomToken(customToken: string): Promise { - return this._interceptUserValue(FirebaseAuth.signInWithCustomToken(customToken)); + return this._interceptUserValue(this._native.signInWithCustomToken(customToken)); } /** @@ -134,7 +130,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise resolved upon completion */ signInWithCredential(credential: CredentialType): Promise { - return this._interceptUserValue(FirebaseAuth.signInWithCredential(credential.provider, credential.token, credential.secret)); + return this._interceptUserValue(this._native.signInWithCredential(credential.provider, credential.token, credential.secret)); } /** @@ -142,7 +138,7 @@ export default class Auth extends ModuleBase { * @param {string} email The email to send password reset instructions */ sendPasswordResetEmail(email: string): Promise { - return FirebaseAuth.sendPasswordResetEmail(email); + return this._native.sendPasswordResetEmail(email); } /** @@ -150,7 +146,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ getCurrentUser(): Promise { - return this._interceptUserValue(FirebaseAuth.getCurrentUser()); + return this._interceptUserValue(this._native.getCurrentUser()); } /** @@ -158,7 +154,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ fetchProvidersForEmail(email: string): Promise> { - return FirebaseAuth.fetchProvidersForEmail(email); + return this._native.fetchProvidersForEmail(email); } /** diff --git a/lib/modules/auth/user.js b/lib/modules/auth/user.js index 4aa99645..e2b784ac 100644 --- a/lib/modules/auth/user.js +++ b/lib/modules/auth/user.js @@ -1,8 +1,3 @@ -import { NativeModules } from 'react-native'; - -const FirebaseAuth = NativeModules.RNFirebaseAuth; - - /** * @url https://firebase.google.com/docs/reference/js/firebase.User */ @@ -106,7 +101,7 @@ export default class User { * @return {Promise} */ delete(): Promise { - return this._auth._interceptUserValue(FirebaseAuth.delete()); + return this._auth._interceptUserValue(this._auth._native.delete()); } /** @@ -114,7 +109,7 @@ export default class User { * @param credential */ linkWithCredential(credential: CredentialType) { - return this._auth._interceptUserValue(FirebaseAuth.link(credential.provider, credential.token, credential.secret)); + return this._auth._interceptUserValue(this._auth._native.link(credential.provider, credential.token, credential.secret)); } /** @@ -122,7 +117,7 @@ export default class User { * @return {Promise} A promise resolved upon completion */ reauthenticateWithCredential(credential: CredentialType) { - return this._auth._interceptUserValue(FirebaseAuth.reauthenticate(credential.provider, credential.token, credential.secret)); + return this._auth._interceptUserValue(this._auth._native.reauthenticate(credential.provider, credential.token, credential.secret)); } /** @@ -130,7 +125,7 @@ export default class User { * @return {Promise} */ reload(): Promise { - return this._auth._interceptUserValue(FirebaseAuth.reload()); + return this._auth._interceptUserValue(this._auth._native.reload()); } /** @@ -140,7 +135,7 @@ export default class User { */ getToken(forceRefresh: Boolean = false): Promise { console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.'); - return FirebaseAuth.getToken(forceRefresh); + return this._auth._native.getToken(forceRefresh); } /** @@ -148,7 +143,7 @@ export default class User { * @return {Promise} */ getIdToken(forceRefresh: Boolean = false): Promise { - return FirebaseAuth.getToken(forceRefresh); + return this._auth._native.getToken(forceRefresh); } /** @@ -166,7 +161,7 @@ export default class User { * @return {Promise} A promise resolved upon completion */ updateEmail(email: string): Promise { - return this._auth._interceptUserValue(FirebaseAuth.updateEmail(email)); + return this._auth._interceptUserValue(this._auth._native.updateEmail(email)); } /** @@ -175,7 +170,7 @@ export default class User { * @return {Promise} */ updateProfile(updates: Object = {}): Promise { - return this._auth._interceptUserValue(FirebaseAuth.updateProfile(updates)); + return this._auth._interceptUserValue(this._auth._native.updateProfile(updates)); } /** @@ -184,13 +179,13 @@ export default class User { * @return {Promise} */ updatePassword(password: string): Promise { - return this._auth._interceptUserValue(FirebaseAuth.updatePassword(password)); + return this._auth._interceptUserValue(this._auth._native.updatePassword(password)); } /** * Send verification email to current user. */ sendEmailVerification(): Promise { - return this._auth._interceptUserValue(FirebaseAuth.sendEmailVerification()); + return this._auth._interceptUserValue(this._auth._native.sendEmailVerification()); } } diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index 19ac9cfc..67c160a7 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -1,26 +1,14 @@ /** * @flow */ -import { NativeModules } from 'react-native'; - -import { Base } from './../base'; -import { nativeSDKMissing } from './../../utils'; - -const FirebaseRemoteConfig = NativeModules.RNFirebaseRemoteConfig; - -type RemoteConfigOptions = {} +import ModuleBase from './../../utils/ModuleBase'; /** * @class Config */ -export default class RemoteConfig extends Base { - constructor(firebase: Object, options: RemoteConfigOptions = {}) { - super(firebase, options); - if (!FirebaseRemoteConfig) { - return nativeSDKMissing('remote config'); - } - - this.namespace = 'firebase:config'; +export default class RemoteConfig extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Config'); this.developerModeEnabled = false; } @@ -48,7 +36,7 @@ export default class RemoteConfig extends Base { enableDeveloperMode() { if (!this.developerModeEnabled) { this.log.debug('Enabled developer mode'); - FirebaseRemoteConfig.enableDeveloperMode(); + this._native.enableDeveloperMode(); this.developerModeEnabled = true; } } @@ -61,10 +49,10 @@ export default class RemoteConfig extends Base { fetch(expiration?: number) { if (expiration !== undefined) { this.log.debug(`Fetching remote config data with expiration ${expiration.toString()}`); - return FirebaseRemoteConfig.fetchWithExpirationDuration(expiration); + return this._native.fetchWithExpirationDuration(expiration); } this.log.debug('Fetching remote config data'); - return FirebaseRemoteConfig.fetch(); + return this._native.fetch(); } /** @@ -75,7 +63,7 @@ export default class RemoteConfig extends Base { */ activateFetched() { this.log.debug('Activating remote config'); - return FirebaseRemoteConfig.activateFetched(); + return this._native.activateFetched(); } /** @@ -92,7 +80,7 @@ export default class RemoteConfig extends Base { * } */ getValue(key: String) { - return FirebaseRemoteConfig + return this._native .getValue(key || '') .then(this._nativeValueToJS); } @@ -112,10 +100,10 @@ export default class RemoteConfig extends Base { * } */ getValues(keys: Array) { - return FirebaseRemoteConfig + return this._native .getValues(keys || []) .then((nativeValues) => { - const values:{[String]: Object} = {}; + const values: { [String]: Object } = {}; for (let i = 0, len = keys.length; i < len; i++) { values[keys[i]] = this._nativeValueToJS(nativeValues[i]); } @@ -129,7 +117,7 @@ export default class RemoteConfig extends Base { * @returns {*|Promise.>} */ getKeysByPrefix(prefix?: String) { - return FirebaseRemoteConfig.getKeysByPrefix(prefix); + return this._native.getKeysByPrefix(prefix); } /** @@ -137,7 +125,7 @@ export default class RemoteConfig extends Base { * @param defaults: A dictionary mapping a String key to a Object values. */ setDefaults(defaults: Object) { - FirebaseRemoteConfig.setDefaults(defaults); + this._native.setDefaults(defaults); } /** @@ -145,6 +133,6 @@ export default class RemoteConfig extends Base { * @param resource: The plist file name or resource ID */ setDefaultsFromResource(resource: String | number) { - FirebaseRemoteConfig.setDefaultsFromResource(resource); + this._native.setDefaultsFromResource(resource); } } diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 2b36553f..7ed078db 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -1,14 +1,9 @@ // @flow -import { NativeModules } from 'react-native'; -import { nativeSDKMissing } from './../../utils'; +import ModuleBase from './../../utils/ModuleBase'; -const FirebaseCrash = NativeModules.RNFirebaseCrash; - -export default class Crash { - constructor() { - if (!FirebaseCrash) { - return nativeSDKMissing('crash'); - } +export default class Crash extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Crash'); } /** @@ -16,7 +11,7 @@ export default class Crash { * @param enabled */ setCrashCollectionEnabled(enabled: boolean): void { - FirebaseCrash.setCrashCollectionEnabled(enabled); + this._native.setCrashCollectionEnabled(enabled); } /** @@ -24,16 +19,15 @@ export default class Crash { * @returns {Promise.} */ isCrashCollectionEnabled(): Promise { - return FirebaseCrash.isCrashCollectionEnabled(); + return this._native.isCrashCollectionEnabled(); } /** * Logs a message that will appear in a subsequent crash report. * @param {string} message - * @param params */ log(message: string): void { - FirebaseCrash.log(message); + this._native.log(message); } /** @@ -44,7 +38,7 @@ export default class Crash { * @param {string} tag */ logcat(level: number, tag: string, message: string): void { - FirebaseCrash.logcat(level, tag, message); + this._native.logcat(level, tag, message); } /** @@ -71,10 +65,6 @@ export default class Crash { errorMessage = `${errorMessage} - ${stackRows[i]}\r\n`; } - FirebaseCrash.report(errorMessage); - } - - get namespace(): string { - return 'firebase:crash'; + this._native.report(errorMessage); } } diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index 7a22539f..63fa7005 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -2,45 +2,38 @@ * @flow * Database representation wrapper */ -import { NativeModules, NativeEventEmitter } from 'react-native'; +import { NativeModules } from 'react-native'; -import { Base } from './../base'; +import ModuleBase from './../../utils/ModuleBase'; import Snapshot from './snapshot'; import Reference from './reference'; import TransactionHandler from './transaction'; -import { promisify, nativeSDKMissing } from './../../utils'; - -const FirebaseDatabase = NativeModules.RNFirebaseDatabase; -const FirebaseDatabaseEvt = FirebaseDatabase && new NativeEventEmitter(FirebaseDatabase); +import { promisify } from './../../utils'; /** * @class Database */ -export default class Database extends Base { - constructor(firebase: Object, options: Object = {}) { - super(firebase, options); - if (!FirebaseDatabase) { - return nativeSDKMissing('database'); - } - +// TODO refactor native and js - legacy code here using old fb methods +export default class Database extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Database', true); this.references = {}; this.serverTimeOffset = 0; this.persistenceEnabled = false; - this.namespace = 'firebase:database'; - this.transaction = new TransactionHandler(firebase, this, FirebaseDatabaseEvt); + this.transaction = new TransactionHandler(this); - if (firebase.options.persistence === true) { + if (options.persistence === true) { this._setPersistence(true); } - this.successListener = FirebaseDatabaseEvt.addListener( + this.successListener = this._eventEmitter.addListener( 'database_event', - event => this._handleDatabaseEvent(event) + event => this._handleDatabaseEvent(event), ); - this.errorListener = FirebaseDatabaseEvt.addListener( + this.errorListener = this._eventEmitter.addListener( 'database_error', - err => this._handleDatabaseError(err) + err => this._handleDatabaseError(err), ); this.offsetRef = this.ref('.info/serverTimeOffset'); @@ -63,34 +56,26 @@ export default class Database extends Base { /** * - * @param path - * @param modifiersString - * @param modifiers - * @param eventName - * @param cb - * @param errorCb * @returns {*} + * @param ref + * @param listener */ on(ref: Reference, listener: DatabaseListener) { const { refId, path, query } = ref; const { listenerId, eventName } = listener; this.log.debug('on() : ', ref.refId, listenerId, eventName); this.references[refId] = ref; - return promisify('on', FirebaseDatabase)(refId, path, query.getModifiers(), listenerId, eventName); + return promisify('on', this._native)(refId, path, query.getModifiers(), listenerId, eventName); } /** * - * @param path - * @param modifiersString - * @param eventName - * @param origCB * @returns {*} + * @param refId + * @param listeners + * @param remainingListenersCount */ - off(refId: number, - // $FlowFixMe - listeners: Array, - remainingListenersCount: number) { + off(refId: number, listeners: Array, remainingListenersCount: number) { this.log.debug('off() : ', refId, listeners); // Delete the reference if there are no more listeners @@ -98,7 +83,7 @@ export default class Database extends Base { if (listeners.length === 0) return Promise.resolve(); - return promisify('off', FirebaseDatabase)(refId, listeners.map(listener => ({ + return promisify('off', this._native)(refId, listeners.map(listener => ({ listenerId: listener.listenerId, eventName: listener.eventName, }))); @@ -118,11 +103,11 @@ export default class Database extends Base { } goOnline() { - FirebaseDatabase.goOnline(); + this._native.goOnline(); } goOffline() { - FirebaseDatabase.goOffline(); + this._native.goOffline(); } /** @@ -142,7 +127,7 @@ export default class Database extends Base { if (this.persistenceEnabled !== enable) { this.persistenceEnabled = enable; this.log.debug(`${enable ? 'Enabling' : 'Disabling'} persistence.`); - return promisify('enablePersistence', FirebaseDatabase)(enable); + return promisify('enablePersistence', this._native)(enable); } return Promise.reject({ status: 'Already enabled' }); @@ -161,7 +146,7 @@ export default class Database extends Base { const cb = this.references[refId].refListeners[listenerId].successCallback; cb(new Snapshot(this.references[refId], snapshot), previousChildName); } else { - FirebaseDatabase.off(refId, [{ listenerId, eventName }], () => { + this._native.off(refId, [{ listenerId, eventName }], () => { this.log.debug('_handleDatabaseEvent: No JS listener registered, removed native listener', refId, listenerId, eventName); }); } @@ -211,7 +196,7 @@ export default class Database extends Base { } export const statics = { - ServerValue: FirebaseDatabase ? { - TIMESTAMP: FirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' }, + ServerValue: NativeModules.FirebaseDatabase ? { + TIMESTAMP: NativeModules.FirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' }, } : {}, }; diff --git a/lib/modules/database/query.js b/lib/modules/database/query.js index b3014f53..307626b9 100644 --- a/lib/modules/database/query.js +++ b/lib/modules/database/query.js @@ -2,7 +2,7 @@ * @flow */ -import { ReferenceBase } from './../base'; +import ReferenceBase from './../../utils/ModuleBase'; import Reference from './reference.js'; /** diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index 0c4dfef6..1713caf8 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -1,15 +1,12 @@ /** * @flow */ -import { NativeModules } from 'react-native'; - import Query from './query.js'; import Snapshot from './snapshot'; import Disconnect from './disconnect'; -import { ReferenceBase } from './../base'; +import ReferenceBase from './../../utils/ReferenceBase'; import { promisify, isFunction, isObject, tryJSONParse, tryJSONStringify, generatePushID } from './../../utils'; -const FirebaseDatabase = NativeModules.RNFirebaseDatabase; // Unique Reference ID for native events let refId = 1; @@ -57,10 +54,11 @@ export default class Reference extends ReferenceBase { refId: number; refListeners: { [listenerId: number]: DatabaseListener }; - database: FirebaseDatabase; + database: Object; query: Query; - constructor(database: FirebaseDatabase, path: string, existingModifiers?: Array) { + // todo logger missing as reference base no longer extends module base + constructor(database: Object, path: string, existingModifiers?: Array) { super(path); this.refId = refId++; this.refListeners = {}; @@ -77,7 +75,7 @@ export default class Reference extends ReferenceBase { */ keepSynced(bool: boolean) { const path = this.path; - return promisify('keepSynced', FirebaseDatabase)(path, bool); + return promisify('keepSynced', this.database._native)(path, bool); } /** @@ -88,7 +86,7 @@ export default class Reference extends ReferenceBase { set(value: any) { const path = this.path; const _value = this._serializeAnyType(value); - return promisify('set', FirebaseDatabase)(path, _value); + return promisify('set', this.database._native)(path, _value); } /** @@ -99,7 +97,7 @@ export default class Reference extends ReferenceBase { update(val: Object) { const path = this.path; const value = this._serializeObject(val); - return promisify('update', FirebaseDatabase)(path, value); + return promisify('update', this.database._native)(path, value); } /** @@ -107,7 +105,7 @@ export default class Reference extends ReferenceBase { * @returns {*} */ remove() { - return promisify('remove', FirebaseDatabase)(this.path); + return promisify('remove', this.database._native)(this.path); } /** @@ -123,7 +121,7 @@ export default class Reference extends ReferenceBase { const path = this.path; const _value = this._serializeAnyType(value); - return promisify('push', FirebaseDatabase)(path, _value) + return promisify('push', this.database._native)(path, _value) .then(({ ref }) => { const newRef = new Reference(this.database, ref); if (isFunction(onComplete)) return onComplete(null, newRef); @@ -244,31 +242,26 @@ export default class Reference extends ReferenceBase { if (arguments.length > 2 && !failureCallbackOrContext) throw new Error('Query.on failed: third argument must either be a cancel callback or a context object.'); this.log.debug('adding reference.on', this.refId, eventType); - let _failureCallback; let _context; if (context) { _context = context; _failureCallback = failureCallbackOrContext; + } else if (isFunction(failureCallbackOrContext)) { + _failureCallback = failureCallbackOrContext; } else { - if (isFunction(failureCallbackOrContext)) { - _failureCallback = failureCallbackOrContext; - } else { - _context = failureCallbackOrContext; - } + _context = failureCallbackOrContext; } if (_failureCallback) { _failureCallback = (error) => { if (error.message.startsWith('FirebaseError: permission_denied')) { - - error.message = `permission_denied at /${this.path}: Client doesn\'t have permission to access the desired data.` + error.message = `permission_denied at /${this.path}: Client doesn't have permission to access the desired data.` } failureCallbackOrContext(error); - - } + }; } let _successCallback; @@ -300,7 +293,7 @@ export default class Reference extends ReferenceBase { * @returns {Promise.} */ once(eventName: string = 'value', successCallback: (snapshot: Object) => void, failureCallback: (error: FirebaseError) => void) { - return promisify('once', FirebaseDatabase)(this.refId, this.path, this.query.getModifiers(), eventName) + return promisify('once', this.database._native)(this.refId, this.path, this.query.getModifiers(), eventName) .then(({ snapshot }) => new Snapshot(this, snapshot)) .then((snapshot) => { if (isFunction(successCallback)) successCallback(snapshot); @@ -375,14 +368,10 @@ export default class Reference extends ReferenceBase { * @param onComplete * @param applyLocally */ - transaction( - transactionUpdate: Function, - onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *, - applyLocally: boolean = false - ) { + transaction(transactionUpdate: Function, onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *, applyLocally: boolean = false) { if (!isFunction(transactionUpdate)) { return Promise.reject( - new Error('Missing transactionUpdate function argument.') + new Error('Missing transactionUpdate function argument.'), ); } @@ -588,7 +577,7 @@ export default class Reference extends ReferenceBase { * * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#parent} */ - get parent(): Reference|null { + get parent(): Reference | null { if (this.path === '/') return null; return new Reference(this.database, this.path.substring(0, this.path.lastIndexOf('/'))); } diff --git a/lib/modules/database/transaction.js b/lib/modules/database/transaction.js index 8a4b529a..5c65e2c1 100644 --- a/lib/modules/database/transaction.js +++ b/lib/modules/database/transaction.js @@ -2,26 +2,19 @@ * @flow * Database representation wrapper */ -import { NativeModules } from 'react-native'; -import { Base } from './../base'; import { generatePushID } from './../../utils'; -const FirebaseDatabase = NativeModules.RNFirebaseDatabase; - /** * @class Database */ -export default class TransactionHandler extends Base { - constructor(firebase: Object, database: Object, FirebaseDatabaseEvt: Object) { - super(firebase, {}); - this.transactions = {}; - this.database = database; - this.namespace = 'firebase:database:transaction'; - - this.transactionListener = FirebaseDatabaseEvt.addListener( +export default class TransactionHandler { + constructor(database: Object) { + this._transactions = {}; + this._database = database; + this._transactionListener = this._database._eventEmitter.addListener( 'database_transaction_event', - event => this._handleTransactionEvent(event) + event => this._handleTransactionEvent(event), ); } @@ -40,7 +33,7 @@ export default class TransactionHandler extends Base { ) { const id = this._generateTransactionId(); - this.transactions[id] = { + this._transactions[id] = { id, reference, transactionUpdater, @@ -50,7 +43,7 @@ export default class TransactionHandler extends Base { started: true, }; - FirebaseDatabase.startTransaction(reference.path, id, applyLocally); + this._database._native.startTransaction(reference.path, id, applyLocally); } /** @@ -63,7 +56,7 @@ export default class TransactionHandler extends Base { * @private */ _generateTransactionId(): string { - return generatePushID(this.database.serverTimeOffset); + return generatePushID(this._database.serverTimeOffset); } /** @@ -96,7 +89,7 @@ export default class TransactionHandler extends Base { const { id, value } = event; try { - const transaction = this.transactions[id]; + const transaction = this._transactions[id]; // todo handle when transaction no longer exists on js side? newValue = transaction.transactionUpdater(value); } finally { @@ -106,7 +99,7 @@ export default class TransactionHandler extends Base { abort = true; } - FirebaseDatabase.tryCommitTransaction(id, { value: newValue, abort }); + this._database._native.tryCommitTransaction(id, { value: newValue, abort }); } } @@ -116,14 +109,14 @@ export default class TransactionHandler extends Base { * @private */ _handleError(event: Object = {}) { - const transaction = this.transactions[event.id]; + const transaction = this._transactions[event.id]; if (transaction && !transaction.completed) { transaction.completed = true; try { transaction.onComplete(new Error(event.message, event.code), null); } finally { setImmediate(() => { - delete this.transactions[event.id]; + delete this._transactions[event.id]; }); } } @@ -135,14 +128,14 @@ export default class TransactionHandler extends Base { * @private */ _handleComplete(event: Object = {}) { - const transaction = this.transactions[event.id]; + const transaction = this._transactions[event.id]; if (transaction && !transaction.completed) { transaction.completed = true; try { transaction.onComplete(null, event.committed, Object.assign({}, event.snapshot)); } finally { setImmediate(() => { - delete this.transactions[event.id]; + delete this._transactions[event.id]; }); } } diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 8e3b174b..b7940074 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -1,11 +1,7 @@ -import { NativeEventEmitter, NativeModules, Platform } from 'react-native'; -import { Base } from './../base'; -import { nativeSDKMissing } from './../../utils'; +import { Platform } from 'react-native'; +import ModuleBase from './../../utils/ModuleBase'; import RemoteMessage from './RemoteMessage'; -const FirebaseMessaging = NativeModules.RNFirebaseMessaging; -const FirebaseMessagingEvt = FirebaseMessaging && new NativeEventEmitter(FirebaseMessaging); - const EVENT_TYPE = { RefreshToken: 'messaging_token_refreshed', Notification: 'messaging_notification_received', @@ -63,9 +59,8 @@ function finish(data) { } FirebaseMessaging.finishWillPresentNotification(this._completionHandlerId, result); - return; + break; default: - return; } } } @@ -74,14 +69,9 @@ function finish(data) { /** * @class Messaging */ -export default class Messaging extends Base { - constructor(firebase, options = {}) { - super(firebase, options); - if (!FirebaseMessaging) { - return nativeSDKMissing('messaging'); - } - - this.namespace = 'firebase:messaging'; +export default class Messaging extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Messaging'); } get EVENT_TYPE() { @@ -105,7 +95,7 @@ export default class Messaging extends Base { * @returns {*} */ getInitialNotification() { - return FirebaseMessaging.getInitialNotification(); + return this._native.getInitialNotification(); } /** @@ -113,7 +103,7 @@ export default class Messaging extends Base { * @returns {*|Promise.} */ getToken() { - return FirebaseMessaging.getToken(); + return this._native.getToken(); } /** @@ -125,7 +115,7 @@ export default class Messaging extends Base { const _notification = Object.assign({}, notification); _notification.id = _notification.id || new Date().getTime().toString(); _notification.local_notification = true; - return FirebaseMessaging.createLocalNotification(_notification); + return this._native.createLocalNotification(_notification); } /** @@ -137,7 +127,7 @@ export default class Messaging extends Base { const _notification = Object.assign({}, notification); if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.')); _notification.local_notification = true; - return FirebaseMessaging.scheduleLocalNotification(_notification); + return this._native.scheduleLocalNotification(_notification); } /** @@ -145,7 +135,7 @@ export default class Messaging extends Base { * @returns {Promise.} */ getScheduledLocalNotifications() { - return FirebaseMessaging.getScheduledLocalNotifications(); + return this._native.getScheduledLocalNotifications(); } /** @@ -156,8 +146,8 @@ export default class Messaging extends Base { */ cancelLocalNotification(id: string) { if (!id) return null; - if (id === '*') return FirebaseMessaging.cancelAllLocalNotifications(); - return FirebaseMessaging.cancelLocalNotification(id); + if (id === '*') return this._native.cancelAllLocalNotifications(); + return this._native.cancelLocalNotification(id); } /** @@ -168,8 +158,8 @@ export default class Messaging extends Base { */ removeDeliveredNotification(id: string) { if (!id) return null; - if (id === '*') return FirebaseMessaging.removeAllDeliveredNotifications(); - return FirebaseMessaging.removeDeliveredNotification(id); + if (id === '*') return this._native.removeAllDeliveredNotifications(); + return this._native.removeDeliveredNotification(id); } /** @@ -178,7 +168,7 @@ export default class Messaging extends Base { * @returns {*|Promise.<*>} */ requestPermissions() { - return FirebaseMessaging.requestPermissions(); + return this._native.requestPermissions(); } @@ -187,7 +177,7 @@ export default class Messaging extends Base { * @param n */ setBadgeNumber(n: number) { - FirebaseMessaging.setBadgeNumber(n); + this._native.setBadgeNumber(n); } /** @@ -195,7 +185,7 @@ export default class Messaging extends Base { * @returns {Promise.} */ getBadgeNumber() { - return FirebaseMessaging.getBadgeNumber(); + return this._native.getBadgeNumber(); } /** @@ -204,9 +194,9 @@ export default class Messaging extends Base { * @returns {*} */ onMessage(listener: Function): () => any { - const rnListener = FirebaseMessagingEvt.addListener( + const rnListener = this._eventEmitter.addListener( EVENT_TYPE.Notification, - async(event) => { + async (event) => { const data = { ...event, finish, @@ -216,7 +206,7 @@ export default class Messaging extends Base { if (!data._finishCalled) { data.finish(); } - } + }, ); return () => rnListener.remove(); } @@ -227,7 +217,7 @@ export default class Messaging extends Base { * @returns {*} */ onTokenRefresh(listener: Function): () => any { - const rnListener = FirebaseMessagingEvt.addListener(EVENT_TYPE.RefreshToken, listener); + const rnListener = this._eventEmitter.addListener(EVENT_TYPE.RefreshToken, listener); return () => rnListener.remove(); } @@ -236,7 +226,7 @@ export default class Messaging extends Base { * @param topic */ subscribeToTopic(topic: String) { - FirebaseMessaging.subscribeToTopic(topic); + this._native.subscribeToTopic(topic); } /** @@ -244,7 +234,7 @@ export default class Messaging extends Base { * @param topic */ unsubscribeFromTopic(topic: String) { - FirebaseMessaging.unsubscribeFromTopic(topic); + this._native.unsubscribeFromTopic(topic); } /** @@ -256,7 +246,7 @@ export default class Messaging extends Base { throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.'); } - return FirebaseMessaging.send(remoteMessage.toJSON()); + return this._native.send(remoteMessage.toJSON()); } } diff --git a/lib/modules/perf/Trace.js b/lib/modules/perf/Trace.js index 258a622a..7ac258b0 100644 --- a/lib/modules/perf/Trace.js +++ b/lib/modules/perf/Trace.js @@ -1,7 +1,3 @@ -import { NativeModules } from 'react-native'; - -const FirebasePerformance = NativeModules.RNFirebasePerformance; - export default class Trace { constructor(perf: Object, identifier: string) { @@ -10,14 +6,14 @@ export default class Trace { } start() { - FirebasePerformance.start(this.identifier); + this.perf._native.start(this.identifier); } stop() { - FirebasePerformance.stop(this.identifier); + this.perf._native.stop(this.identifier); } incrementCounter(event: string) { - FirebasePerformance.incrementCounter(this.identifier, event); + this.perf._native.incrementCounter(this.identifier, event); } } diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 910f4438..69121a5e 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -1,15 +1,10 @@ // @flow -import { NativeModules } from 'react-native'; -import { nativeSDKMissing } from './../../utils'; import Trace from './Trace'; +import ModuleBase from '../../utils/ModuleBase'; -const FirebasePerformance = NativeModules.RNFirebasePerformance; - -export default class PerformanceMonitoring { - constructor() { - if (!FirebasePerformance) { - return nativeSDKMissing('perf'); - } +export default class PerformanceMonitoring extends ModuleBase { + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Perf'); } /** @@ -18,7 +13,7 @@ export default class PerformanceMonitoring { * @returns {*} */ setPerformanceCollectionEnabled(enabled: boolean) { - return FirebasePerformance.setPerformanceCollectionEnabled(enabled); + return this._native.setPerformanceCollectionEnabled(enabled); } /** diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index 98013f22..e56c3122 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -1,39 +1,29 @@ /* @flow */ -import { NativeModules, NativeEventEmitter } from 'react-native'; +import { NativeModules } from 'react-native'; -import { Base } from './../base'; -import { nativeSDKMissing } from './../../utils'; import StorageRef from './reference'; +import ModuleBase from './../../utils/ModuleBase'; const FirebaseStorage = NativeModules.RNFirebaseStorage; -const FirebaseStorageEvt = FirebaseStorage && new NativeEventEmitter(FirebaseStorage); -type StorageOptionsType = { - storageBucket?: ?string, -}; - -export default class Storage extends Base { +export default class Storage extends ModuleBase { /** * - * @param firebase + * @param firebaseApp * @param options */ - constructor(firebase: Object, options: StorageOptionsType = {}) { - super(firebase, options); - if (!FirebaseStorage) { - return nativeSDKMissing('storage'); - } + constructor(firebaseApp: Object, options: Object = {}) { + super(firebaseApp, options, 'Storage', true); + this._subscriptions = {}; - this.subscriptions = {}; - - this.successListener = FirebaseStorageEvt.addListener( + this._successListener = this._eventEmitter.addListener( 'storage_event', - event => this._handleStorageEvent(event) + event => this._handleStorageEvent(event), ); - this.errorListener = FirebaseStorageEvt.addListener( + this._errorListener = this._eventEmitter.addListener( 'storage_error', - err => this._handleStorageError(err) + err => this._handleStorageError(err), ); } @@ -64,7 +54,7 @@ export default class Storage extends Base { * @param time The new maximum operation retry time in milliseconds. */ setMaxOperationRetryTime(time: number) { - FirebaseStorage.setMaxOperationRetryTime(time); + this._native.setMaxOperationRetryTime(time); } /** @@ -73,7 +63,7 @@ export default class Storage extends Base { * @param time The new maximum upload retry time in milliseconds. */ setMaxUploadRetryTime(time: number) { - FirebaseStorage.setMaxUploadRetryTime(time); + this._native.setMaxUploadRetryTime(time); } /** @@ -82,7 +72,7 @@ export default class Storage extends Base { * @param time The new maximum download retry time in milliseconds. */ setMaxDownloadRetryTime(time: number) { - FirebaseStorage.setMaxDownloadRetryTime(time); + this._native.setMaxDownloadRetryTime(time); } /** ********** @@ -95,8 +85,8 @@ export default class Storage extends Base { this.log.debug('_handleStorageEvent: ', path, eventName, body); - if (this.subscriptions[path] && this.subscriptions[path][eventName]) { - this.subscriptions[path][eventName].forEach((cb) => { + if (this._subscriptions[path] && this._subscriptions[path][eventName]) { + this._subscriptions[path][eventName].forEach((cb) => { cb(body); }); } @@ -107,34 +97,30 @@ export default class Storage extends Base { } _addListener(path: string, eventName: string, cb: (evt: Object) => Object) { - if (!this.subscriptions[path]) this.subscriptions[path] = {}; - if (!this.subscriptions[path][eventName]) this.subscriptions[path][eventName] = []; - this.subscriptions[path][eventName].push(cb); + if (!this._subscriptions[path]) this._subscriptions[path] = {}; + if (!this._subscriptions[path][eventName]) this._subscriptions[path][eventName] = []; + this._subscriptions[path][eventName].push(cb); } _removeListener(path: string, eventName: string, origCB: (evt: Object) => Object) { - if (!this.subscriptions[path] || (eventName && !this.subscriptions[path][eventName])) { + if (!this._subscriptions[path] || (eventName && !this._subscriptions[path][eventName])) { this.log.warn('_removeListener() called, but not currently listening at that location (bad path)', path, eventName); return; } if (eventName && origCB) { - const i = this.subscriptions[path][eventName].indexOf(origCB); + const i = this._subscriptions[path][eventName].indexOf(origCB); if (i === -1) { this.log.warn('_removeListener() called, but the callback specified is not listening at this location (bad path)', path, eventName); } else { - this.subscriptions[path][eventName].splice(i, 1); + this._subscriptions[path][eventName].splice(i, 1); } } else if (eventName) { - this.subscriptions[path][eventName] = []; + this._subscriptions[path][eventName] = []; } else { - this.subscriptions[path] = {}; + this._subscriptions[path] = {}; } } - - get namespace(): string { - return 'firebase:storage'; - } } export const statics = { diff --git a/lib/modules/storage/reference.js b/lib/modules/storage/reference.js index d5827f0a..15e73a5a 100644 --- a/lib/modules/storage/reference.js +++ b/lib/modules/storage/reference.js @@ -1,11 +1,9 @@ /* @flow */ -import { NativeModules } from 'react-native'; -import { ReferenceBase } from '../base'; +import ReferenceBase from '../../utils/ReferenceBase'; import StorageTask, { UPLOAD_TASK, DOWNLOAD_TASK } from './task'; import Storage from './'; -const FirebaseStorage = NativeModules.RNFirebaseStorage; /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference @@ -39,7 +37,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ delete(): Promise<*> { - return FirebaseStorage.delete(this.path); + return this.storate._native.delete(this.path); } /** @@ -47,7 +45,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ getDownloadURL(): Promise { - return FirebaseStorage.getDownloadURL(this.path); + return this.storate._native.getDownloadURL(this.path); } /** @@ -55,7 +53,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ getMetadata(): Promise { - return FirebaseStorage.getMetadata(this.path); + return this.storate._native.getMetadata(this.path); } /** @@ -64,7 +62,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ updateMetadata(metadata: Object = {}): Promise { - return FirebaseStorage.updateMetadata(this.path, metadata); + return this.storate._native.updateMetadata(this.path, metadata); } /** @@ -73,7 +71,7 @@ export default class StorageReference extends ReferenceBase { * @return {Promise} */ downloadFile(filePath: string): Promise { - return new StorageTask(DOWNLOAD_TASK, FirebaseStorage.downloadFile(this.path, filePath), this); + return new StorageTask(DOWNLOAD_TASK, this.storate._native.downloadFile(this.path, filePath), this); } /** @@ -92,6 +90,6 @@ export default class StorageReference extends ReferenceBase { */ putFile(filePath: Object, metadata: Object = {}): Promise { const _filePath = filePath.replace('file://', ''); - return new StorageTask(UPLOAD_TASK, FirebaseStorage.putFile(this.path, _filePath, metadata), this); + return new StorageTask(UPLOAD_TASK, this.storate._native.putFile(this.path, _filePath, metadata), this); } } diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index f75e2f34..9999acfe 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -1,17 +1,15 @@ /** * @flow */ -import { NativeModules } from 'react-native'; +import { NativeModules, NativeEventEmitter } from 'react-native'; import Log from '../utils/log'; import { nativeWithApp } from './../utils'; import INTERNALS from './../internals'; -// logging instances - const logs = {}; export default class ModuleBase { - constructor(firebaseApp, options, moduleName) { + constructor(firebaseApp, options, moduleName, withEventEmitter = false) { this._options = Object.assign({}, options); this._module = moduleName; this._firebaseApp = firebaseApp; @@ -27,6 +25,9 @@ export default class ModuleBase { // used by the modules that extend ModuleBase to access their native module counterpart this._native = nativeWithApp(this._appName, nativeModule); + if (withEventEmitter) { + this._eventEmitter = new NativeEventEmitter(this._native); + } } /** diff --git a/lib/utils/ReferenceBase.js b/lib/utils/ReferenceBase.js new file mode 100644 index 00000000..15da7e04 --- /dev/null +++ b/lib/utils/ReferenceBase.js @@ -0,0 +1,20 @@ +/** + * @flow + */ +export default class ReferenceBase { + constructor(path: string) { + this.path = path || '/'; + } + + // todo add missing firebase reference props/methods + + /** + * The last part of a Reference's path (after the last '/') + * The key of a root Reference is null. + * @type {String} + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#key} + */ + get key(): string | null { + return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1); + } +} diff --git a/tests/src/tests/config/configTests.js b/tests/src/tests/config/configTests.js index 20f4e818..5baece05 100644 --- a/tests/src/tests/config/configTests.js +++ b/tests/src/tests/config/configTests.js @@ -1,5 +1,5 @@ function configTests({ before, describe, it, firebase }) { - + // todo tests are buggy - shows success but doesn't actually run tests /* Remote config service values = { foo: true, foobar: 'barbaz', @@ -61,7 +61,6 @@ function configTests({ before, describe, it, firebase }) { it('it get all keys as an array', () => { return firebase.native.config().getKeysByPrefix() .then((result) => { - console.log(result) result.should.be.Array(); return Promise.resolve(); });