[android][firestore] cleanup
This commit is contained in:
parent
e7e89732c0
commit
0061ad9888
@ -1,20 +1,21 @@
|
|||||||
package io.invertase.firebase;
|
package io.invertase.firebase;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.util.Log;
|
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.List;
|
||||||
import java.util.Map;
|
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;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,18 +52,16 @@ public class FirestoreSerialize {
|
|||||||
if (documentSnapshot.exists()) {
|
if (documentSnapshot.exists()) {
|
||||||
documentMap.putMap(KEY_DATA, objectMapToWritable(documentSnapshot.getData()));
|
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;
|
return documentMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WritableMap snapshotToWritableMap(QuerySnapshot querySnapshot) {
|
static WritableMap snapshotToWritableMap(QuerySnapshot querySnapshot) {
|
||||||
WritableMap queryMap = Arguments.createMap();
|
WritableMap queryMap = Arguments.createMap();
|
||||||
|
|
||||||
List<DocumentChange> documentChanges = querySnapshot.getDocumentChanges();
|
List<DocumentChange> documentChanges = querySnapshot.getDocumentChanges();
|
||||||
@ -78,12 +76,10 @@ public class FirestoreSerialize {
|
|||||||
queryMap.putArray(KEY_DOCUMENTS, documents);
|
queryMap.putArray(KEY_DOCUMENTS, documents);
|
||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
if (querySnapshot.getMetadata() != null) {
|
WritableMap metadata = Arguments.createMap();
|
||||||
WritableMap metadata = Arguments.createMap();
|
metadata.putBoolean("fromCache", querySnapshot.getMetadata().isFromCache());
|
||||||
metadata.putBoolean("fromCache", querySnapshot.getMetadata().isFromCache());
|
metadata.putBoolean("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites());
|
||||||
metadata.putBoolean("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites());
|
queryMap.putMap(KEY_METADATA, metadata);
|
||||||
queryMap.putMap(KEY_METADATA, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryMap;
|
return queryMap;
|
||||||
}
|
}
|
||||||
@ -94,7 +90,7 @@ public class FirestoreSerialize {
|
|||||||
* @param documentChanges List<DocumentChange>
|
* @param documentChanges List<DocumentChange>
|
||||||
* @return WritableArray
|
* @return WritableArray
|
||||||
*/
|
*/
|
||||||
static WritableArray documentChangesToWritableArray(List<DocumentChange> documentChanges) {
|
private static WritableArray documentChangesToWritableArray(List<DocumentChange> documentChanges) {
|
||||||
WritableArray documentChangesWritable = Arguments.createArray();
|
WritableArray documentChangesWritable = Arguments.createArray();
|
||||||
for (DocumentChange documentChange : documentChanges) {
|
for (DocumentChange documentChange : documentChanges) {
|
||||||
documentChangesWritable.pushMap(documentChangeToWritableMap(documentChange));
|
documentChangesWritable.pushMap(documentChangeToWritableMap(documentChange));
|
||||||
@ -108,7 +104,7 @@ public class FirestoreSerialize {
|
|||||||
* @param documentChange DocumentChange
|
* @param documentChange DocumentChange
|
||||||
* @return WritableMap
|
* @return WritableMap
|
||||||
*/
|
*/
|
||||||
static WritableMap documentChangeToWritableMap(DocumentChange documentChange) {
|
private static WritableMap documentChangeToWritableMap(DocumentChange documentChange) {
|
||||||
WritableMap documentChangeMap = Arguments.createMap();
|
WritableMap documentChangeMap = Arguments.createMap();
|
||||||
|
|
||||||
switch (documentChange.getType()) {
|
switch (documentChange.getType()) {
|
||||||
@ -122,8 +118,10 @@ public class FirestoreSerialize {
|
|||||||
documentChangeMap.putString(KEY_DOC_CHANGE_TYPE, "modified");
|
documentChangeMap.putString(KEY_DOC_CHANGE_TYPE, "modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
documentChangeMap.putMap(KEY_DOC_CHANGE_DOCUMENT,
|
documentChangeMap.putMap(
|
||||||
snapshotToWritableMap(documentChange.getDocument()));
|
KEY_DOC_CHANGE_DOCUMENT,
|
||||||
|
snapshotToWritableMap(documentChange.getDocument())
|
||||||
|
);
|
||||||
documentChangeMap.putInt(KEY_DOC_CHANGE_NEW_INDEX, documentChange.getNewIndex());
|
documentChangeMap.putInt(KEY_DOC_CHANGE_NEW_INDEX, documentChange.getNewIndex());
|
||||||
documentChangeMap.putInt(KEY_DOC_CHANGE_OLD_INDEX, documentChange.getOldIndex());
|
documentChangeMap.putInt(KEY_DOC_CHANGE_OLD_INDEX, documentChange.getOldIndex());
|
||||||
|
|
||||||
@ -136,7 +134,7 @@ public class FirestoreSerialize {
|
|||||||
* @param map Map<String, Object>
|
* @param map Map<String, Object>
|
||||||
* @return WritableMap
|
* @return WritableMap
|
||||||
*/
|
*/
|
||||||
static WritableMap objectMapToWritable(Map<String, Object> map) {
|
private static WritableMap objectMapToWritable(Map<String, Object> map) {
|
||||||
WritableMap writableMap = Arguments.createMap();
|
WritableMap writableMap = Arguments.createMap();
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
WritableMap typeMap = buildTypeMap(entry.getValue());
|
WritableMap typeMap = buildTypeMap(entry.getValue());
|
||||||
@ -224,7 +222,10 @@ public class FirestoreSerialize {
|
|||||||
return typeMap;
|
return typeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, Object> parseReadableMap(FirebaseFirestore firestore, ReadableMap readableMap) {
|
static Map<String, Object> parseReadableMap(
|
||||||
|
FirebaseFirestore firestore,
|
||||||
|
ReadableMap readableMap
|
||||||
|
) {
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
if (readableMap != null) {
|
if (readableMap != null) {
|
||||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||||
@ -290,7 +291,10 @@ public class FirestoreSerialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Object> parseDocumentBatches(FirebaseFirestore firestore, ReadableArray readableArray) {
|
static List<Object> parseDocumentBatches(
|
||||||
|
FirebaseFirestore firestore,
|
||||||
|
ReadableArray readableArray
|
||||||
|
) {
|
||||||
List<Object> writes = new ArrayList<>(readableArray.size());
|
List<Object> writes = new ArrayList<>(readableArray.size());
|
||||||
for (int i = 0; i < readableArray.size(); i++) {
|
for (int i = 0; i < readableArray.size(); i++) {
|
||||||
Map<String, Object> write = new HashMap<>();
|
Map<String, Object> write = new HashMap<>();
|
||||||
|
@ -18,13 +18,13 @@ import com.google.android.gms.tasks.OnFailureListener;
|
|||||||
import com.google.android.gms.tasks.OnSuccessListener;
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
import com.google.android.gms.tasks.Task;
|
import com.google.android.gms.tasks.Task;
|
||||||
import com.google.firebase.FirebaseApp;
|
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.DocumentReference;
|
||||||
import com.google.firebase.firestore.FieldValue;
|
import com.google.firebase.firestore.FieldValue;
|
||||||
import com.google.firebase.firestore.FirebaseFirestore;
|
import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
import com.google.firebase.firestore.FirebaseFirestoreException;
|
import com.google.firebase.firestore.FirebaseFirestoreException;
|
||||||
|
import com.google.firebase.firestore.FirebaseFirestoreSettings;
|
||||||
import com.google.firebase.firestore.SetOptions;
|
import com.google.firebase.firestore.SetOptions;
|
||||||
|
import com.google.firebase.firestore.Transaction;
|
||||||
import com.google.firebase.firestore.WriteBatch;
|
import com.google.firebase.firestore.WriteBatch;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -48,6 +48,184 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
* REACT NATIVE METHODS
|
* 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
|
@ReactMethod
|
||||||
public void disableNetwork(String appName, final Promise promise) {
|
public void disableNetwork(String appName, final Promise promise) {
|
||||||
getFirestoreForApp(appName).disableNetwork().addOnCompleteListener(new OnCompleteListener<Void>() {
|
getFirestoreForApp(appName).disableNetwork().addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||||
@ -58,7 +236,10 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "disableNetwork:onComplete:failure", task.getException());
|
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);
|
promise.resolve(null);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "enableNetwork:onComplete:failure", task.getException());
|
Log.e(TAG, "enableNetwork:onComplete:failure", task.getException());
|
||||||
RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException());
|
RNFirebaseFirestore.promiseRejectException(
|
||||||
|
promise,
|
||||||
|
(FirebaseFirestoreException) task.getException()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void collectionGet(String appName, String path, ReadableArray filters,
|
public void collectionGet(
|
||||||
ReadableArray orders, ReadableMap options, ReadableMap getOptions,
|
String appName, String path, ReadableArray filters,
|
||||||
final Promise promise) {
|
ReadableArray orders, ReadableMap options, ReadableMap getOptions,
|
||||||
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options);
|
final Promise promise
|
||||||
|
) {
|
||||||
|
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(
|
||||||
|
appName,
|
||||||
|
path,
|
||||||
|
filters,
|
||||||
|
orders,
|
||||||
|
options
|
||||||
|
);
|
||||||
ref.get(getOptions, promise);
|
ref.get(getOptions, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void collectionOffSnapshot(String appName, String path, ReadableArray filters,
|
public void collectionOffSnapshot(
|
||||||
ReadableArray orders, ReadableMap options, String listenerId) {
|
String appName, String path, ReadableArray filters,
|
||||||
|
ReadableArray orders, ReadableMap options, String listenerId
|
||||||
|
) {
|
||||||
RNFirebaseFirestoreCollectionReference.offSnapshot(listenerId);
|
RNFirebaseFirestoreCollectionReference.offSnapshot(listenerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void collectionOnSnapshot(String appName, String path, ReadableArray filters,
|
public void collectionOnSnapshot(
|
||||||
ReadableArray orders, ReadableMap options, String listenerId,
|
String appName, String path, ReadableArray filters,
|
||||||
ReadableMap queryListenOptions) {
|
ReadableArray orders, ReadableMap options, String listenerId,
|
||||||
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options);
|
ReadableMap queryListenOptions
|
||||||
|
) {
|
||||||
|
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(
|
||||||
|
appName,
|
||||||
|
path,
|
||||||
|
filters,
|
||||||
|
orders,
|
||||||
|
options
|
||||||
|
);
|
||||||
ref.onSnapshot(listenerId, queryListenOptions);
|
ref.onSnapshot(listenerId, queryListenOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void documentBatch(final String appName, final ReadableArray writes,
|
public void documentBatch(final String appName, final ReadableArray writes,
|
||||||
final Promise promise) {
|
final Promise promise) {
|
||||||
@ -166,7 +367,12 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@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);
|
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||||
ref.get(getOptions, promise);
|
ref.get(getOptions, promise);
|
||||||
}
|
}
|
||||||
@ -177,18 +383,31 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void documentOnSnapshot(String appName, String path, String listenerId,
|
public void documentOnSnapshot(
|
||||||
ReadableMap docListenOptions) {
|
String appName, String path, String listenerId,
|
||||||
|
ReadableMap docListenOptions
|
||||||
|
) {
|
||||||
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||||
ref.onSnapshot(listenerId, docListenOptions);
|
ref.onSnapshot(listenerId, docListenOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@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);
|
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||||
ref.set(data, options, promise);
|
ref.set(data, options, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transaction Methods
|
||||||
|
*/
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void documentUpdate(String appName, String path, ReadableMap data, final Promise promise) {
|
public void documentUpdate(String appName, String path, ReadableMap data, final Promise promise) {
|
||||||
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||||
@ -214,18 +433,17 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
} else {
|
} else {
|
||||||
firestoreSettings.setSslEnabled(firestore.getFirestoreSettings().isSslEnabled());
|
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());
|
firestore.setFirestoreSettings(firestoreSettings.build());
|
||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try clean up previous transactions on reload
|
* Try clean up previous transactions on reload
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCatalystInstanceDestroy() {
|
public void onCatalystInstanceDestroy() {
|
||||||
@ -239,23 +457,22 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
transactionHandlers.clear();
|
transactionHandlers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transaction Methods
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the internal Firestore Transaction classes instance .get(ref) method and resolves with
|
* Calls the internal Firestore Transaction classes instance .get(ref) method and resolves with
|
||||||
* the DocumentSnapshot.
|
* the DocumentSnapshot.
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param transactionId
|
* @param transactionId transactionId
|
||||||
* @param path
|
* @param path path
|
||||||
* @param promise
|
* @param promise promise
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@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);
|
RNFirebaseFirestoreTransactionHandler handler = transactionHandlers.get(transactionId);
|
||||||
|
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
@ -269,11 +486,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* INTERNALS/UTILS
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts any pending signals and deletes the transaction handler.
|
* Aborts any pending signals and deletes the transaction handler.
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param transactionId
|
* @param transactionId transactionId
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void transactionDispose(String appName, int transactionId) {
|
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.
|
* Signals to transactionHandler that the command buffer is ready.
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param transactionId
|
* @param transactionId transactionId
|
||||||
* @param commandBuffer
|
* @param commandBuffer commandBuffer
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void transactionApplyBuffer(String appName, int transactionId, ReadableArray commandBuffer) {
|
public void transactionApplyBuffer(
|
||||||
|
String appName,
|
||||||
|
int transactionId,
|
||||||
|
ReadableArray commandBuffer
|
||||||
|
) {
|
||||||
RNFirebaseFirestoreTransactionHandler handler = transactionHandlers.get(transactionId);
|
RNFirebaseFirestoreTransactionHandler handler = transactionHandlers.get(transactionId);
|
||||||
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
@ -304,12 +530,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
/**
|
/**
|
||||||
* Begin a new transaction via AsyncTask 's
|
* Begin a new transaction via AsyncTask 's
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param transactionId
|
* @param transactionId transactionId
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void transactionBegin(final String appName, int transactionId) {
|
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);
|
transactionHandlers.put(transactionId, transactionHandler);
|
||||||
|
|
||||||
AsyncTask.execute(new Runnable() {
|
AsyncTask.execute(new Runnable() {
|
||||||
@ -327,7 +557,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
WritableMap eventMap = transactionHandler.createEventMap(null, "update");
|
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 ...
|
// exit early if aborted - has to throw an exception otherwise will just keep trying ...
|
||||||
if (transactionHandler.aborted) {
|
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 ...
|
// exit early if timeout from bridge - has to throw an exception otherwise will just keep trying ...
|
||||||
if (transactionHandler.timeout) {
|
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
|
// process any buffered commands from JS land
|
||||||
@ -357,15 +597,19 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
ReadableMap command = buffer.getMap(i);
|
ReadableMap command = buffer.getMap(i);
|
||||||
String path = command.getString("path");
|
String path = command.getString("path");
|
||||||
String type = command.getString("type");
|
String type = command.getString("type");
|
||||||
RNFirebaseFirestoreDocumentReference documentReference = getDocumentForAppPath(appName, path);
|
RNFirebaseFirestoreDocumentReference documentReference = getDocumentForAppPath(
|
||||||
|
appName,
|
||||||
|
path
|
||||||
|
);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "set":
|
case "set":
|
||||||
data = command.getMap("data");
|
data = command.getMap("data");
|
||||||
|
|
||||||
ReadableMap options = command.getMap("options");
|
ReadableMap options = command.getMap("options");
|
||||||
Map<String, Object> setData = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data);
|
Map<String, Object> setData = FirestoreSerialize.parseReadableMap(
|
||||||
|
RNFirebaseFirestore.getFirestoreForApp(appName),
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
if (options != null && options.hasKey("merge") && options.getBoolean("merge")) {
|
if (options != null && options.hasKey("merge") && options.getBoolean("merge")) {
|
||||||
transaction.set(documentReference.getRef(), setData, SetOptions.merge());
|
transaction.set(documentReference.getRef(), setData, SetOptions.merge());
|
||||||
@ -376,7 +620,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
case "update":
|
case "update":
|
||||||
data = command.getMap("data");
|
data = command.getMap("data");
|
||||||
|
|
||||||
Map<String, Object> updateData = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data);
|
Map<String, Object> updateData = FirestoreSerialize.parseReadableMap(
|
||||||
|
RNFirebaseFirestore.getFirestoreForApp(appName),
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
transaction.update(documentReference.getRef(), updateData);
|
transaction.update(documentReference.getRef(), updateData);
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
@ -396,7 +644,11 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
|||||||
if (!transactionHandler.aborted) {
|
if (!transactionHandler.aborted) {
|
||||||
Log.d(TAG, "Transaction onSuccess!");
|
Log.d(TAG, "Transaction onSuccess!");
|
||||||
WritableMap eventMap = transactionHandler.createEventMap(null, "complete");
|
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) {
|
public void onFailure(@NonNull Exception e) {
|
||||||
if (!transactionHandler.aborted) {
|
if (!transactionHandler.aborted) {
|
||||||
Log.w(TAG, "Transaction onFailure.", e);
|
Log.w(TAG, "Transaction onFailure.", e);
|
||||||
WritableMap eventMap = transactionHandler.createEventMap((FirebaseFirestoreException) e, "error");
|
WritableMap eventMap = transactionHandler.createEventMap(
|
||||||
Utils.sendEvent(getReactApplicationContext(), "firestore_transaction_event", eventMap);
|
(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
|
* Get a collection reference for a specific app and path
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param filters
|
* @param filters filters
|
||||||
* @param orders
|
* @param orders orders
|
||||||
* @param options
|
* @param options options
|
||||||
* @param path @return
|
* @param path @return
|
||||||
*/
|
*/
|
||||||
private RNFirebaseFirestoreCollectionReference getCollectionForAppPath(String appName, String path,
|
private RNFirebaseFirestoreCollectionReference getCollectionForAppPath(
|
||||||
ReadableArray filters,
|
String appName, String path,
|
||||||
ReadableArray orders,
|
ReadableArray filters,
|
||||||
ReadableMap options) {
|
ReadableArray orders,
|
||||||
return new RNFirebaseFirestoreCollectionReference(this.getReactApplicationContext(), appName, path, filters, orders, options);
|
ReadableMap options
|
||||||
|
) {
|
||||||
|
return new RNFirebaseFirestoreCollectionReference(
|
||||||
|
this.getReactApplicationContext(),
|
||||||
|
appName,
|
||||||
|
path,
|
||||||
|
filters,
|
||||||
|
orders,
|
||||||
|
options
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a document reference for a specific app and path
|
* Get a document reference for a specific app and path
|
||||||
*
|
*
|
||||||
* @param appName
|
* @param appName appName
|
||||||
* @param path
|
* @param path path
|
||||||
* @return
|
* @return RNFirebaseFirestoreDocumentReference
|
||||||
*/
|
*/
|
||||||
private RNFirebaseFirestoreDocumentReference getDocumentForAppPath(String appName, String path) {
|
private RNFirebaseFirestoreDocumentReference getDocumentForAppPath(String appName, String path) {
|
||||||
return new RNFirebaseFirestoreDocumentReference(this.getReactApplicationContext(), appName, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.invertase.firebase.firestore;
|
package io.invertase.firebase.firestore;
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
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.QuerySnapshot;
|
||||||
import com.google.firebase.firestore.Source;
|
import com.google.firebase.firestore.Source;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.invertase.firebase.Utils;
|
import io.invertase.firebase.Utils;
|
||||||
|
|
||||||
public class RNFirebaseFirestoreCollectionReference {
|
class RNFirebaseFirestoreCollectionReference {
|
||||||
private static final String TAG = "RNFSCollectionReference";
|
private static final String TAG = "RNFSCollectionReference";
|
||||||
private static Map<String, ListenerRegistration> collectionSnapshotListeners = new HashMap<>();
|
private static Map<String, ListenerRegistration> collectionSnapshotListeners = new HashMap<>();
|
||||||
|
|
||||||
private final String appName;
|
|
||||||
private final String path;
|
private final String path;
|
||||||
private final ReadableArray filters;
|
|
||||||
private final ReadableArray orders;
|
|
||||||
private final ReadableMap options;
|
|
||||||
private final Query query;
|
private final Query query;
|
||||||
|
private final String appName;
|
||||||
|
private final ReadableMap options;
|
||||||
|
private final ReadableArray orders;
|
||||||
|
private final ReadableArray filters;
|
||||||
private ReactContext reactContext;
|
private ReactContext reactContext;
|
||||||
|
|
||||||
RNFirebaseFirestoreCollectionReference(ReactContext reactContext, String appName, String path,
|
RNFirebaseFirestoreCollectionReference(
|
||||||
ReadableArray filters, ReadableArray orders,
|
ReactContext reactContext,
|
||||||
ReadableMap options) {
|
String appName,
|
||||||
|
String path,
|
||||||
|
ReadableArray filters,
|
||||||
|
ReadableArray orders,
|
||||||
|
ReadableMap options
|
||||||
|
) {
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.filters = filters;
|
this.filters = filters;
|
||||||
@ -53,6 +58,13 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
this.reactContext = reactContext;
|
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) {
|
void get(ReadableMap getOptions, final Promise promise) {
|
||||||
Source source;
|
Source source;
|
||||||
if (getOptions != null && getOptions.hasKey("source")) {
|
if (getOptions != null && getOptions.hasKey("source")) {
|
||||||
@ -67,29 +79,34 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
} else {
|
} else {
|
||||||
source = Source.DEFAULT;
|
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<QuerySnapshot>() {
|
query.get(source).addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
Log.d(TAG, "get:onComplete:success");
|
Log.d(TAG, "get:onComplete:success");
|
||||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(task.getResult());
|
serializeAsyncTask.execute(task.getResult());
|
||||||
promise.resolve(data);
|
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "get:onComplete:failure", task.getException());
|
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) {
|
void onSnapshot(final String listenerId, final ReadableMap queryListenOptions) {
|
||||||
ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId);
|
|
||||||
if (listenerRegistration != null) {
|
|
||||||
listenerRegistration.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSnapshot(final String listenerId, final ReadableMap queryListenOptions) {
|
|
||||||
if (!collectionSnapshotListeners.containsKey(listenerId)) {
|
if (!collectionSnapshotListeners.containsKey(listenerId)) {
|
||||||
final EventListener<QuerySnapshot> listener = new EventListener<QuerySnapshot>() {
|
final EventListener<QuerySnapshot> listener = new EventListener<QuerySnapshot>() {
|
||||||
@Override
|
@Override
|
||||||
@ -97,7 +114,8 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
handleQuerySnapshotEvent(listenerId, querySnapshot);
|
handleQuerySnapshotEvent(listenerId, querySnapshot);
|
||||||
} else {
|
} else {
|
||||||
ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId);
|
ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(
|
||||||
|
listenerId);
|
||||||
if (listenerRegistration != null) {
|
if (listenerRegistration != null) {
|
||||||
listenerRegistration.remove();
|
listenerRegistration.remove();
|
||||||
}
|
}
|
||||||
@ -115,7 +133,10 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
metadataChanges = MetadataChanges.EXCLUDE;
|
metadataChanges = MetadataChanges.EXCLUDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListenerRegistration listenerRegistration = this.query.addSnapshotListener(metadataChanges, listener);
|
ListenerRegistration listenerRegistration = this.query.addSnapshotListener(
|
||||||
|
metadataChanges,
|
||||||
|
listener
|
||||||
|
);
|
||||||
collectionSnapshotListeners.put(listenerId, listenerRegistration);
|
collectionSnapshotListeners.put(listenerId, listenerRegistration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +191,7 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
} else {
|
} else {
|
||||||
ReadableArray fieldPathElements = fieldPathMap.getArray("elements");
|
ReadableArray fieldPathElements = fieldPathMap.getArray("elements");
|
||||||
String[] fieldPathArray = new String[fieldPathElements.size()];
|
String[] fieldPathArray = new String[fieldPathElements.size()];
|
||||||
for (int j=0; j<fieldPathElements.size(); j++) {
|
for (int j = 0; j < fieldPathElements.size(); j++) {
|
||||||
fieldPathArray[j] = fieldPathElements.getString(j);
|
fieldPathArray[j] = fieldPathElements.getString(j);
|
||||||
}
|
}
|
||||||
FieldPath fieldPath = FieldPath.of(fieldPathArray);
|
FieldPath fieldPath = FieldPath.of(fieldPathArray);
|
||||||
@ -202,13 +223,13 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
Map<String, Object> order = (Map) o;
|
Map<String, Object> order = (Map) o;
|
||||||
String direction = (String) order.get("direction");
|
String direction = (String) order.get("direction");
|
||||||
Map<String, Object> fieldPathMap = (Map) order.get("fieldPath");
|
Map<String, Object> fieldPathMap = (Map) order.get("fieldPath");
|
||||||
String fieldPathType = (String)fieldPathMap.get("type");
|
String fieldPathType = (String) fieldPathMap.get("type");
|
||||||
|
|
||||||
if (fieldPathType.equals("string")) {
|
if (fieldPathType.equals("string")) {
|
||||||
String fieldPath = (String)fieldPathMap.get("string");
|
String fieldPath = (String) fieldPathMap.get("string");
|
||||||
query = query.orderBy(fieldPath, Query.Direction.valueOf(direction));
|
query = query.orderBy(fieldPath, Query.Direction.valueOf(direction));
|
||||||
} else {
|
} else {
|
||||||
List<String> fieldPathElements = (List)fieldPathMap.get("elements");
|
List<String> fieldPathElements = (List) fieldPathMap.get("elements");
|
||||||
FieldPath fieldPath = FieldPath.of(fieldPathElements.toArray(new String[fieldPathElements.size()]));
|
FieldPath fieldPath = FieldPath.of(fieldPathElements.toArray(new String[fieldPathElements.size()]));
|
||||||
query = query.orderBy(fieldPath, Query.Direction.valueOf(direction));
|
query = query.orderBy(fieldPath, Query.Direction.valueOf(direction));
|
||||||
}
|
}
|
||||||
@ -218,57 +239,79 @@ public class RNFirebaseFirestoreCollectionReference {
|
|||||||
|
|
||||||
private Query applyOptions(FirebaseFirestore firestore, Query query) {
|
private Query applyOptions(FirebaseFirestore firestore, Query query) {
|
||||||
if (options.hasKey("endAt")) {
|
if (options.hasKey("endAt")) {
|
||||||
List<Object> endAtList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endAt"));
|
List<Object> endAtList = FirestoreSerialize.parseReadableArray(
|
||||||
|
firestore,
|
||||||
|
options.getArray("endAt")
|
||||||
|
);
|
||||||
query = query.endAt(endAtList.toArray());
|
query = query.endAt(endAtList.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hasKey("endBefore")) {
|
if (options.hasKey("endBefore")) {
|
||||||
List<Object> endBeforeList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endBefore"));
|
List<Object> endBeforeList = FirestoreSerialize.parseReadableArray(
|
||||||
|
firestore,
|
||||||
|
options.getArray("endBefore")
|
||||||
|
);
|
||||||
query = query.endBefore(endBeforeList.toArray());
|
query = query.endBefore(endBeforeList.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hasKey("limit")) {
|
if (options.hasKey("limit")) {
|
||||||
int limit = options.getInt("limit");
|
int limit = options.getInt("limit");
|
||||||
query = query.limit(limit);
|
query = query.limit(limit);
|
||||||
}
|
}
|
||||||
if (options.hasKey("offset")) {
|
// if (options.hasKey("offset")) {
|
||||||
// Android doesn't support offset
|
// Android doesn't support offset
|
||||||
}
|
// }
|
||||||
if (options.hasKey("selectFields")) {
|
// if (options.hasKey("selectFields")) {
|
||||||
// Android doesn't support selectFields
|
// Android doesn't support selectFields
|
||||||
}
|
// }
|
||||||
if (options.hasKey("startAfter")) {
|
if (options.hasKey("startAfter")) {
|
||||||
List<Object> startAfterList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAfter"));
|
List<Object> startAfterList = FirestoreSerialize.parseReadableArray(
|
||||||
|
firestore,
|
||||||
|
options.getArray("startAfter")
|
||||||
|
);
|
||||||
query = query.startAfter(startAfterList.toArray());
|
query = query.startAfter(startAfterList.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hasKey("startAt")) {
|
if (options.hasKey("startAt")) {
|
||||||
List<Object> startAtList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAt"));
|
List<Object> startAtList = FirestoreSerialize.parseReadableArray(
|
||||||
|
firestore,
|
||||||
|
options.getArray("startAt")
|
||||||
|
);
|
||||||
query = query.startAt(startAtList.toArray());
|
query = query.startAt(startAtList.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles documentSnapshot events.
|
* Handles documentSnapshot events.
|
||||||
*
|
*
|
||||||
* @param listenerId
|
* @param listenerId id
|
||||||
* @param querySnapshot
|
* @param querySnapshot snapshot
|
||||||
*/
|
*/
|
||||||
private void handleQuerySnapshotEvent(String listenerId, QuerySnapshot querySnapshot) {
|
private void handleQuerySnapshotEvent(final String listenerId, QuerySnapshot querySnapshot) {
|
||||||
WritableMap event = Arguments.createMap();
|
@SuppressLint("StaticFieldLeak") final QuerySnapshotSerializeAsyncTask serializeAsyncTask = new QuerySnapshotSerializeAsyncTask(
|
||||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(querySnapshot);
|
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);
|
serializeAsyncTask.execute(querySnapshot);
|
||||||
event.putString("path", path);
|
|
||||||
event.putString("listenerId", listenerId);
|
|
||||||
event.putMap("querySnapshot", data);
|
|
||||||
|
|
||||||
Utils.sendEvent(reactContext, "firestore_collection_sync_event", event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a documentSnapshot error event
|
* Handles a documentSnapshot error event
|
||||||
*
|
*
|
||||||
* @param listenerId
|
* @param listenerId id
|
||||||
* @param exception
|
* @param exception exception
|
||||||
*/
|
*/
|
||||||
private void handleQuerySnapshotError(String listenerId, FirebaseFirestoreException exception) {
|
private void handleQuerySnapshotError(String listenerId, FirebaseFirestoreException exception) {
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.invertase.firebase.firestore;
|
package io.invertase.firebase.firestore;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -31,17 +32,24 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
|
|
||||||
private final String appName;
|
private final String appName;
|
||||||
private final String path;
|
private final String path;
|
||||||
private ReactContext reactContext;
|
|
||||||
private final DocumentReference ref;
|
private final DocumentReference ref;
|
||||||
|
private ReactContext reactContext;
|
||||||
|
|
||||||
RNFirebaseFirestoreDocumentReference(ReactContext reactContext, String appName, String path) {
|
RNFirebaseFirestoreDocumentReference(ReactContext reactContext, String appName, String path) {
|
||||||
this.appName = appName;
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.appName = appName;
|
||||||
this.reactContext = reactContext;
|
this.reactContext = reactContext;
|
||||||
this.ref = RNFirebaseFirestore.getFirestoreForApp(appName).document(path);
|
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<Void>() {
|
this.ref.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(@NonNull Task<Void> task) {
|
public void onComplete(@NonNull Task<Void> task) {
|
||||||
@ -50,7 +58,10 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "delete:onComplete:failure", task.getException());
|
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) {
|
void get(final ReadableMap getOptions, final Promise promise) {
|
||||||
Source source;
|
Source source;
|
||||||
|
|
||||||
if (getOptions != null && getOptions.hasKey("source")) {
|
if (getOptions != null && getOptions.hasKey("source")) {
|
||||||
String optionsSource = getOptions.getString("source");
|
String optionsSource = getOptions.getString("source");
|
||||||
if ("server".equals(optionsSource)) {
|
if ("server".equals(optionsSource)) {
|
||||||
@ -70,45 +82,57 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
} else {
|
} else {
|
||||||
source = Source.DEFAULT;
|
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<DocumentSnapshot>() {
|
this.ref.get(source).addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
|
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
Log.d(TAG, "get:onComplete:success");
|
Log.d(TAG, "get:onComplete:success");
|
||||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(task.getResult());
|
serializeAsyncTask.execute(task.getResult());
|
||||||
promise.resolve(data);
|
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "get:onComplete:failure", task.getException());
|
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) {
|
void onSnapshot(final String listenerId, final ReadableMap docListenOptions) {
|
||||||
ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId);
|
|
||||||
if (listenerRegistration != null) {
|
|
||||||
listenerRegistration.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSnapshot(final String listenerId, final ReadableMap docListenOptions) {
|
|
||||||
if (!documentSnapshotListeners.containsKey(listenerId)) {
|
if (!documentSnapshotListeners.containsKey(listenerId)) {
|
||||||
final EventListener<DocumentSnapshot> listener = new EventListener<DocumentSnapshot>() {
|
final EventListener<DocumentSnapshot> listener = new EventListener<DocumentSnapshot>() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException exception) {
|
public void onEvent(
|
||||||
|
DocumentSnapshot documentSnapshot,
|
||||||
|
FirebaseFirestoreException exception
|
||||||
|
) {
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
handleDocumentSnapshotEvent(listenerId, documentSnapshot);
|
handleDocumentSnapshotEvent(listenerId, documentSnapshot);
|
||||||
} else {
|
} else {
|
||||||
ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId);
|
ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId);
|
||||||
|
|
||||||
if (listenerRegistration != null) {
|
if (listenerRegistration != null) {
|
||||||
listenerRegistration.remove();
|
listenerRegistration.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDocumentSnapshotError(listenerId, exception);
|
handleDocumentSnapshotError(listenerId, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MetadataChanges metadataChanges;
|
MetadataChanges metadataChanges;
|
||||||
|
|
||||||
if (docListenOptions != null
|
if (docListenOptions != null
|
||||||
&& docListenOptions.hasKey("includeMetadataChanges")
|
&& docListenOptions.hasKey("includeMetadataChanges")
|
||||||
&& docListenOptions.getBoolean("includeMetadataChanges")) {
|
&& docListenOptions.getBoolean("includeMetadataChanges")) {
|
||||||
@ -116,19 +140,30 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
} else {
|
} else {
|
||||||
metadataChanges = MetadataChanges.EXCLUDE;
|
metadataChanges = MetadataChanges.EXCLUDE;
|
||||||
}
|
}
|
||||||
ListenerRegistration listenerRegistration = this.ref.addSnapshotListener(metadataChanges, listener);
|
|
||||||
|
ListenerRegistration listenerRegistration = this.ref.addSnapshotListener(
|
||||||
|
metadataChanges,
|
||||||
|
listener
|
||||||
|
);
|
||||||
|
|
||||||
documentSnapshotListeners.put(listenerId, listenerRegistration);
|
documentSnapshotListeners.put(listenerId, listenerRegistration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(final ReadableMap data, final ReadableMap options, final Promise promise) {
|
public void set(final ReadableMap data, final ReadableMap options, final Promise promise) {
|
||||||
Map<String, Object> map = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data);
|
|
||||||
Task<Void> task;
|
Task<Void> task;
|
||||||
|
|
||||||
|
Map<String, Object> map = FirestoreSerialize.parseReadableMap(
|
||||||
|
RNFirebaseFirestore.getFirestoreForApp(appName),
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
if (options != null && options.hasKey("merge") && options.getBoolean("merge")) {
|
if (options != null && options.hasKey("merge") && options.getBoolean("merge")) {
|
||||||
task = this.ref.set(map, SetOptions.merge());
|
task = this.ref.set(map, SetOptions.merge());
|
||||||
} else {
|
} else {
|
||||||
task = this.ref.set(map);
|
task = this.ref.set(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
task.addOnCompleteListener(new OnCompleteListener<Void>() {
|
task.addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(@NonNull Task<Void> task) {
|
public void onComplete(@NonNull Task<Void> task) {
|
||||||
@ -137,14 +172,21 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "set:onComplete:failure", task.getException());
|
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) {
|
void update(final ReadableMap data, final Promise promise) {
|
||||||
Map<String, Object> map = FirestoreSerialize.parseReadableMap(RNFirebaseFirestore.getFirestoreForApp(appName), data);
|
Map<String, Object> map = FirestoreSerialize.parseReadableMap(
|
||||||
|
RNFirebaseFirestore.getFirestoreForApp(appName),
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
this.ref.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {
|
this.ref.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(@NonNull Task<Void> task) {
|
public void onComplete(@NonNull Task<Void> task) {
|
||||||
@ -153,7 +195,10 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "update:onComplete:failure", task.getException());
|
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
|
* INTERNALS/UTILS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public DocumentReference getRef() {
|
DocumentReference getRef() {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,32 +219,44 @@ public class RNFirebaseFirestoreDocumentReference {
|
|||||||
/**
|
/**
|
||||||
* Handles documentSnapshot events.
|
* Handles documentSnapshot events.
|
||||||
*
|
*
|
||||||
* @param listenerId
|
* @param listenerId id
|
||||||
* @param documentSnapshot
|
* @param documentSnapshot snapshot
|
||||||
*/
|
*/
|
||||||
private void handleDocumentSnapshotEvent(String listenerId, DocumentSnapshot documentSnapshot) {
|
private void handleDocumentSnapshotEvent(
|
||||||
WritableMap event = Arguments.createMap();
|
final String listenerId,
|
||||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(documentSnapshot);
|
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);
|
serializeAsyncTask.execute(documentSnapshot);
|
||||||
event.putString("path", path);
|
|
||||||
event.putString("listenerId", listenerId);
|
|
||||||
event.putMap("documentSnapshot", data);
|
|
||||||
|
|
||||||
Utils.sendEvent(reactContext, "firestore_document_sync_event", event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a documentSnapshot error event
|
* Handles a documentSnapshot error event
|
||||||
*
|
*
|
||||||
* @param listenerId
|
* @param listenerId id
|
||||||
* @param exception
|
* @param exception exception
|
||||||
*/
|
*/
|
||||||
private void handleDocumentSnapshotError(String listenerId, FirebaseFirestoreException exception) {
|
private void handleDocumentSnapshotError(
|
||||||
|
String listenerId,
|
||||||
|
FirebaseFirestoreException exception
|
||||||
|
) {
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
|
|
||||||
event.putString("appName", appName);
|
|
||||||
event.putString("path", path);
|
event.putString("path", path);
|
||||||
|
event.putString("appName", appName);
|
||||||
event.putString("listenerId", listenerId);
|
event.putString("listenerId", listenerId);
|
||||||
event.putMap("error", RNFirebaseFirestore.getJSError(exception));
|
event.putMap("error", RNFirebaseFirestore.getJSError(exception));
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package io.invertase.firebase.firestore;
|
package io.invertase.firebase.firestore;
|
||||||
|
|
||||||
import com.facebook.react.ReactPackage;
|
import com.facebook.react.ReactPackage;
|
||||||
import com.facebook.react.bridge.JavaScriptModule;
|
|
||||||
import com.facebook.react.bridge.NativeModule;
|
import com.facebook.react.bridge.NativeModule;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.uimanager.UIManagerModule;
|
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}
|
* @return a list of view managers that should be registered with {@link UIManagerModule}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,17 +17,16 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
|
|
||||||
class RNFirebaseFirestoreTransactionHandler {
|
class RNFirebaseFirestoreTransactionHandler {
|
||||||
|
private final ReentrantLock lock;
|
||||||
|
private final Condition condition;
|
||||||
|
boolean aborted = false;
|
||||||
|
boolean timeout = false;
|
||||||
private String appName;
|
private String appName;
|
||||||
private long timeoutAt;
|
private long timeoutAt;
|
||||||
private int transactionId;
|
private int transactionId;
|
||||||
private final ReentrantLock lock;
|
|
||||||
private final Condition condition;
|
|
||||||
private ReadableArray commandBuffer;
|
private ReadableArray commandBuffer;
|
||||||
private Transaction firestoreTransaction;
|
private Transaction firestoreTransaction;
|
||||||
|
|
||||||
boolean aborted = false;
|
|
||||||
boolean timeout = false;
|
|
||||||
|
|
||||||
RNFirebaseFirestoreTransactionHandler(String app, int id) {
|
RNFirebaseFirestoreTransactionHandler(String app, int id) {
|
||||||
appName = app;
|
appName = app;
|
||||||
transactionId = id;
|
transactionId = id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user