diff --git a/README.md b/README.md index ca064bd..e4a609d 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,17 @@ npm i react-native-firestack --save [![npm version](https://img.shields.io/npm/v/react-native-firestack.svg)](https://www.npmjs.com/package/react-native-firestack) [![License](https://img.shields.io/npm/l/react-native-firestack.svg)](/LICENSE) -Firestack is a _light-weight_ layer sitting on-top of the native Firebase libraries for both iOS and Android which mirrors the React Native JS api as closely as possible. It features: +Firestack is a _light-weight_ layer sitting on-top of the native Firebase libraries for both iOS and Android which mirrors the React Native JS api as closely as possible. Featuring; authentication, storage, real-time database, presence, analytics, cloud messaging, remote configuration, redux support and more! ## Firestack vs Firebase JS lib -Although the [Firebase](https://www.npmjs.com/package/firebase) JavaScript library will work with React Native, it's designed for the web and/or server. The native SDKs provide much needed features specifically for mobile applications such as offline persistance. Firestack provides a JavaScript interface into the native SDKs to allow your React Native application to utilise these features, and more! +Although the [Firebase](https://www.npmjs.com/package/firebase) JavaScript library will work with React Native, it is mainly designed for the web. + +The native SDK's are much better for performance compared to the web SDK. The web SDK will run on the same thread as your apps ([JS thread](https://facebook.github.io/react-native/docs/performance.html#javascript-frame-rate)) therefore limiting your JS framerate, potentially affecting things touch events and transitions/animations. + +The native SDK's also contains functionality that the web SDK's do not, for example [Analytics](/docs/api/analytics.md) and [Remote Config](/docs/api/remote-config.md). ## Example app @@ -36,6 +40,7 @@ We have a working application example available in at [fullstackreact/FirestackA * [Presence](docs/api/presence.md) * [ServerValue](docs/api/server-value.md) * [Cloud Messaging](docs/api/cloud-messaging.md) + * [Remote Config](docs/api/remote-config.md) * [Events](docs/api/events.md) * [Redux](docs/redux.md) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java index b4cc28e..b41ea12 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java @@ -19,7 +19,6 @@ import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; -import com.google.firebase.FirebaseApp; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; @@ -42,14 +41,12 @@ class FirestackAuthModule extends ReactContextBaseJavaModule { // private Context context; private ReactContext mReactContext; private FirebaseAuth mAuth; - private FirebaseApp app; - private FirebaseUser user; private FirebaseAuth.AuthStateListener mAuthListener; public FirestackAuthModule(ReactApplicationContext reactContext) { super(reactContext); - // this.context = reactContext; mReactContext = reactContext; + mAuth = FirebaseAuth.getInstance(); Log.d(TAG, "New FirestackAuth instance"); } @@ -78,16 +75,17 @@ private void callbackNoUser(Callback callback, Boolean isError) { @ReactMethod public void listenForAuth() { - if (mAuthListener == null || mAuth == null) { + if (mAuthListener == null) { mAuthListener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { + FirebaseUser user = firebaseAuth.getCurrentUser(); WritableMap msgMap = Arguments.createMap(); msgMap.putString("eventName", "listenForAuth"); - if (FirestackAuthModule.this.user != null) { + if (user != null) { // TODO move to helper - WritableMap userMap = getUserMap(); + WritableMap userMap = getUserMap(user); msgMap.putBoolean("authenticated", true); msgMap.putMap("user", userMap); @@ -98,8 +96,6 @@ public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { } } }; - - mAuth = FirebaseAuth.getInstance(); mAuth.addAuthStateListener(mAuthListener); } } @@ -119,16 +115,13 @@ public void unlistenForAuth(final Callback callback) { @ReactMethod public void createUserWithEmail(final String email, final String password, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - mAuth.createUserWithEmailAndPassword(email, password) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -141,7 +134,6 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void signInWithEmail(final String email, final String password, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); mAuth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(new OnCompleteListener() { @@ -149,8 +141,7 @@ public void signInWithEmail(final String email, final String password, final Cal public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -175,9 +166,6 @@ public void signInWithProvider(final String provider, final String authToken, fi @ReactMethod public void signInAnonymously(final Callback callback) { Log.d(TAG, "signInAnonymously:called:"); - mAuth = FirebaseAuth.getInstance(); - - mAuth.signInAnonymously() .addOnCompleteListener(new OnCompleteListener() { @Override @@ -186,8 +174,7 @@ public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -200,8 +187,6 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void signInWithCustomToken(final String customToken, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - mAuth.signInWithCustomToken(customToken) .addOnCompleteListener(new OnCompleteListener() { @Override @@ -209,8 +194,7 @@ public void onComplete(@NonNull Task task) { Log.d(TAG, "signInWithCustomToken:onComplete:" + task.isSuccessful()); try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -231,7 +215,7 @@ public void reauthenticateWithCredentialForProvider(final String provider, final @ReactMethod public void updateUserEmail(final String email, final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { user @@ -242,8 +226,7 @@ public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { Log.d(TAG, "User email address updated"); - FirebaseUser u = FirebaseAuth.getInstance().getCurrentUser(); - userCallback(u, callback); + userCallback(mAuth.getCurrentUser(), callback); } else { userErrorCallback(task, callback); } @@ -259,7 +242,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void updateUserPassword(final String newPassword, final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { user.updatePassword(newPassword) @@ -269,9 +252,7 @@ public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { Log.d(TAG, "User password updated"); - - FirebaseUser u = FirebaseAuth.getInstance().getCurrentUser(); - userCallback(u, callback); + userCallback(mAuth.getCurrentUser(), callback); } else { userErrorCallback(task, callback); } @@ -287,8 +268,6 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void sendPasswordResetWithEmail(final String email, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - mAuth.sendPasswordResetEmail(email) .addOnCompleteListener(new OnCompleteListener() { @Override @@ -310,7 +289,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void deleteUser(final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { user.delete() .addOnCompleteListener(new OnCompleteListener() { @@ -339,7 +318,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void sendEmailVerification(final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { user.sendEmailVerification() @@ -371,7 +350,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void getToken(final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { user.getToken(true) @@ -403,7 +382,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void updateUserProfile(ReadableMap props, final Callback callback) { - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + FirebaseUser user = mAuth.getCurrentUser(); if (user != null) { UserProfileChangeRequest.Builder profileBuilder = new UserProfileChangeRequest.Builder(); @@ -430,8 +409,7 @@ public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { Log.d(TAG, "User profile updated"); - FirebaseUser u = FirebaseAuth.getInstance().getCurrentUser(); - userCallback(u, callback); + userCallback(mAuth.getCurrentUser(), callback); } else { userErrorCallback(task, callback); } @@ -447,8 +425,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void signOut(final Callback callback) { - FirebaseAuth.getInstance().signOut(); - this.user = null; + mAuth.signOut(); WritableMap resp = Arguments.createMap(); resp.putString("status", "complete"); @@ -458,22 +435,18 @@ public void signOut(final Callback callback) { @ReactMethod public void getCurrentUser(final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - - this.user = mAuth.getCurrentUser(); - if (this.user == null) { + FirebaseUser user = mAuth.getCurrentUser(); + if (user == null) { callbackNoUser(callback, false); } else { - Log.d("USRC", this.user.getUid()); - userCallback(this.user, callback); + Log.d("USRC", user.getUid()); + userCallback(user, callback); } } // TODO: Check these things @ReactMethod public void googleLogin(String IdToken, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - AuthCredential credential = GoogleAuthProvider.getCredential(IdToken, null); mAuth.signInWithCredential(credential) .addOnCompleteListener(new OnCompleteListener() { @@ -481,8 +454,7 @@ public void googleLogin(String IdToken, final Callback callback) { public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -495,8 +467,6 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void facebookLogin(String Token, final Callback callback) { - mAuth = FirebaseAuth.getInstance(); - AuthCredential credential = FacebookAuthProvider.getCredential(Token); mAuth.signInWithCredential(credential) .addOnCompleteListener(new OnCompleteListener() { @@ -504,8 +474,7 @@ public void facebookLogin(String Token, final Callback callback) { public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - FirestackAuthModule.this.user = task.getResult().getUser(); - userCallback(FirestackAuthModule.this.user, callback); + userCallback(task.getResult().getUser(), callback); } else { userErrorCallback(task, callback); } @@ -517,24 +486,15 @@ public void onComplete(@NonNull Task task) { } // Internal helpers - private void userCallback(FirebaseUser passedUser, final Callback callback) { - - if (passedUser == null) { - mAuth = FirebaseAuth.getInstance(); - this.user = mAuth.getCurrentUser(); - } else { - this.user = passedUser; - } - - if (this.user != null) { - this.user.getToken(true).addOnCompleteListener(new OnCompleteListener() { + private void userCallback(final FirebaseUser user, final Callback callback) { + if (user != null) { + user.getToken(true).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { try { if (task.isSuccessful()) { - WritableMap userMap = getUserMap(); - final String token = task.getResult().getToken(); - userMap.putString("token", token); + WritableMap userMap = getUserMap(user); + userMap.putString("token", task.getResult().getToken()); callback.invoke(null, userMap); } else { userErrorCallback(task, callback); @@ -567,11 +527,8 @@ private void userExceptionCallback(Exception ex, final Callback onFail) { onFail.invoke(error); } - private WritableMap getUserMap() { + private WritableMap getUserMap(FirebaseUser user) { WritableMap userMap = Arguments.createMap(); - - FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); - if (user != null) { final String email = user.getEmail(); final String uid = user.getUid(); diff --git a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java index 4cdf613..b12289c 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java @@ -10,6 +10,7 @@ import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReactMethod; @@ -79,11 +80,9 @@ public void onCancelled(DatabaseError error) { self.handleDatabaseError(name, mPath, error); } }; + Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiersArray); + ref.addChildEventListener(mEventListener); } - - Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiersArray); - ref.addChildEventListener(mEventListener); - //this.setListeningTo(mPath, modifiersString, name); } public void addValueEventListener(final String name, final ReadableArray modifiersArray, final String modifiersString) { @@ -618,54 +617,4 @@ private DatabaseReference getDatabaseReferenceAtPath(final String path) { DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference(path); return mDatabase; } - - - //private WritableMap dataSnapshotToMap(String name, String path, DataSnapshot dataSnapshot) { - // return FirestackUtils.dataSnapshotToMap(name, path, dataSnapshot); - //} - - private Any castSnapshotValue(DataSnapshot snapshot) { - if (snapshot.hasChildren()) { - WritableMap data = Arguments.createMap(); - for (DataSnapshot child : snapshot.getChildren()) { - Any castedChild = castSnapshotValue(child); - switch (castedChild.getClass().getName()) { - case "java.lang.Boolean": - data.putBoolean(child.getKey(), (Boolean) castedChild); - break; - case "java.lang.Long": - data.putDouble(child.getKey(), (Long) castedChild); - break; - case "java.lang.Double": - data.putDouble(child.getKey(), (Double) castedChild); - break; - case "java.lang.String": - data.putString(child.getKey(), (String) castedChild); - break; - case "com.facebook.react.bridge.WritableNativeMap": - data.putMap(child.getKey(), (WritableMap) castedChild); - break; - } - } - return (Any) data; - } else { - if (snapshot.getValue() != null) { - String type = snapshot.getValue().getClass().getName(); - switch (type) { - case "java.lang.Boolean": - return (Any)((Boolean) snapshot.getValue()); - case "java.lang.Long": - return (Any) ((Long) snapshot.getValue()); - case "java.lang.Double": - return (Any)((Double) snapshot.getValue()); - case "java.lang.String": - return (Any)((String) snapshot.getValue()); - default: - return (Any) null; - } - } else { - return (Any) null; - } - } - } } diff --git a/android/src/main/java/io/fullstack/firestack/FirestackStorage.java b/android/src/main/java/io/fullstack/firestack/FirestackStorage.java index 0794f65..b41301d 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackStorage.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackStorage.java @@ -49,11 +49,8 @@ class FirestackStorageModule extends ReactContextBaseJavaModule { private static final String FileTypeRegular = "FILETYPE_REGULAR"; private static final String FileTypeDirectory = "FILETYPE_DIRECTORY"; - private ReactContext mReactContext; - public FirestackStorageModule(ReactApplicationContext reactContext) { super(reactContext); - mReactContext = reactContext; Log.d(TAG, "New instance"); } @@ -142,7 +139,13 @@ public void uploadFile(final String urlStr, final String name, final String file Log.i(TAG, "From file: " + filepath + " to " + urlStr + " with name " + name); try { - Uri file = Uri.fromFile(new File(filepath)); + Uri file; + if (filepath.startsWith("content://")) { + String realPath = getRealPathFromURI(filepath); + file = Uri.fromFile(new File(realPath)); + } else { + file = Uri.fromFile(new File(filepath)); + } StorageMetadata.Builder metadataBuilder = new StorageMetadata.Builder(); Map m = FirestackUtils.recursivelyDeconstructReadableMap(metadata); @@ -190,7 +193,7 @@ public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { WritableMap data = Arguments.createMap(); data.putString("eventName", "upload_progress"); data.putDouble("progress", progress); - FirestackUtils.sendEvent(mReactContext, "upload_progress", data); + FirestackUtils.sendEvent(getReactApplicationContext(), "upload_progress", data); } } }) @@ -203,7 +206,7 @@ public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { WritableMap data = Arguments.createMap(); data.putString("eventName", "upload_paused"); data.putString("ref", bucket); - FirestackUtils.sendEvent(mReactContext, "upload_paused", data); + FirestackUtils.sendEvent(getReactApplicationContext(), "upload_paused", data); } }); } catch (Exception ex) { @@ -214,14 +217,7 @@ public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { @ReactMethod public void getRealPathFromURI(final String uri, final Callback callback) { try { - Context context = getReactApplicationContext(); - String[] proj = {MediaStore.Images.Media.DATA}; - Cursor cursor = context.getContentResolver().query(Uri.parse(uri), proj, null, null, null); - int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - String path = cursor.getString(column_index); - cursor.close(); - + String path = getRealPathFromURI(uri); callback.invoke(null, path); } catch (Exception ex) { ex.printStackTrace(); @@ -229,6 +225,21 @@ public void getRealPathFromURI(final String uri, final Callback callback) { } } + private String getRealPathFromURI(final String uri) { + Cursor cursor = null; + try { + String[] proj = {MediaStore.Images.Media.DATA}; + cursor = getReactApplicationContext().getContentResolver().query(Uri.parse(uri), proj, null, null, null); + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + return cursor.getString(column_index); + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + private WritableMap getDownloadData(final UploadTask.TaskSnapshot taskSnapshot) { Uri downloadUrl = taskSnapshot.getDownloadUrl(); StorageMetadata d = taskSnapshot.getMetadata(); diff --git a/android/src/main/java/io/fullstack/firestack/FirestackUtils.java b/android/src/main/java/io/fullstack/firestack/FirestackUtils.java index ae1bb95..669e337 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackUtils.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackUtils.java @@ -109,32 +109,11 @@ public static WritableMap dataSnapshotToMap( public static Any castSnapshotValue(DataSnapshot snapshot) { if (snapshot.hasChildren()) { - WritableMap data = Arguments.createMap(); - for (DataSnapshot child : snapshot.getChildren()) { - Any castedChild = castSnapshotValue(child); - switch (castedChild.getClass().getName()) { - case "java.lang.Boolean": - data.putBoolean(child.getKey(), (Boolean) castedChild); - break; - case "java.lang.Long": - Long longVal = (Long) castedChild; - data.putDouble(child.getKey(), (double) longVal); - break; - case "java.lang.Double": - data.putDouble(child.getKey(), (Double) castedChild); - break; - case "java.lang.String": - data.putString(child.getKey(), (String) castedChild); - break; - case "com.facebook.react.bridge.WritableNativeMap": - data.putMap(child.getKey(), (WritableMap) castedChild); - break; - default: - Log.w(TAG, "Invalid type: " + castedChild.getClass().getName()); - break; - } + if (isArray(snapshot)) { + return (Any) buildArray(snapshot); + } else { + return (Any) buildMap(snapshot); } - return (Any) data; } else { if (snapshot.getValue() != null) { String type = snapshot.getValue().getClass().getName(); @@ -156,6 +135,88 @@ public static Any castSnapshotValue(DataSnapshot snapshot) { } } + private static boolean isArray(DataSnapshot snapshot) { + long expectedKey = 0; + for (DataSnapshot child : snapshot.getChildren()) { + try { + long key = Long.parseLong(child.getKey()); + if (key == expectedKey) { + expectedKey++; + } else { + return false; + } + } catch (NumberFormatException ex) { + return false; + } + } + return true; + } + + private static WritableArray buildArray(DataSnapshot snapshot) { + WritableArray array = Arguments.createArray(); + for (DataSnapshot child : snapshot.getChildren()) { + Any castedChild = castSnapshotValue(child); + switch (castedChild.getClass().getName()) { + case "java.lang.Boolean": + array.pushBoolean((Boolean) castedChild); + break; + case "java.lang.Long": + Long longVal = (Long) castedChild; + array.pushDouble((double) longVal); + break; + case "java.lang.Double": + array.pushDouble((Double) castedChild); + break; + case "java.lang.String": + array.pushString((String) castedChild); + break; + case "com.facebook.react.bridge.WritableNativeMap": + array.pushMap((WritableMap) castedChild); + break; + case "com.facebook.react.bridge.WritableNativeArray": + array.pushArray((WritableArray) castedChild); + break; + default: + Log.w(TAG, "Invalid type: " + castedChild.getClass().getName()); + break; + } + } + return array; + } + + private static WritableMap buildMap(DataSnapshot snapshot) { + WritableMap map = Arguments.createMap(); + for (DataSnapshot child : snapshot.getChildren()) { + Any castedChild = castSnapshotValue(child); + + switch (castedChild.getClass().getName()) { + case "java.lang.Boolean": + map.putBoolean(child.getKey(), (Boolean) castedChild); + break; + case "java.lang.Long": + Long longVal = (Long) castedChild; + map.putDouble(child.getKey(), (double) longVal); + break; + case "java.lang.Double": + map.putDouble(child.getKey(), (Double) castedChild); + break; + case "java.lang.String": + map.putString(child.getKey(), (String) castedChild); + break; + case "com.facebook.react.bridge.WritableNativeMap": + map.putMap(child.getKey(), (WritableMap) castedChild); + break; + case "com.facebook.react.bridge.WritableNativeArray": + map.putArray(child.getKey(), (WritableArray) castedChild); + break; + default: + Log.w(TAG, "Invalid type: " + castedChild.getClass().getName()); + break; + } + } + return map; + } + public static WritableArray getChildKeys(DataSnapshot snapshot) { WritableArray childKeys = Arguments.createArray(); diff --git a/docs/api/authentication.md b/docs/api/authentication.md index dd234cf..d787374 100644 --- a/docs/api/authentication.md +++ b/docs/api/authentication.md @@ -2,14 +2,14 @@ Firestack handles authentication for us out of the box, both with email/password-based authentication and through oauth providers (with a separate library to handle oauth providers). -> Android requires the Google Play services to installed for authentication to function. +> Authentication requires Google Play services to be installed on Android. ## Auth ### Properties ##### `authenticated: boolean` - Returns the current Firebase authentication state. -##### `currentUser: User | null` - Returns the currently signed-in user (or null). See the [User](/docs/api/authentication#user) class documentation for further usage. +##### `currentUser: User | null` - Returns the currently signed-in user (or null). See the [User](/docs/api/authentication.md#user) class documentation for further usage. ### Methods @@ -26,7 +26,7 @@ class Example extends React.Component { } componentDidMount() { - this.unsubscribe = firebase.auth().onAuthStateChanged(function(user) { + this.unsubscribe = firebase.auth().onAuthStateChanged((user) => { if (user) { // User is signed in. } @@ -34,7 +34,7 @@ class Example extends React.Component { } componentWillUnmount() { - if (this.listener) { + if (this.unsubscribe) { this.unsubscribe(); } } @@ -48,7 +48,7 @@ We can create a user by calling the `createUserWithEmailAndPassword()` function. The method accepts two parameters, an email and a password. ```javascript -firestack.auth().createUserWithEmailAndPassword('ari@fullstack.io', '123456') +firestack.auth().createUserWithEmailAndPassword('foo@bar.com', '123456') .then((user) => { console.log('user created', user) }) @@ -63,7 +63,7 @@ To sign a user in with their email and password, use the `signInWithEmailAndPass It accepts two parameters, the user's email and password: ```javascript -firestack.auth().signInWithEmailAndPassword('ari@fullstack.io', '123456') +firestack.auth().signInWithEmailAndPassword('foo@bar.com', '123456') .then((user) => { console.log('User successfully logged in', user) }) @@ -111,7 +111,7 @@ firestack.auth().signInWithCredential(credential) }) .catch((err) => { console.error('User signin error', err); - }) + }); ``` #### [`signInWithCustomToken(token: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCustomToken) @@ -258,7 +258,7 @@ firestack.auth().updateUserEmail('foo@bar.com') Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. This will Promise reject is the user is anonymous. ```javascript -firestack.auth().updateUserPassword('foobar1234') +firestack.auth().updatePassword('foobar1234') .then() .catch(); ``` diff --git a/docs/api/remote-config.md b/docs/api/remote-config.md new file mode 100644 index 0000000..413c634 --- /dev/null +++ b/docs/api/remote-config.md @@ -0,0 +1 @@ +# Remote Config diff --git a/ios/Firestack/FirestackDatabase.m b/ios/Firestack/FirestackDatabase.m index 918feae..459e0d2 100644 --- a/ios/Firestack/FirestackDatabase.m +++ b/ios/Firestack/FirestackDatabase.m @@ -321,7 +321,8 @@ @implementation FirestackDatabase props:(NSDictionary *) props callback:(RCTResponseSenderBlock) callback) { - FIRDatabaseReference *ref = [[self getRefAtPath:path] childByAutoId]; + FIRDatabaseReference *pathRef = [self getRefAtPath:path]; + FIRDatabaseReference *ref = [pathRef childByAutoId]; NSURL *url = [NSURL URLWithString:ref.URL]; NSString *newPath = [url path]; @@ -351,12 +352,12 @@ @implementation FirestackDatabase RCT_EXPORT_METHOD(on:(NSString *) path modifiersString:(NSString *) modifiersString - modifiersArray:(NSArray *) modifiersArray + modifiers:(NSArray *) modifiers name:(NSString *) eventName callback:(RCTResponseSenderBlock) callback) { - FirestackDBReference *r = [self getDBHandle:path]; - FIRDatabaseQuery *query = [r getQueryWithModifiers:modifiersArray]; + FirestackDBReference *r = [self getDBHandle:path withModifiers:modifiersString]; + FIRDatabaseQuery *query = [r getQueryWithModifiers:modifiers]; if (![r isListeningTo:eventName]) { id withBlock = ^(FIRDataSnapshot * _Nonnull snapshot) { @@ -368,6 +369,7 @@ @implementation FirestackDatabase props: @{ @"eventName": eventName, @"path": path, + @"modifiersString": modifiersString, @"snapshot": props }]; }; @@ -399,14 +401,14 @@ @implementation FirestackDatabase } RCT_EXPORT_METHOD(onOnce:(NSString *) path - modifiersString:(NSString *) modifiersString - modifiersArray:(NSArray *) modifiersArray - name:(NSString *) name - callback:(RCTResponseSenderBlock) callback) + modifiersString:(NSString *) modifiersString + modifiers:(NSArray *) modifiers + name:(NSString *) name + callback:(RCTResponseSenderBlock) callback) { - FirestackDBReference *r = [self getDBHandle:path]; + FirestackDBReference *r = [self getDBHandle:path withModifiers:modifiersString]; int eventType = [r eventTypeFromName:name]; - FIRDatabaseQuery *ref = [r getQueryWithModifiers:modifiersArray]; + FIRDatabaseQuery *ref = [r getQueryWithModifiers:modifiers]; [ref observeSingleEventOfType:eventType withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { @@ -414,6 +416,7 @@ @implementation FirestackDatabase callback(@[[NSNull null], @{ @"eventName": name, @"path": path, + @"modifiersString": modifiersString, @"snapshot": props }]); } @@ -431,14 +434,14 @@ @implementation FirestackDatabase eventName:(NSString *) eventName callback:(RCTResponseSenderBlock) callback) { - FirestackDBReference *r = [self getDBHandle:path]; + FirestackDBReference *r = [self getDBHandle:path withModifiers:modifiersString]; if (eventName == nil || [eventName isEqualToString:@""]) { [r cleanup]; - [self removeDBHandle:path]; + [self removeDBHandle:path withModifiersString:modifiersString]; } else { [r removeEventHandler:eventName]; if (![r hasListeners]) { - [self removeDBHandle:path]; + [self removeDBHandle:path withModifiersString:modifiersString]; } } @@ -447,6 +450,7 @@ @implementation FirestackDatabase callback(@[[NSNull null], @{ @"result": @"success", @"path": path, + @"modifiersString": modifiersString, @"remainingListeners": [r listenerKeys], }]); } @@ -540,10 +544,9 @@ - (FIRDatabaseReference *) getRef return self.ref; } -- (FIRDatabaseReference *) getRefAtPath:(NSString *) str +- (FIRDatabaseReference *) getRefAtPath:(NSString *) path { - FirestackDBReference *r = [self getDBHandle:str]; - return [r getRef]; + return [[FIRDatabase database] referenceWithPath:path]; } // Handles @@ -555,36 +558,48 @@ - (NSDictionary *) storedDBHandles return __DBHandles; } +- (NSString *) getDBListenerKey:(NSString *) path + withModifiers:(NSString *) modifiersString +{ + return [NSString stringWithFormat:@"%@ | %@", path, modifiersString, nil]; +} + - (FirestackDBReference *) getDBHandle:(NSString *) path + withModifiers:modifiersString { NSDictionary *stored = [self storedDBHandles]; - FirestackDBReference *r = [stored objectForKey:path]; + NSString *key = [self getDBListenerKey:path withModifiers:modifiersString]; + FirestackDBReference *r = [stored objectForKey:key]; if (r == nil) { r = [[FirestackDBReference alloc] initWithPath:path]; - [self saveDBHandle:path dbRef:r]; + [self saveDBHandle:path withModifiersString:modifiersString dbRef:r]; } return r; } - (void) saveDBHandle:(NSString *) path + withModifiersString:(NSString*)modifiersString dbRef:(FirestackDBReference *) dbRef { NSMutableDictionary *stored = [[self storedDBHandles] mutableCopy]; - if ([stored objectForKey:path]) { - FirestackDBReference *r = [stored objectForKey:path]; + NSString *key = [self getDBListenerKey:path withModifiers:modifiersString]; + if ([stored objectForKey:key]) { + FirestackDBReference *r = [stored objectForKey:key]; [r cleanup]; } - [stored setObject:dbRef forKey:path]; + [stored setObject:dbRef forKey:key]; self._DBHandles = stored; } - (void) removeDBHandle:(NSString *) path + withModifiersString:(NSString*)modifiersString { NSMutableDictionary *stored = [[self storedDBHandles] mutableCopy]; + NSString *key = [self getDBListenerKey:path withModifiers:modifiersString]; - FirestackDBReference *r = [stored objectForKey:path]; + FirestackDBReference *r = [stored objectForKey:key]; if (r != nil) { [r cleanup]; } diff --git a/lib/modules/auth.js b/lib/modules/auth.js index 6963fbf..04e5775 100644 --- a/lib/modules/auth.js +++ b/lib/modules/auth.js @@ -26,13 +26,6 @@ export default class Auth extends Base { // but this is ok as we fake it with the getCurrentUser below FirestackAuthEvt.addListener('listenForAuth', this._onAuthStateChanged.bind(this)); FirestackAuth.listenForAuth(); - - this.getCurrentUser().then((u: Object) => { - this._onAuthStateChanged({ authenticated: !!u, user: u || null }); - }).catch(() => { - // todo check if error contains user disabled message maybe and add a disabled flag? - this._onAuthStateChanged({ authenticated: false, user: null }); - }); } /** diff --git a/lib/modules/database/disconnect.js b/lib/modules/database/disconnect.js index 4b1733e..4c9fdcb 100644 --- a/lib/modules/database/disconnect.js +++ b/lib/modules/database/disconnect.js @@ -1,5 +1,7 @@ +/* @flow */ import { NativeModules } from 'react-native'; +import promisify from './../../utils/promisify'; import Reference from './reference'; const FirestackDatabase = NativeModules.FirestackDatabase; diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index ece4f74..a42a046 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -5,6 +5,7 @@ import { NativeModules } from 'react-native'; import promisify from './../../utils/promisify'; import { ReferenceBase } from './../base'; import Snapshot from './snapshot.js'; +import Disconnect from './disconnect.js'; import Query from './query.js'; const FirestackDatabase = NativeModules.FirestackDatabase; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy