From 0061ad98884ad3eba9da7ca1f056fc62bced2e67 Mon Sep 17 00:00:00 2001 From: Salakar Date: Wed, 1 Aug 2018 23:00:40 +0100 Subject: [PATCH] [android][firestore] cleanup --- .../java/io/invertase/firebase/Utils.java | 17 +- .../firestore/FirestoreSerialize.java | 46 +- .../firestore/RNFirebaseFirestore.java | 535 +++++++++++------- ...NFirebaseFirestoreCollectionReference.java | 141 +++-- .../RNFirebaseFirestoreDocumentReference.java | 133 +++-- .../firestore/RNFirebaseFirestorePackage.java | 3 +- ...RNFirebaseFirestoreTransactionHandler.java | 9 +- 7 files changed, 566 insertions(+), 318 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/Utils.java b/android/src/main/java/io/invertase/firebase/Utils.java index 458ae2ec..0d8eba07 100644 --- a/android/src/main/java/io/invertase/firebase/Utils.java +++ b/android/src/main/java/io/invertase/firebase/Utils.java @@ -1,20 +1,21 @@ package io.invertase.firebase; +import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.Context; +import android.os.AsyncTask; import android.util.Log; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; + import java.util.List; import java.util.Map; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.core.DeviceEventManagerModule; - -import com.facebook.react.bridge.ReadableArray; - import javax.annotation.Nullable; diff --git a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java index 90291179..53913db9 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java +++ b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java @@ -52,18 +52,16 @@ public class FirestoreSerialize { if (documentSnapshot.exists()) { documentMap.putMap(KEY_DATA, objectMapToWritable(documentSnapshot.getData())); } - // metadata - if (documentSnapshot.getMetadata() != null) { - WritableMap metadata = Arguments.createMap(); - metadata.putBoolean("fromCache", documentSnapshot.getMetadata().isFromCache()); - metadata.putBoolean("hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites()); - documentMap.putMap(KEY_METADATA, metadata); - } + // metadata + WritableMap metadata = Arguments.createMap(); + metadata.putBoolean("fromCache", documentSnapshot.getMetadata().isFromCache()); + metadata.putBoolean("hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites()); + documentMap.putMap(KEY_METADATA, metadata); return documentMap; } - public static WritableMap snapshotToWritableMap(QuerySnapshot querySnapshot) { + static WritableMap snapshotToWritableMap(QuerySnapshot querySnapshot) { WritableMap queryMap = Arguments.createMap(); List documentChanges = querySnapshot.getDocumentChanges(); @@ -78,12 +76,10 @@ public class FirestoreSerialize { queryMap.putArray(KEY_DOCUMENTS, documents); // metadata - if (querySnapshot.getMetadata() != null) { - WritableMap metadata = Arguments.createMap(); - metadata.putBoolean("fromCache", querySnapshot.getMetadata().isFromCache()); - metadata.putBoolean("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites()); - queryMap.putMap(KEY_METADATA, metadata); - } + WritableMap metadata = Arguments.createMap(); + metadata.putBoolean("fromCache", querySnapshot.getMetadata().isFromCache()); + metadata.putBoolean("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites()); + queryMap.putMap(KEY_METADATA, metadata); return queryMap; } @@ -94,7 +90,7 @@ public class FirestoreSerialize { * @param documentChanges List * @return WritableArray */ - static WritableArray documentChangesToWritableArray(List documentChanges) { + private static WritableArray documentChangesToWritableArray(List documentChanges) { WritableArray documentChangesWritable = Arguments.createArray(); for (DocumentChange documentChange : documentChanges) { documentChangesWritable.pushMap(documentChangeToWritableMap(documentChange)); @@ -108,7 +104,7 @@ public class FirestoreSerialize { * @param documentChange DocumentChange * @return WritableMap */ - static WritableMap documentChangeToWritableMap(DocumentChange documentChange) { + private static WritableMap documentChangeToWritableMap(DocumentChange documentChange) { WritableMap documentChangeMap = Arguments.createMap(); switch (documentChange.getType()) { @@ -122,8 +118,10 @@ public class FirestoreSerialize { documentChangeMap.putString(KEY_DOC_CHANGE_TYPE, "modified"); } - documentChangeMap.putMap(KEY_DOC_CHANGE_DOCUMENT, - snapshotToWritableMap(documentChange.getDocument())); + documentChangeMap.putMap( + KEY_DOC_CHANGE_DOCUMENT, + snapshotToWritableMap(documentChange.getDocument()) + ); documentChangeMap.putInt(KEY_DOC_CHANGE_NEW_INDEX, documentChange.getNewIndex()); documentChangeMap.putInt(KEY_DOC_CHANGE_OLD_INDEX, documentChange.getOldIndex()); @@ -136,7 +134,7 @@ public class FirestoreSerialize { * @param map Map * @return WritableMap */ - static WritableMap objectMapToWritable(Map map) { + private static WritableMap objectMapToWritable(Map map) { WritableMap writableMap = Arguments.createMap(); for (Map.Entry entry : map.entrySet()) { WritableMap typeMap = buildTypeMap(entry.getValue()); @@ -224,7 +222,10 @@ public class FirestoreSerialize { return typeMap; } - static Map parseReadableMap(FirebaseFirestore firestore, ReadableMap readableMap) { + static Map parseReadableMap( + FirebaseFirestore firestore, + ReadableMap readableMap + ) { Map map = new HashMap<>(); if (readableMap != null) { ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); @@ -290,7 +291,10 @@ public class FirestoreSerialize { } } - public static List parseDocumentBatches(FirebaseFirestore firestore, ReadableArray readableArray) { + static List parseDocumentBatches( + FirebaseFirestore firestore, + ReadableArray readableArray + ) { List writes = new ArrayList<>(readableArray.size()); for (int i = 0; i < readableArray.size(); i++) { Map write = new HashMap<>(); diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java index 9387d275..d0d61fbc 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java @@ -18,13 +18,13 @@ 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.firestore.FirebaseFirestoreSettings; -import com.google.firebase.firestore.Transaction; import com.google.firebase.firestore.DocumentReference; import com.google.firebase.firestore.FieldValue; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.FirebaseFirestoreException; +import com.google.firebase.firestore.FirebaseFirestoreSettings; import com.google.firebase.firestore.SetOptions; +import com.google.firebase.firestore.Transaction; import com.google.firebase.firestore.WriteBatch; import java.util.HashMap; @@ -48,6 +48,184 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { * REACT NATIVE METHODS */ + /** + * Generates a js-like error from an exception and rejects the provided promise with it. + * + * @param exception Exception Exception normally from a task result. + * @param promise Promise react native promise + */ + static void promiseRejectException(Promise promise, FirebaseFirestoreException exception) { + WritableMap jsError = getJSError(exception); + promise.reject( + jsError.getString("code"), + jsError.getString("message"), + exception + ); + } + + /** + * Get a database instance for a specific firebase app instance + * + * @param appName appName + * @return FirebaseFirestore + */ + static FirebaseFirestore getFirestoreForApp(String appName) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + return FirebaseFirestore.getInstance(firebaseApp); + } + + /** + * Convert as firebase DatabaseError instance into a writable map + * with the correct web-like error codes. + * + * @param nativeException nativeException + * @return WritableMap + */ + static WritableMap getJSError(FirebaseFirestoreException nativeException) { + WritableMap errorMap = Arguments.createMap(); + errorMap.putInt("nativeErrorCode", nativeException.getCode().value()); + errorMap.putString("nativeErrorMessage", nativeException.getMessage()); + + String code; + String message; + String service = "Firestore"; + + // TODO: Proper error mappings + switch (nativeException.getCode()) { + case OK: + code = ErrorUtils.getCodeWithService(service, "ok"); + message = ErrorUtils.getMessageWithService("Ok.", service, code); + break; + case CANCELLED: + code = ErrorUtils.getCodeWithService(service, "cancelled"); + message = ErrorUtils.getMessageWithService("The operation was cancelled.", service, code); + break; + case UNKNOWN: + code = ErrorUtils.getCodeWithService(service, "unknown"); + message = ErrorUtils.getMessageWithService( + "Unknown error or an error from a different error domain.", + service, + code + ); + break; + case INVALID_ARGUMENT: + code = ErrorUtils.getCodeWithService(service, "invalid-argument"); + message = ErrorUtils.getMessageWithService( + "Client specified an invalid argument.", + service, + code + ); + break; + case DEADLINE_EXCEEDED: + code = ErrorUtils.getCodeWithService(service, "deadline-exceeded"); + message = ErrorUtils.getMessageWithService( + "Deadline expired before operation could complete.", + service, + code + ); + break; + case NOT_FOUND: + code = ErrorUtils.getCodeWithService(service, "not-found"); + message = ErrorUtils.getMessageWithService( + "Some requested document was not found.", + service, + code + ); + break; + case ALREADY_EXISTS: + code = ErrorUtils.getCodeWithService(service, "already-exists"); + message = ErrorUtils.getMessageWithService( + "Some document that we attempted to create already exists.", + service, + code + ); + break; + case PERMISSION_DENIED: + code = ErrorUtils.getCodeWithService(service, "permission-denied"); + message = ErrorUtils.getMessageWithService( + "The caller does not have permission to execute the specified operation.", + service, + code + ); + break; + case RESOURCE_EXHAUSTED: + code = ErrorUtils.getCodeWithService(service, "resource-exhausted"); + message = ErrorUtils.getMessageWithService( + "Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.", + service, + code + ); + break; + case FAILED_PRECONDITION: + code = ErrorUtils.getCodeWithService(service, "failed-precondition"); + message = ErrorUtils.getMessageWithService( + "Operation was rejected because the system is not in a state required for the operation`s execution.", + service, + code + ); + break; + case ABORTED: + code = ErrorUtils.getCodeWithService(service, "aborted"); + message = ErrorUtils.getMessageWithService( + "The operation was aborted, typically due to a concurrency issue like transaction aborts, etc.", + service, + code + ); + break; + case OUT_OF_RANGE: + code = ErrorUtils.getCodeWithService(service, "out-of-range"); + message = ErrorUtils.getMessageWithService( + "Operation was attempted past the valid range.", + service, + code + ); + break; + case UNIMPLEMENTED: + code = ErrorUtils.getCodeWithService(service, "unimplemented"); + message = ErrorUtils.getMessageWithService( + "Operation is not implemented or not supported/enabled.", + service, + code + ); + break; + case INTERNAL: + code = ErrorUtils.getCodeWithService(service, "internal"); + message = ErrorUtils.getMessageWithService("Internal errors.", service, code); + break; + case UNAVAILABLE: + code = ErrorUtils.getCodeWithService(service, "unavailable"); + message = ErrorUtils.getMessageWithService( + "The service is currently unavailable.", + service, + code + ); + break; + case DATA_LOSS: + code = ErrorUtils.getCodeWithService(service, "data-loss"); + message = ErrorUtils.getMessageWithService( + "Unrecoverable data loss or corruption.", + service, + code + ); + break; + case UNAUTHENTICATED: + code = ErrorUtils.getCodeWithService(service, "unauthenticated"); + message = ErrorUtils.getMessageWithService( + "The request does not have valid authentication credentials for the operation.", + service, + code + ); + break; + default: + code = ErrorUtils.getCodeWithService(service, "unknown"); + message = ErrorUtils.getMessageWithService("An unknown error occurred.", service, code); + } + + errorMap.putString("code", code); + errorMap.putString("message", message); + return errorMap; + } + @ReactMethod public void disableNetwork(String appName, final Promise promise) { getFirestoreForApp(appName).disableNetwork().addOnCompleteListener(new OnCompleteListener() { @@ -58,7 +236,10 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { promise.resolve(null); } else { Log.e(TAG, "disableNetwork:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); @@ -83,35 +264,55 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { promise.resolve(null); } else { Log.e(TAG, "enableNetwork:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); } @ReactMethod - public void collectionGet(String appName, String path, ReadableArray filters, - ReadableArray orders, ReadableMap options, ReadableMap getOptions, - final Promise promise) { - RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options); + public void collectionGet( + String appName, String path, ReadableArray filters, + ReadableArray orders, ReadableMap options, ReadableMap getOptions, + final Promise promise + ) { + RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath( + appName, + path, + filters, + orders, + options + ); ref.get(getOptions, promise); } @ReactMethod - public void collectionOffSnapshot(String appName, String path, ReadableArray filters, - ReadableArray orders, ReadableMap options, String listenerId) { + public void collectionOffSnapshot( + String appName, String path, ReadableArray filters, + ReadableArray orders, ReadableMap options, String listenerId + ) { RNFirebaseFirestoreCollectionReference.offSnapshot(listenerId); } @ReactMethod - public void collectionOnSnapshot(String appName, String path, ReadableArray filters, - ReadableArray orders, ReadableMap options, String listenerId, - ReadableMap queryListenOptions) { - RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options); + public void collectionOnSnapshot( + String appName, String path, ReadableArray filters, + ReadableArray orders, ReadableMap options, String listenerId, + ReadableMap queryListenOptions + ) { + RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath( + appName, + path, + filters, + orders, + options + ); ref.onSnapshot(listenerId, queryListenOptions); } - @ReactMethod public void documentBatch(final String appName, final ReadableArray writes, final Promise promise) { @@ -166,7 +367,12 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { } @ReactMethod - public void documentGet(String appName, String path, ReadableMap getOptions, final Promise promise) { + public void documentGet( + String appName, + String path, + ReadableMap getOptions, + final Promise promise + ) { RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path); ref.get(getOptions, promise); } @@ -177,18 +383,31 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { } @ReactMethod - public void documentOnSnapshot(String appName, String path, String listenerId, - ReadableMap docListenOptions) { + public void documentOnSnapshot( + String appName, String path, String listenerId, + ReadableMap docListenOptions + ) { RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path); ref.onSnapshot(listenerId, docListenOptions); } @ReactMethod - public void documentSet(String appName, String path, ReadableMap data, ReadableMap options, final Promise promise) { + public void documentSet( + String appName, + String path, + ReadableMap data, + ReadableMap options, + final Promise promise + ) { RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path); ref.set(data, options, promise); } + + /* + * Transaction Methods + */ + @ReactMethod public void documentUpdate(String appName, String path, ReadableMap data, final Promise promise) { RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path); @@ -214,18 +433,17 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { } else { firestoreSettings.setSslEnabled(firestore.getFirestoreSettings().isSslEnabled()); } - if (settings.hasKey("timestampsInSnapshots")) { - // TODO: Not supported on Android yet - } + +// if (settings.hasKey("timestampsInSnapshots")) { +// // TODO: Not supported on Android yet +// } firestore.setFirestoreSettings(firestoreSettings.build()); promise.resolve(null); } - /** * Try clean up previous transactions on reload - * */ @Override public void onCatalystInstanceDestroy() { @@ -239,23 +457,22 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { transactionHandlers.clear(); } - - /* - * Transaction Methods - */ - - /** * Calls the internal Firestore Transaction classes instance .get(ref) method and resolves with * the DocumentSnapshot. * - * @param appName - * @param transactionId - * @param path - * @param promise + * @param appName appName + * @param transactionId transactionId + * @param path path + * @param promise promise */ @ReactMethod - public void transactionGetDocument(String appName, int transactionId, String path, final Promise promise) { + public void transactionGetDocument( + String appName, + int transactionId, + String path, + final Promise promise + ) { RNFirebaseFirestoreTransactionHandler handler = transactionHandlers.get(transactionId); if (handler == null) { @@ -269,11 +486,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { } } + + /* + * INTERNALS/UTILS + */ + /** * Aborts any pending signals and deletes the transaction handler. * - * @param appName - * @param transactionId + * @param appName appName + * @param transactionId transactionId */ @ReactMethod public void transactionDispose(String appName, int transactionId) { @@ -288,12 +510,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { /** * Signals to transactionHandler that the command buffer is ready. * - * @param appName - * @param transactionId - * @param commandBuffer + * @param appName appName + * @param transactionId transactionId + * @param commandBuffer commandBuffer */ @ReactMethod - public void transactionApplyBuffer(String appName, int transactionId, ReadableArray commandBuffer) { + public void transactionApplyBuffer( + String appName, + int transactionId, + ReadableArray commandBuffer + ) { RNFirebaseFirestoreTransactionHandler handler = transactionHandlers.get(transactionId); if (handler != null) { @@ -304,12 +530,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { /** * Begin a new transaction via AsyncTask 's * - * @param appName - * @param transactionId + * @param appName appName + * @param transactionId transactionId */ @ReactMethod public void transactionBegin(final String appName, int transactionId) { - final RNFirebaseFirestoreTransactionHandler transactionHandler = new RNFirebaseFirestoreTransactionHandler(appName, transactionId); + final RNFirebaseFirestoreTransactionHandler transactionHandler = new RNFirebaseFirestoreTransactionHandler( + appName, + transactionId + ); + transactionHandlers.put(transactionId, transactionHandler); AsyncTask.execute(new Runnable() { @@ -327,7 +557,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { @Override public void run() { WritableMap eventMap = transactionHandler.createEventMap(null, "update"); - Utils.sendEvent(getReactApplicationContext(), "firestore_transaction_event", eventMap); + Utils.sendEvent( + getReactApplicationContext(), + "firestore_transaction_event", + eventMap + ); } }); @@ -336,12 +570,18 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { // exit early if aborted - has to throw an exception otherwise will just keep trying ... if (transactionHandler.aborted) { - throw new FirebaseFirestoreException("abort", FirebaseFirestoreException.Code.ABORTED); + throw new FirebaseFirestoreException( + "abort", + FirebaseFirestoreException.Code.ABORTED + ); } // exit early if timeout from bridge - has to throw an exception otherwise will just keep trying ... if (transactionHandler.timeout) { - throw new FirebaseFirestoreException("timeout", FirebaseFirestoreException.Code.DEADLINE_EXCEEDED); + throw new FirebaseFirestoreException( + "timeout", + FirebaseFirestoreException.Code.DEADLINE_EXCEEDED + ); } // process any buffered commands from JS land @@ -357,15 +597,19 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { ReadableMap command = buffer.getMap(i); String path = command.getString("path"); String type = command.getString("type"); - RNFirebaseFirestoreDocumentReference documentReference = getDocumentForAppPath(appName, path); - + RNFirebaseFirestoreDocumentReference documentReference = getDocumentForAppPath( + appName, + path + ); switch (type) { case "set": data = command.getMap("data"); - ReadableMap options = command.getMap("options"); - Map setData = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data); + Map setData = FirestoreSerialize.parseReadableMap( + RNFirebaseFirestore.getFirestoreForApp(appName), + data + ); if (options != null && options.hasKey("merge") && options.getBoolean("merge")) { transaction.set(documentReference.getRef(), setData, SetOptions.merge()); @@ -376,7 +620,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { case "update": data = command.getMap("data"); - Map updateData = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data); + Map updateData = FirestoreSerialize.parseReadableMap( + RNFirebaseFirestore.getFirestoreForApp(appName), + data + ); + transaction.update(documentReference.getRef(), updateData); break; case "delete": @@ -396,7 +644,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { if (!transactionHandler.aborted) { Log.d(TAG, "Transaction onSuccess!"); WritableMap eventMap = transactionHandler.createEventMap(null, "complete"); - Utils.sendEvent(getReactApplicationContext(), "firestore_transaction_event", eventMap); + Utils.sendEvent( + getReactApplicationContext(), + "firestore_transaction_event", + eventMap + ); } } }) @@ -405,8 +657,15 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { public void onFailure(@NonNull Exception e) { if (!transactionHandler.aborted) { Log.w(TAG, "Transaction onFailure.", e); - WritableMap eventMap = transactionHandler.createEventMap((FirebaseFirestoreException) e, "error"); - Utils.sendEvent(getReactApplicationContext(), "firestore_transaction_event", eventMap); + WritableMap eventMap = transactionHandler.createEventMap( + (FirebaseFirestoreException) e, + "error" + ); + Utils.sendEvent( + getReactApplicationContext(), + "firestore_transaction_event", + eventMap + ); } } }); @@ -414,158 +673,44 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { }); } - - /* - * INTERNALS/UTILS - */ - - /** - * Generates a js-like error from an exception and rejects the provided promise with it. - * - * @param exception Exception Exception normally from a task result. - * @param promise Promise react native promise - */ - static void promiseRejectException(Promise promise, FirebaseFirestoreException exception) { - WritableMap jsError = getJSError(exception); - promise.reject( - jsError.getString("code"), - jsError.getString("message"), - exception - ); - } - - /** - * Get a database instance for a specific firebase app instance - * - * @param appName - * @return - */ - static FirebaseFirestore getFirestoreForApp(String appName) { - FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); - return FirebaseFirestore.getInstance(firebaseApp); - } - /** * Get a collection reference for a specific app and path * - * @param appName - * @param filters - * @param orders - * @param options + * @param appName appName + * @param filters filters + * @param orders orders + * @param options options * @param path @return */ - private RNFirebaseFirestoreCollectionReference getCollectionForAppPath(String appName, String path, - ReadableArray filters, - ReadableArray orders, - ReadableMap options) { - return new RNFirebaseFirestoreCollectionReference(this.getReactApplicationContext(), appName, path, filters, orders, options); + private RNFirebaseFirestoreCollectionReference getCollectionForAppPath( + String appName, String path, + ReadableArray filters, + ReadableArray orders, + ReadableMap options + ) { + return new RNFirebaseFirestoreCollectionReference( + this.getReactApplicationContext(), + appName, + path, + filters, + orders, + options + ); } /** * Get a document reference for a specific app and path * - * @param appName - * @param path - * @return + * @param appName appName + * @param path path + * @return RNFirebaseFirestoreDocumentReference */ private RNFirebaseFirestoreDocumentReference getDocumentForAppPath(String appName, String path) { - return new RNFirebaseFirestoreDocumentReference(this.getReactApplicationContext(), appName, path); - } - - /** - * Convert as firebase DatabaseError instance into a writable map - * with the correct web-like error codes. - * - * @param nativeException - * @return - */ - static WritableMap getJSError(FirebaseFirestoreException nativeException) { - WritableMap errorMap = Arguments.createMap(); - errorMap.putInt("nativeErrorCode", nativeException.getCode().value()); - errorMap.putString("nativeErrorMessage", nativeException.getMessage()); - - String code; - String message; - String service = "Firestore"; - - // TODO: Proper error mappings - switch (nativeException.getCode()) { - case OK: - code = ErrorUtils.getCodeWithService(service, "ok"); - message = ErrorUtils.getMessageWithService("Ok.", service, code); - break; - case CANCELLED: - code = ErrorUtils.getCodeWithService(service, "cancelled"); - message = ErrorUtils.getMessageWithService("The operation was cancelled.", service, code); - break; - case UNKNOWN: - code = ErrorUtils.getCodeWithService(service, "unknown"); - message = ErrorUtils.getMessageWithService("Unknown error or an error from a different error domain.", service, code); - break; - case INVALID_ARGUMENT: - code = ErrorUtils.getCodeWithService(service, "invalid-argument"); - message = ErrorUtils.getMessageWithService("Client specified an invalid argument.", service, code); - break; - case DEADLINE_EXCEEDED: - code = ErrorUtils.getCodeWithService(service, "deadline-exceeded"); - message = ErrorUtils.getMessageWithService("Deadline expired before operation could complete.", service, code); - break; - case NOT_FOUND: - code = ErrorUtils.getCodeWithService(service, "not-found"); - message = ErrorUtils.getMessageWithService("Some requested document was not found.", service, code); - break; - case ALREADY_EXISTS: - code = ErrorUtils.getCodeWithService(service, "already-exists"); - message = ErrorUtils.getMessageWithService("Some document that we attempted to create already exists.", service, code); - break; - case PERMISSION_DENIED: - code = ErrorUtils.getCodeWithService(service, "permission-denied"); - message = ErrorUtils.getMessageWithService("The caller does not have permission to execute the specified operation.", service, code); - break; - case RESOURCE_EXHAUSTED: - code = ErrorUtils.getCodeWithService(service, "resource-exhausted"); - message = ErrorUtils.getMessageWithService("Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.", service, code); - break; - case FAILED_PRECONDITION: - code = ErrorUtils.getCodeWithService(service, "failed-precondition"); - message = ErrorUtils.getMessageWithService("Operation was rejected because the system is not in a state required for the operation`s execution.", service, code); - break; - case ABORTED: - code = ErrorUtils.getCodeWithService(service, "aborted"); - message = ErrorUtils.getMessageWithService("The operation was aborted, typically due to a concurrency issue like transaction aborts, etc.", service, code); - break; - case OUT_OF_RANGE: - code = ErrorUtils.getCodeWithService(service, "out-of-range"); - message = ErrorUtils.getMessageWithService("Operation was attempted past the valid range.", service, code); - break; - case UNIMPLEMENTED: - code = ErrorUtils.getCodeWithService(service, "unimplemented"); - message = ErrorUtils.getMessageWithService("Operation is not implemented or not supported/enabled.", service, code); - break; - case INTERNAL: - code = ErrorUtils.getCodeWithService(service, "internal"); - message = ErrorUtils.getMessageWithService("Internal errors.", service, code); - break; - case UNAVAILABLE: - code = ErrorUtils.getCodeWithService(service, "unavailable"); - message = ErrorUtils.getMessageWithService("The service is currently unavailable.", service, code); - break; - case DATA_LOSS: - code = ErrorUtils.getCodeWithService(service, "data-loss"); - message = ErrorUtils.getMessageWithService("Unrecoverable data loss or corruption.", service, code); - break; - case UNAUTHENTICATED: - code = ErrorUtils.getCodeWithService(service, "unauthenticated"); - message = ErrorUtils.getMessageWithService("The request does not have valid authentication credentials for the operation.", service, code); - break; - default: - code = ErrorUtils.getCodeWithService(service, "unknown"); - message = ErrorUtils.getMessageWithService("An unknown error occurred.", service, code); - } - - errorMap.putString("code", code); - errorMap.putString("message", message); - return errorMap; + return new RNFirebaseFirestoreDocumentReference( + this.getReactApplicationContext(), + appName, + path + ); } /** diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreCollectionReference.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreCollectionReference.java index 548f942f..b251ec5f 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreCollectionReference.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreCollectionReference.java @@ -1,6 +1,7 @@ package io.invertase.firebase.firestore; +import android.annotation.SuppressLint; import android.support.annotation.NonNull; import android.util.Log; @@ -22,28 +23,32 @@ import com.google.firebase.firestore.Query; import com.google.firebase.firestore.QuerySnapshot; import com.google.firebase.firestore.Source; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import io.invertase.firebase.Utils; -public class RNFirebaseFirestoreCollectionReference { +class RNFirebaseFirestoreCollectionReference { private static final String TAG = "RNFSCollectionReference"; private static Map collectionSnapshotListeners = new HashMap<>(); - private final String appName; private final String path; - private final ReadableArray filters; - private final ReadableArray orders; - private final ReadableMap options; private final Query query; + private final String appName; + private final ReadableMap options; + private final ReadableArray orders; + private final ReadableArray filters; private ReactContext reactContext; - RNFirebaseFirestoreCollectionReference(ReactContext reactContext, String appName, String path, - ReadableArray filters, ReadableArray orders, - ReadableMap options) { + RNFirebaseFirestoreCollectionReference( + ReactContext reactContext, + String appName, + String path, + ReadableArray filters, + ReadableArray orders, + ReadableMap options + ) { this.appName = appName; this.path = path; this.filters = filters; @@ -53,6 +58,13 @@ public class RNFirebaseFirestoreCollectionReference { this.reactContext = reactContext; } + static void offSnapshot(final String listenerId) { + ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId); + if (listenerRegistration != null) { + listenerRegistration.remove(); + } + } + void get(ReadableMap getOptions, final Promise promise) { Source source; if (getOptions != null && getOptions.hasKey("source")) { @@ -67,29 +79,34 @@ public class RNFirebaseFirestoreCollectionReference { } else { source = Source.DEFAULT; } + + @SuppressLint("StaticFieldLeak") final QuerySnapshotSerializeAsyncTask serializeAsyncTask = new QuerySnapshotSerializeAsyncTask( + reactContext, this + ) { + @Override + protected void onPostExecute(WritableMap writableMap) { + promise.resolve(writableMap); + } + }; + query.get(source).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "get:onComplete:success"); - WritableMap data = FirestoreSerialize.snapshotToWritableMap(task.getResult()); - promise.resolve(data); + serializeAsyncTask.execute(task.getResult()); } else { Log.e(TAG, "get:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); } - public static void offSnapshot(final String listenerId) { - ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId); - if (listenerRegistration != null) { - listenerRegistration.remove(); - } - } - - public void onSnapshot(final String listenerId, final ReadableMap queryListenOptions) { + void onSnapshot(final String listenerId, final ReadableMap queryListenOptions) { if (!collectionSnapshotListeners.containsKey(listenerId)) { final EventListener listener = new EventListener() { @Override @@ -97,7 +114,8 @@ public class RNFirebaseFirestoreCollectionReference { if (exception == null) { handleQuerySnapshotEvent(listenerId, querySnapshot); } else { - ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId); + ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove( + listenerId); if (listenerRegistration != null) { listenerRegistration.remove(); } @@ -115,7 +133,10 @@ public class RNFirebaseFirestoreCollectionReference { metadataChanges = MetadataChanges.EXCLUDE; } - ListenerRegistration listenerRegistration = this.query.addSnapshotListener(metadataChanges, listener); + ListenerRegistration listenerRegistration = this.query.addSnapshotListener( + metadataChanges, + listener + ); collectionSnapshotListeners.put(listenerId, listenerRegistration); } } @@ -170,7 +191,7 @@ public class RNFirebaseFirestoreCollectionReference { } else { ReadableArray fieldPathElements = fieldPathMap.getArray("elements"); String[] fieldPathArray = new String[fieldPathElements.size()]; - for (int j=0; j order = (Map) o; String direction = (String) order.get("direction"); Map fieldPathMap = (Map) order.get("fieldPath"); - String fieldPathType = (String)fieldPathMap.get("type"); + String fieldPathType = (String) fieldPathMap.get("type"); if (fieldPathType.equals("string")) { - String fieldPath = (String)fieldPathMap.get("string"); + String fieldPath = (String) fieldPathMap.get("string"); query = query.orderBy(fieldPath, Query.Direction.valueOf(direction)); } else { - List fieldPathElements = (List)fieldPathMap.get("elements"); + List fieldPathElements = (List) fieldPathMap.get("elements"); FieldPath fieldPath = FieldPath.of(fieldPathElements.toArray(new String[fieldPathElements.size()])); query = query.orderBy(fieldPath, Query.Direction.valueOf(direction)); } @@ -218,57 +239,79 @@ public class RNFirebaseFirestoreCollectionReference { private Query applyOptions(FirebaseFirestore firestore, Query query) { if (options.hasKey("endAt")) { - List endAtList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endAt")); + List endAtList = FirestoreSerialize.parseReadableArray( + firestore, + options.getArray("endAt") + ); query = query.endAt(endAtList.toArray()); } + if (options.hasKey("endBefore")) { - List endBeforeList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endBefore")); + List endBeforeList = FirestoreSerialize.parseReadableArray( + firestore, + options.getArray("endBefore") + ); query = query.endBefore(endBeforeList.toArray()); } + if (options.hasKey("limit")) { int limit = options.getInt("limit"); query = query.limit(limit); } - if (options.hasKey("offset")) { - // Android doesn't support offset - } - if (options.hasKey("selectFields")) { - // Android doesn't support selectFields - } +// if (options.hasKey("offset")) { + // Android doesn't support offset +// } +// if (options.hasKey("selectFields")) { + // Android doesn't support selectFields +// } if (options.hasKey("startAfter")) { - List startAfterList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAfter")); + List startAfterList = FirestoreSerialize.parseReadableArray( + firestore, + options.getArray("startAfter") + ); query = query.startAfter(startAfterList.toArray()); } + if (options.hasKey("startAt")) { - List startAtList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAt")); + List startAtList = FirestoreSerialize.parseReadableArray( + firestore, + options.getArray("startAt") + ); query = query.startAt(startAtList.toArray()); } + return query; } /** * Handles documentSnapshot events. * - * @param listenerId - * @param querySnapshot + * @param listenerId id + * @param querySnapshot snapshot */ - private void handleQuerySnapshotEvent(String listenerId, QuerySnapshot querySnapshot) { - WritableMap event = Arguments.createMap(); - WritableMap data = FirestoreSerialize.snapshotToWritableMap(querySnapshot); + private void handleQuerySnapshotEvent(final String listenerId, QuerySnapshot querySnapshot) { + @SuppressLint("StaticFieldLeak") final QuerySnapshotSerializeAsyncTask serializeAsyncTask = new QuerySnapshotSerializeAsyncTask( + reactContext, this + ) { + @Override + protected void onPostExecute(WritableMap writableMap) { + WritableMap event = Arguments.createMap(); + event.putString("path", path); + event.putString("appName", appName); + event.putString("listenerId", listenerId); + event.putMap("querySnapshot", writableMap); + Utils.sendEvent(reactContext, "firestore_collection_sync_event", event); + } + }; - event.putString("appName", appName); - event.putString("path", path); - event.putString("listenerId", listenerId); - event.putMap("querySnapshot", data); - - Utils.sendEvent(reactContext, "firestore_collection_sync_event", event); + serializeAsyncTask.execute(querySnapshot); } /** * Handles a documentSnapshot error event * - * @param listenerId - * @param exception + * @param listenerId id + * @param exception exception */ private void handleQuerySnapshotError(String listenerId, FirebaseFirestoreException exception) { WritableMap event = Arguments.createMap(); diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java index ebb87a8d..2690afa1 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java @@ -1,5 +1,6 @@ package io.invertase.firebase.firestore; +import android.annotation.SuppressLint; import android.support.annotation.NonNull; import android.util.Log; @@ -31,17 +32,24 @@ public class RNFirebaseFirestoreDocumentReference { private final String appName; private final String path; - private ReactContext reactContext; private final DocumentReference ref; + private ReactContext reactContext; RNFirebaseFirestoreDocumentReference(ReactContext reactContext, String appName, String path) { - this.appName = appName; this.path = path; + this.appName = appName; this.reactContext = reactContext; this.ref = RNFirebaseFirestore.getFirestoreForApp(appName).document(path); } - public void delete(final Promise promise) { + static void offSnapshot(final String listenerId) { + ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId); + if (listenerRegistration != null) { + listenerRegistration.remove(); + } + } + + void delete(final Promise promise) { this.ref.delete().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -50,7 +58,10 @@ public class RNFirebaseFirestoreDocumentReference { promise.resolve(null); } else { Log.e(TAG, "delete:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); @@ -58,6 +69,7 @@ public class RNFirebaseFirestoreDocumentReference { void get(final ReadableMap getOptions, final Promise promise) { Source source; + if (getOptions != null && getOptions.hasKey("source")) { String optionsSource = getOptions.getString("source"); if ("server".equals(optionsSource)) { @@ -70,45 +82,57 @@ public class RNFirebaseFirestoreDocumentReference { } else { source = Source.DEFAULT; } + + @SuppressLint("StaticFieldLeak") final DocumentSnapshotSerializeAsyncTask serializeAsyncTask = new DocumentSnapshotSerializeAsyncTask( + reactContext, this + ) { + @Override + protected void onPostExecute(WritableMap writableMap) { + promise.resolve(writableMap); + } + }; + this.ref.get(source).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Log.d(TAG, "get:onComplete:success"); - WritableMap data = FirestoreSerialize.snapshotToWritableMap(task.getResult()); - promise.resolve(data); + serializeAsyncTask.execute(task.getResult()); } else { Log.e(TAG, "get:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); } - public static void offSnapshot(final String listenerId) { - ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId); - if (listenerRegistration != null) { - listenerRegistration.remove(); - } - } - - public void onSnapshot(final String listenerId, final ReadableMap docListenOptions) { + void onSnapshot(final String listenerId, final ReadableMap docListenOptions) { if (!documentSnapshotListeners.containsKey(listenerId)) { final EventListener listener = new EventListener() { @Override - public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException exception) { + public void onEvent( + DocumentSnapshot documentSnapshot, + FirebaseFirestoreException exception + ) { if (exception == null) { handleDocumentSnapshotEvent(listenerId, documentSnapshot); } else { ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId); + if (listenerRegistration != null) { listenerRegistration.remove(); } + handleDocumentSnapshotError(listenerId, exception); } } }; + MetadataChanges metadataChanges; + if (docListenOptions != null && docListenOptions.hasKey("includeMetadataChanges") && docListenOptions.getBoolean("includeMetadataChanges")) { @@ -116,19 +140,30 @@ public class RNFirebaseFirestoreDocumentReference { } else { metadataChanges = MetadataChanges.EXCLUDE; } - ListenerRegistration listenerRegistration = this.ref.addSnapshotListener(metadataChanges, listener); + + ListenerRegistration listenerRegistration = this.ref.addSnapshotListener( + metadataChanges, + listener + ); + documentSnapshotListeners.put(listenerId, listenerRegistration); } } public void set(final ReadableMap data, final ReadableMap options, final Promise promise) { - Map map = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data); Task task; + + Map map = FirestoreSerialize.parseReadableMap( + RNFirebaseFirestore.getFirestoreForApp(appName), + data + ); + if (options != null && options.hasKey("merge") && options.getBoolean("merge")) { task = this.ref.set(map, SetOptions.merge()); } else { task = this.ref.set(map); } + task.addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -137,14 +172,21 @@ public class RNFirebaseFirestoreDocumentReference { promise.resolve(null); } else { Log.e(TAG, "set:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); } - public void update(final ReadableMap data, final Promise promise) { - Map map = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data); + void update(final ReadableMap data, final Promise promise) { + Map map = FirestoreSerialize.parseReadableMap( + RNFirebaseFirestore.getFirestoreForApp(appName), + data + ); + this.ref.update(map).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -153,7 +195,10 @@ public class RNFirebaseFirestoreDocumentReference { promise.resolve(null); } else { Log.e(TAG, "update:onComplete:failure", task.getException()); - RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException()); + RNFirebaseFirestore.promiseRejectException( + promise, + (FirebaseFirestoreException) task.getException() + ); } } }); @@ -163,7 +208,7 @@ public class RNFirebaseFirestoreDocumentReference { * INTERNALS/UTILS */ - public DocumentReference getRef() { + DocumentReference getRef() { return ref; } @@ -174,32 +219,44 @@ public class RNFirebaseFirestoreDocumentReference { /** * Handles documentSnapshot events. * - * @param listenerId - * @param documentSnapshot + * @param listenerId id + * @param documentSnapshot snapshot */ - private void handleDocumentSnapshotEvent(String listenerId, DocumentSnapshot documentSnapshot) { - WritableMap event = Arguments.createMap(); - WritableMap data = FirestoreSerialize.snapshotToWritableMap(documentSnapshot); + private void handleDocumentSnapshotEvent( + final String listenerId, + DocumentSnapshot documentSnapshot + ) { + @SuppressLint("StaticFieldLeak") final DocumentSnapshotSerializeAsyncTask serializeAsyncTask = new DocumentSnapshotSerializeAsyncTask( + reactContext, this + ) { + @Override + protected void onPostExecute(WritableMap writableMap) { + WritableMap event = Arguments.createMap(); + event.putString("path", path); + event.putString("appName", appName); + event.putString("listenerId", listenerId); + event.putMap("documentSnapshot", writableMap); + Utils.sendEvent(reactContext, "firestore_document_sync_event", event); + } + }; - event.putString("appName", appName); - event.putString("path", path); - event.putString("listenerId", listenerId); - event.putMap("documentSnapshot", data); - - Utils.sendEvent(reactContext, "firestore_document_sync_event", event); + serializeAsyncTask.execute(documentSnapshot); } /** * Handles a documentSnapshot error event * - * @param listenerId - * @param exception + * @param listenerId id + * @param exception exception */ - private void handleDocumentSnapshotError(String listenerId, FirebaseFirestoreException exception) { + private void handleDocumentSnapshotError( + String listenerId, + FirebaseFirestoreException exception + ) { WritableMap event = Arguments.createMap(); - event.putString("appName", appName); event.putString("path", path); + event.putString("appName", appName); event.putString("listenerId", listenerId); event.putMap("error", RNFirebaseFirestore.getJSError(exception)); diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestorePackage.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestorePackage.java index f971daea..22629c35 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestorePackage.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestorePackage.java @@ -1,7 +1,6 @@ package io.invertase.firebase.firestore; import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.UIManagerModule; @@ -29,7 +28,7 @@ public class RNFirebaseFirestorePackage implements ReactPackage { } /** - * @param reactContext + * @param reactContext reactContext * @return a list of view managers that should be registered with {@link UIManagerModule} */ @Override diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreTransactionHandler.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreTransactionHandler.java index ef136ed7..dd908eb8 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreTransactionHandler.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreTransactionHandler.java @@ -17,17 +17,16 @@ import javax.annotation.Nullable; class RNFirebaseFirestoreTransactionHandler { + private final ReentrantLock lock; + private final Condition condition; + boolean aborted = false; + boolean timeout = false; private String appName; private long timeoutAt; private int transactionId; - private final ReentrantLock lock; - private final Condition condition; private ReadableArray commandBuffer; private Transaction firestoreTransaction; - boolean aborted = false; - boolean timeout = false; - RNFirebaseFirestoreTransactionHandler(String app, int id) { appName = app; transactionId = id;