From b93503459281b8cd91617877e81a5f86962e1c5c Mon Sep 17 00:00:00 2001 From: Salakar Date: Wed, 2 Aug 2017 10:38:30 +0100 Subject: [PATCH] [database][wip] misc multi-app --- .../firebase/database/RNFirebaseDatabase.java | 51 +- .../database/RNFirebaseDatabaseOld.java | 962 +++++++++--------- .../database/RNFirebaseDatabaseReference.java | 23 +- lib/modules/database/index.js | 23 +- lib/modules/database/index.old.js | 7 +- lib/modules/database/reference.js | 3 +- lib/modules/database/transaction.js | 2 +- lib/utils/ModuleBase.js | 3 + 8 files changed, 566 insertions(+), 508 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java index d1c9adbe..6ceeece4 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java @@ -373,10 +373,9 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { ref.removeValue(listener); } - // Push no longer required, handled in JS now. /** - * Subcribe once to a firebase reference. + * Subscribe once to a firebase reference. * * @param appName * @param refId @@ -387,15 +386,24 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { */ @ReactMethod public void once(String appName, int refId, String path, ReadableArray modifiers, String eventName, Promise promise) { - RNFirebaseDatabaseReference internalRef = getInternalReferenceForApp(appName, refId, path, modifiers, false); - - if (eventName.equals("value")) { - internalRef.addOnceValueEventListener(promise); - } else { - internalRef.addChildOnceEventListener(eventName, promise); - } + getInternalReferenceForApp(appName, refId, path, modifiers, false).once(eventName, promise); } + /** + * Subscribe to real time events for the specified database path + modifiers + * + * @param appName + * @param refId + * @param path + * @param modifiers + * @param eventName + * @param promise + */ + @ReactMethod + public void on(String appName, int refId, String path, ReadableArray modifiers, String eventName, Promise promise) { + getInternalReferenceForApp(appName, refId, path, modifiers, true).on(eventName); + + } @@ -422,6 +430,11 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { } } + /** + * React Method - returns this module name + * + * @return + */ @Override public String getName() { return "RNFirebaseDatabase"; @@ -482,13 +495,27 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { return existingRef; } - // todo move to error util for use in other modules - static String getMessageWithService(String message, String service, String fullCode) { + /** + * Wrap a message string with the specified service name e.g. 'Database' + * + * @param message + * @param service + * @param fullCode + * @return + */ + private static String getMessageWithService(String message, String service, String fullCode) { // Service: Error message (service/code). return service + ": " + message + " (" + fullCode.toLowerCase() + ")."; } - static String getCodeWithService(String service, String code) { + /** + * Generate a service error code string e.g. 'DATABASE/PERMISSION-DENIED' + * + * @param service + * @param code + * @return + */ + private static String getCodeWithService(String service, String code) { return service.toUpperCase() + "/" + code.toUpperCase(); } diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseOld.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseOld.java index 116a36ca..7e5d964d 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseOld.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseOld.java @@ -1,504 +1,504 @@ -package io.invertase.firebase.database; - -import java.util.Map; -import java.util.List; -import java.util.HashMap; - -import android.net.Uri; -import android.os.AsyncTask; -import android.util.Log; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReadableMapKeySetIterator; - -import com.facebook.react.bridge.WritableNativeArray; -import com.google.firebase.database.DataSnapshot; -import com.google.firebase.database.MutableData; -import com.google.firebase.database.ServerValue; -import com.google.firebase.database.OnDisconnect; -import com.google.firebase.database.DatabaseError; -import com.google.firebase.database.DatabaseReference; -import com.google.firebase.database.FirebaseDatabase; -import com.google.firebase.database.DatabaseException; -import com.google.firebase.database.Transaction; - -import io.invertase.firebase.Utils; - -public class RNFirebaseDatabaseOld extends ReactContextBaseJavaModule { -// private static final String TAG = "RNFirebaseDatabase"; -// private HashMap mReferences = new HashMap<>(); -// private HashMap mTransactionHandlers = new HashMap<>(); -// private FirebaseDatabase mFirebaseDatabase; +//package io.invertase.firebase.database; // -// public RNFirebaseDatabaseOld(ReactApplicationContext reactContext) { -// super(reactContext); -// mFirebaseDatabase = FirebaseDatabase.getInstance(); -// } - -// @Override -// public String getName() { -// return TAG; -// } - -// // Persistence -// @ReactMethod -// public void enablePersistence( -// final Boolean enable, -// final Callback callback) { -// try { -// mFirebaseDatabase.setPersistenceEnabled(enable); -// } catch (DatabaseException t) { +//import java.util.Map; +//import java.util.List; +//import java.util.HashMap; // -// } +//import android.net.Uri; +//import android.os.AsyncTask; +//import android.util.Log; // -// WritableMap res = Arguments.createMap(); -// res.putString("status", "success"); -// callback.invoke(null, res); -// } - -// @ReactMethod -// public void keepSynced( -// final String path, -// final Boolean enable, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// ref.keepSynced(enable); +//import com.facebook.react.bridge.Callback; +//import com.facebook.react.bridge.Arguments; +//import com.facebook.react.bridge.WritableArray; +//import com.facebook.react.bridge.WritableMap; +//import com.facebook.react.bridge.ReadableMap; +//import com.facebook.react.bridge.ReactMethod; +//import com.facebook.react.bridge.ReactContext; +//import com.facebook.react.bridge.ReadableArray; +//import com.facebook.react.bridge.ReactApplicationContext; +//import com.facebook.react.bridge.ReactContextBaseJavaModule; +//import com.facebook.react.bridge.ReadableMapKeySetIterator; // -// WritableMap res = Arguments.createMap(); -// res.putString("status", "success"); -// res.putString("path", path); -// callback.invoke(null, res); -// } - -// // RNFirebaseDatabase -// @ReactMethod -// public void set( -// final String path, -// final ReadableMap props, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// Map m = Utils.recursivelyDeconstructReadableMap(props); +//import com.facebook.react.bridge.WritableNativeArray; +//import com.google.firebase.database.DataSnapshot; +//import com.google.firebase.database.MutableData; +//import com.google.firebase.database.ServerValue; +//import com.google.firebase.database.OnDisconnect; +//import com.google.firebase.database.DatabaseError; +//import com.google.firebase.database.DatabaseReference; +//import com.google.firebase.database.FirebaseDatabase; +//import com.google.firebase.database.DatabaseException; +//import com.google.firebase.database.Transaction; // -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("set", callback, error); -// } -// }; +//import io.invertase.firebase.Utils; // -// ref.setValue(m.get("value"), listener); -// } - -// @ReactMethod -// public void priority( -// final String path, -// final ReadableMap priority, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// Map priorityMap = Utils.recursivelyDeconstructReadableMap(priority); +//public class RNFirebaseDatabaseOld extends ReactContextBaseJavaModule { +//// private static final String TAG = "RNFirebaseDatabase"; +//// private HashMap mReferences = new HashMap<>(); +//// private HashMap mTransactionHandlers = new HashMap<>(); +//// private FirebaseDatabase mFirebaseDatabase; +//// +//// public RNFirebaseDatabaseOld(ReactApplicationContext reactContext) { +//// super(reactContext); +//// mFirebaseDatabase = FirebaseDatabase.getInstance(); +//// } // -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("priority", callback, error); -// } -// }; +//// @Override +//// public String getName() { +//// return TAG; +//// } // -// ref.setPriority(priorityMap.get("value"), listener); -// } +//// // Persistence +//// @ReactMethod +//// public void enablePersistence( +//// final Boolean enable, +//// final Callback callback) { +//// try { +//// mFirebaseDatabase.setPersistenceEnabled(enable); +//// } catch (DatabaseException t) { +//// +//// } +//// +//// WritableMap res = Arguments.createMap(); +//// res.putString("status", "success"); +//// callback.invoke(null, res); +//// } +// +//// @ReactMethod +//// public void keepSynced( +//// final String path, +//// final Boolean enable, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// ref.keepSynced(enable); +//// +//// WritableMap res = Arguments.createMap(); +//// res.putString("status", "success"); +//// res.putString("path", path); +//// callback.invoke(null, res); +//// } +// +//// // RNFirebaseDatabase +//// @ReactMethod +//// public void set( +//// final String path, +//// final ReadableMap props, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// Map m = Utils.recursivelyDeconstructReadableMap(props); +//// +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("set", callback, error); +//// } +//// }; +//// +//// ref.setValue(m.get("value"), listener); +//// } +// +//// @ReactMethod +//// public void priority( +//// final String path, +//// final ReadableMap priority, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// Map priorityMap = Utils.recursivelyDeconstructReadableMap(priority); +//// +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("priority", callback, error); +//// } +//// }; +//// +//// ref.setPriority(priorityMap.get("value"), listener); +//// } +//// +//// @ReactMethod +//// public void withPriority( +//// final String path, +//// final ReadableMap data, +//// final ReadableMap priority, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// Map dataMap = Utils.recursivelyDeconstructReadableMap(data); +//// Map priorityMap = Utils.recursivelyDeconstructReadableMap(priority); +//// +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("withPriority", callback, error); +//// } +//// }; +//// +//// ref.setValue(dataMap.get("value"), priorityMap.get("value"), listener); +//// } +//// +//// @ReactMethod +//// public void update(final String path, +//// final ReadableMap props, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// Map m = Utils.recursivelyDeconstructReadableMap(props); +//// +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("update", callback, error); +//// } +//// }; +//// +//// ref.updateChildren(m, listener); +//// } +// +//// @ReactMethod +//// public void remove(final String path, +//// final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("remove", callback, error); +//// } +//// }; +//// +//// ref.removeValue(listener); +//// } +// +//// @ReactMethod +//// public void push(final String path, +//// final ReadableMap props, +//// final Callback callback) { +//// +//// Log.d(TAG, "Called push with " + path); +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// DatabaseReference newRef = ref.push(); +//// +//// final Uri url = Uri.parse(newRef.toString()); +//// final String newPath = url.getPath(); +//// +//// ReadableMapKeySetIterator iterator = props.keySetIterator(); +//// if (iterator.hasNextKey()) { +//// Log.d(TAG, "Passed value to push"); +//// // lame way to check if the `props` are empty +//// Map m = Utils.recursivelyDeconstructReadableMap(props); +//// +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// if (error != null) { +//// WritableMap err = Arguments.createMap(); +//// err.putInt("code", error.getCode()); +//// err.putString("details", error.getDetails()); +//// err.putString("description", error.getMessage()); +//// callback.invoke(err); +//// } else { +//// WritableMap res = Arguments.createMap(); +//// res.putString("status", "success"); +//// res.putString("ref", newPath); +//// callback.invoke(null, res); +//// } +//// } +//// }; +//// +//// newRef.setValue(m.get("value"), listener); +//// } else { +//// Log.d(TAG, "No value passed to push: " + newPath); +//// WritableMap res = Arguments.createMap(); +//// res.putString("status", "success"); +//// res.putString("ref", newPath); +//// callback.invoke(null, res); +//// } +//// } +// +//// /** +//// * @param path +//// * @param id +//// * @param applyLocally +//// */ +//// @ReactMethod +//// public void startTransaction(final String path, final String id, final Boolean applyLocally) { +//// AsyncTask.execute(new Runnable() { +//// @Override +//// public void run() { +//// DatabaseReference transactionRef = FirebaseDatabase.getInstance().getReference(path); +//// +//// transactionRef.runTransaction(new Transaction.Handler() { +//// @Override +//// public Transaction.Result doTransaction(MutableData mutableData) { +//// final WritableMap updatesMap = Arguments.createMap(); +//// +//// updatesMap.putString("id", id); +//// updatesMap.putString("type", "update"); +//// +//// if (!mutableData.hasChildren()) { +//// Utils.mapPutValue("value", mutableData.getValue(), updatesMap); +//// } else { +//// Object value = Utils.castValue(mutableData); +//// if (value instanceof WritableNativeArray) { +//// updatesMap.putArray("value", (WritableArray) value); +//// } else { +//// updatesMap.putMap("value", (WritableMap) value); +//// } +//// } +//// +//// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = new RNFirebaseTransactionHandler(); +//// mTransactionHandlers.put(id, rnFirebaseTransactionHandler); +//// +//// AsyncTask.execute(new Runnable() { +//// @Override +//// public void run() { +//// Utils.sendEvent(getReactApplicationContext(), "database_transaction_event", updatesMap); +//// } +//// }); +//// +//// try { +//// rnFirebaseTransactionHandler.await(); +//// } catch (InterruptedException e) { +//// rnFirebaseTransactionHandler.interrupted = true; +//// return Transaction.abort(); +//// } +//// +//// if (rnFirebaseTransactionHandler.abort) { +//// return Transaction.abort(); +//// } +//// +//// mutableData.setValue(rnFirebaseTransactionHandler.value); +//// return Transaction.success(mutableData); +//// } +//// +//// @Override +//// public void onComplete(DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) { +//// final WritableMap updatesMap = Arguments.createMap(); +//// updatesMap.putString("id", id); +//// +//// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = mTransactionHandlers.get(id); +//// +//// // TODO error conversion util for database to create web sdk codes based on DatabaseError +//// if (databaseError != null) { +//// updatesMap.putString("type", "error"); +//// +//// updatesMap.putInt("code", databaseError.getCode()); +//// updatesMap.putString("message", databaseError.getMessage()); +//// } else if (rnFirebaseTransactionHandler.interrupted) { +//// updatesMap.putString("type", "error"); +//// +//// updatesMap.putInt("code", 666); +//// updatesMap.putString("message", "RNFirebase transaction was interrupted, aborting."); +//// } else { +//// updatesMap.putString("type", "complete"); +//// updatesMap.putBoolean("committed", committed); +//// updatesMap.putMap("snapshot", Utils.snapshotToMap(dataSnapshot)); +//// } +//// +//// Utils.sendEvent(getReactApplicationContext(), "database_transaction_event", updatesMap); +//// mTransactionHandlers.remove(id); +//// } +//// }, applyLocally); +//// } +//// }); +//// } +//// +//// /** +//// * +//// * @param id +//// * @param updates +//// */ +//// @ReactMethod +//// public void tryCommitTransaction(final String id, final ReadableMap updates) { +//// Map updatesReturned = Utils.recursivelyDeconstructReadableMap(updates); +//// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = mTransactionHandlers.get(id); +//// +//// if (rnFirebaseTransactionHandler != null) { +//// rnFirebaseTransactionHandler.signalUpdateReceived(updatesReturned); +//// } +//// } // // @ReactMethod -// public void withPriority( -// final String path, -// final ReadableMap data, -// final ReadableMap priority, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// Map dataMap = Utils.recursivelyDeconstructReadableMap(data); -// Map priorityMap = Utils.recursivelyDeconstructReadableMap(priority); -// -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("withPriority", callback, error); -// } -// }; -// -// ref.setValue(dataMap.get("value"), priorityMap.get("value"), listener); -// } -// -// @ReactMethod -// public void update(final String path, -// final ReadableMap props, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// Map m = Utils.recursivelyDeconstructReadableMap(props); -// -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("update", callback, error); -// } -// }; -// -// ref.updateChildren(m, listener); -// } - -// @ReactMethod -// public void remove(final String path, -// final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("remove", callback, error); -// } -// }; -// -// ref.removeValue(listener); -// } - -// @ReactMethod -// public void push(final String path, -// final ReadableMap props, -// final Callback callback) { -// -// Log.d(TAG, "Called push with " + path); -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// DatabaseReference newRef = ref.push(); -// -// final Uri url = Uri.parse(newRef.toString()); -// final String newPath = url.getPath(); -// -// ReadableMapKeySetIterator iterator = props.keySetIterator(); -// if (iterator.hasNextKey()) { -// Log.d(TAG, "Passed value to push"); -// // lame way to check if the `props` are empty -// Map m = Utils.recursivelyDeconstructReadableMap(props); -// -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// if (error != null) { -// WritableMap err = Arguments.createMap(); -// err.putInt("code", error.getCode()); -// err.putString("details", error.getDetails()); -// err.putString("description", error.getMessage()); -// callback.invoke(err); -// } else { -// WritableMap res = Arguments.createMap(); -// res.putString("status", "success"); -// res.putString("ref", newPath); -// callback.invoke(null, res); -// } -// } -// }; -// -// newRef.setValue(m.get("value"), listener); -// } else { -// Log.d(TAG, "No value passed to push: " + newPath); -// WritableMap res = Arguments.createMap(); -// res.putString("status", "success"); -// res.putString("ref", newPath); -// callback.invoke(null, res); -// } -// } - -// /** -// * @param path -// * @param id -// * @param applyLocally -// */ -// @ReactMethod -// public void startTransaction(final String path, final String id, final Boolean applyLocally) { -// AsyncTask.execute(new Runnable() { -// @Override -// public void run() { -// DatabaseReference transactionRef = FirebaseDatabase.getInstance().getReference(path); -// -// transactionRef.runTransaction(new Transaction.Handler() { -// @Override -// public Transaction.Result doTransaction(MutableData mutableData) { -// final WritableMap updatesMap = Arguments.createMap(); -// -// updatesMap.putString("id", id); -// updatesMap.putString("type", "update"); -// -// if (!mutableData.hasChildren()) { -// Utils.mapPutValue("value", mutableData.getValue(), updatesMap); -// } else { -// Object value = Utils.castValue(mutableData); -// if (value instanceof WritableNativeArray) { -// updatesMap.putArray("value", (WritableArray) value); -// } else { -// updatesMap.putMap("value", (WritableMap) value); -// } -// } -// -// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = new RNFirebaseTransactionHandler(); -// mTransactionHandlers.put(id, rnFirebaseTransactionHandler); -// -// AsyncTask.execute(new Runnable() { -// @Override -// public void run() { -// Utils.sendEvent(getReactApplicationContext(), "database_transaction_event", updatesMap); -// } -// }); -// -// try { -// rnFirebaseTransactionHandler.await(); -// } catch (InterruptedException e) { -// rnFirebaseTransactionHandler.interrupted = true; -// return Transaction.abort(); -// } -// -// if (rnFirebaseTransactionHandler.abort) { -// return Transaction.abort(); -// } -// -// mutableData.setValue(rnFirebaseTransactionHandler.value); -// return Transaction.success(mutableData); -// } -// -// @Override -// public void onComplete(DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) { -// final WritableMap updatesMap = Arguments.createMap(); -// updatesMap.putString("id", id); -// -// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = mTransactionHandlers.get(id); -// -// // TODO error conversion util for database to create web sdk codes based on DatabaseError -// if (databaseError != null) { -// updatesMap.putString("type", "error"); -// -// updatesMap.putInt("code", databaseError.getCode()); -// updatesMap.putString("message", databaseError.getMessage()); -// } else if (rnFirebaseTransactionHandler.interrupted) { -// updatesMap.putString("type", "error"); -// -// updatesMap.putInt("code", 666); -// updatesMap.putString("message", "RNFirebase transaction was interrupted, aborting."); -// } else { -// updatesMap.putString("type", "complete"); -// updatesMap.putBoolean("committed", committed); -// updatesMap.putMap("snapshot", Utils.snapshotToMap(dataSnapshot)); -// } -// -// Utils.sendEvent(getReactApplicationContext(), "database_transaction_event", updatesMap); -// mTransactionHandlers.remove(id); -// } -// }, applyLocally); -// } -// }); -// } - -// /** -// * -// * @param id -// * @param updates -// */ -// @ReactMethod -// public void tryCommitTransaction(final String id, final ReadableMap updates) { -// Map updatesReturned = Utils.recursivelyDeconstructReadableMap(updates); -// RNFirebaseTransactionHandler rnFirebaseTransactionHandler = mTransactionHandlers.get(id); -// -// if (rnFirebaseTransactionHandler != null) { -// rnFirebaseTransactionHandler.signalUpdateReceived(updatesReturned); -// } -// } - - @ReactMethod - public void on(final int refId, final String path, final ReadableArray modifiers, final int listenerId, final String eventName, final Callback callback) { - RNFirebaseDatabaseReference ref = this.getDBHandle(refId, path, modifiers); - - if (eventName.equals("value")) { - ref.addValueEventListener(listenerId); - } else { - ref.addChildEventListener(listenerId, eventName); - } - - WritableMap resp = Arguments.createMap(); - resp.putString("status", "success"); - resp.putInt("refId", refId); - resp.putString("handle", path); - callback.invoke(null, resp); - } - -// @ReactMethod -// public void once(final int refId, final String path, final ReadableArray modifiers, final String eventName, final Callback callback) { +// public void on(final int refId, final String path, final ReadableArray modifiers, final int listenerId, final String eventName, final Callback callback) { // RNFirebaseDatabaseReference ref = this.getDBHandle(refId, path, modifiers); // // if (eventName.equals("value")) { -// ref.addOnceValueEventListener(callback); +// ref.addValueEventListener(listenerId); // } else { -// ref.addChildOnceEventListener(eventName, callback); +// ref.addChildEventListener(listenerId, eventName); // } +// +// WritableMap resp = Arguments.createMap(); +// resp.putString("status", "success"); +// resp.putInt("refId", refId); +// resp.putString("handle", path); +// callback.invoke(null, resp); // } - - /** - * At the time of this writing, off() only gets called when there are no more subscribers to a given path. - * `mListeners` might therefore be out of sync (though javascript isnt listening for those eventNames, so - * it doesn't really matter- just polluting the RN bridge a little more than necessary. - * off() should therefore clean *everything* up - */ - @ReactMethod - public void off( - final int refId, - final ReadableArray listeners, - final Callback callback) { - - RNFirebaseDatabaseReference r = mReferences.get(refId); - - if (r != null) { - List listenersList = Utils.recursivelyDeconstructReadableArray(listeners); - - for (Object l : listenersList) { - Map listener = (Map) l; - int listenerId = ((Double) listener.get("listenerId")).intValue(); - String eventName = (String) listener.get("eventName"); - r.removeEventListener(listenerId, eventName); - if (!r.hasListeners()) { - mReferences.remove(refId); - } - } - } - - Log.d(TAG, "Removed listeners refId: " + refId + " ; count: " + listeners.size()); - WritableMap resp = Arguments.createMap(); - resp.putInt("refId", refId); - resp.putString("status", "success"); - callback.invoke(null, resp); - } - +// +//// @ReactMethod +//// public void once(final int refId, final String path, final ReadableArray modifiers, final String eventName, final Callback callback) { +//// RNFirebaseDatabaseReference ref = this.getDBHandle(refId, path, modifiers); +//// +//// if (eventName.equals("value")) { +//// ref.addOnceValueEventListener(callback); +//// } else { +//// ref.addChildOnceEventListener(eventName, callback); +//// } +//// } +// +// /** +// * At the time of this writing, off() only gets called when there are no more subscribers to a given path. +// * `mListeners` might therefore be out of sync (though javascript isnt listening for those eventNames, so +// * it doesn't really matter- just polluting the RN bridge a little more than necessary. +// * off() should therefore clean *everything* up +// */ // @ReactMethod -// public void onDisconnectSet(final String path, final ReadableMap props, final Callback callback) { -// String type = props.getString("type"); -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// OnDisconnect od = ref.onDisconnect(); -// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("onDisconnectSet", callback, error); -// } -// }; +// public void off( +// final int refId, +// final ReadableArray listeners, +// final Callback callback) { // -// switch (type) { -// case "object": -// Map map = Utils.recursivelyDeconstructReadableMap(props.getMap("value")); -// od.setValue(map, listener); -// break; -// case "array": -// List list = Utils.recursivelyDeconstructReadableArray(props.getArray("value")); -// od.setValue(list, listener); -// break; -// case "string": -// od.setValue(props.getString("value"), listener); -// break; -// case "number": -// od.setValue(props.getDouble("value"), listener); -// break; -// case "boolean": -// od.setValue(props.getBoolean("value"), listener); -// break; -// case "null": -// od.setValue(null, listener); -// break; -// } -// } -// -// @ReactMethod -// public void onDisconnectUpdate(final String path, final ReadableMap props, final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// OnDisconnect od = ref.onDisconnect(); -// Map map = Utils.recursivelyDeconstructReadableMap(props); -// od.updateChildren(map, new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("onDisconnectUpdate", callback, error); -// } -// }); -// } -// -// @ReactMethod -// public void onDisconnectRemove(final String path, final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// -// OnDisconnect od = ref.onDisconnect(); -// od.removeValue(new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("onDisconnectRemove", callback, error); -// } -// }); -// } -// -// @ReactMethod -// public void onDisconnectCancel(final String path, final Callback callback) { -// DatabaseReference ref = mFirebaseDatabase.getReference(path); -// -// OnDisconnect od = ref.onDisconnect(); -// od.cancel(new DatabaseReference.CompletionListener() { -// @Override -// public void onComplete(DatabaseError error, DatabaseReference ref) { -// handleCallback("onDisconnectCancel", callback, error); -// } -// }); -// } - -// @ReactMethod -// public void goOnline() { -// mFirebaseDatabase.goOnline(); -// } -// -// @ReactMethod -// public void goOffline() { -// mFirebaseDatabase.goOffline(); -// } - -// private void handleCallback( -// final String methodName, -// final Callback callback, -// final DatabaseError databaseError) { -// if (databaseError != null) { -// WritableMap err = Arguments.createMap(); -// err.putInt("code", databaseError.getCode()); -// err.putString("details", databaseError.getDetails()); -// err.putString("description", databaseError.getMessage()); -// callback.invoke(err); -// } else { -// WritableMap res = Arguments.createMap(); -// res.putString("status", "success"); -// res.putString("method", methodName); -// callback.invoke(null, res); -// } -// } - -// private RNFirebaseDatabaseReference getDBHandle(final int refId, final String path, -// final ReadableArray modifiers) { // RNFirebaseDatabaseReference r = mReferences.get(refId); // -// if (r == null) { -// ReactContext ctx = getReactApplicationContext(); -// r = new RNFirebaseDatabaseReference(ctx, mFirebaseDatabase, refId, path, modifiers); -// mReferences.put(refId, r); +// if (r != null) { +// List listenersList = Utils.recursivelyDeconstructReadableArray(listeners); +// +// for (Object l : listenersList) { +// Map listener = (Map) l; +// int listenerId = ((Double) listener.get("listenerId")).intValue(); +// String eventName = (String) listener.get("eventName"); +// r.removeEventListener(listenerId, eventName); +// if (!r.hasListeners()) { +// mReferences.remove(refId); +// } +// } // } // -// return r; +// Log.d(TAG, "Removed listeners refId: " + refId + " ; count: " + listeners.size()); +// WritableMap resp = Arguments.createMap(); +// resp.putInt("refId", refId); +// resp.putString("status", "success"); +// callback.invoke(null, resp); // } - -// @Override -// public Map getConstants() { -// final Map constants = new HashMap<>(); -// constants.put("serverValueTimestamp", ServerValue.TIMESTAMP); -// return constants; -// } -} +// +//// @ReactMethod +//// public void onDisconnectSet(final String path, final ReadableMap props, final Callback callback) { +//// String type = props.getString("type"); +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// OnDisconnect od = ref.onDisconnect(); +//// DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("onDisconnectSet", callback, error); +//// } +//// }; +//// +//// switch (type) { +//// case "object": +//// Map map = Utils.recursivelyDeconstructReadableMap(props.getMap("value")); +//// od.setValue(map, listener); +//// break; +//// case "array": +//// List list = Utils.recursivelyDeconstructReadableArray(props.getArray("value")); +//// od.setValue(list, listener); +//// break; +//// case "string": +//// od.setValue(props.getString("value"), listener); +//// break; +//// case "number": +//// od.setValue(props.getDouble("value"), listener); +//// break; +//// case "boolean": +//// od.setValue(props.getBoolean("value"), listener); +//// break; +//// case "null": +//// od.setValue(null, listener); +//// break; +//// } +//// } +//// +//// @ReactMethod +//// public void onDisconnectUpdate(final String path, final ReadableMap props, final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// OnDisconnect od = ref.onDisconnect(); +//// Map map = Utils.recursivelyDeconstructReadableMap(props); +//// od.updateChildren(map, new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("onDisconnectUpdate", callback, error); +//// } +//// }); +//// } +//// +//// @ReactMethod +//// public void onDisconnectRemove(final String path, final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// +//// OnDisconnect od = ref.onDisconnect(); +//// od.removeValue(new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("onDisconnectRemove", callback, error); +//// } +//// }); +//// } +//// +//// @ReactMethod +//// public void onDisconnectCancel(final String path, final Callback callback) { +//// DatabaseReference ref = mFirebaseDatabase.getReference(path); +//// +//// OnDisconnect od = ref.onDisconnect(); +//// od.cancel(new DatabaseReference.CompletionListener() { +//// @Override +//// public void onComplete(DatabaseError error, DatabaseReference ref) { +//// handleCallback("onDisconnectCancel", callback, error); +//// } +//// }); +//// } +// +//// @ReactMethod +//// public void goOnline() { +//// mFirebaseDatabase.goOnline(); +//// } +//// +//// @ReactMethod +//// public void goOffline() { +//// mFirebaseDatabase.goOffline(); +//// } +// +//// private void handleCallback( +//// final String methodName, +//// final Callback callback, +//// final DatabaseError databaseError) { +//// if (databaseError != null) { +//// WritableMap err = Arguments.createMap(); +//// err.putInt("code", databaseError.getCode()); +//// err.putString("details", databaseError.getDetails()); +//// err.putString("description", databaseError.getMessage()); +//// callback.invoke(err); +//// } else { +//// WritableMap res = Arguments.createMap(); +//// res.putString("status", "success"); +//// res.putString("method", methodName); +//// callback.invoke(null, res); +//// } +//// } +// +//// private RNFirebaseDatabaseReference getDBHandle(final int refId, final String path, +//// final ReadableArray modifiers) { +//// RNFirebaseDatabaseReference r = mReferences.get(refId); +//// +//// if (r == null) { +//// ReactContext ctx = getReactApplicationContext(); +//// r = new RNFirebaseDatabaseReference(ctx, mFirebaseDatabase, refId, path, modifiers); +//// mReferences.put(refId, r); +//// } +//// +//// return r; +//// } +// +//// @Override +//// public Map getConstants() { +//// final Map constants = new HashMap<>(); +//// constants.put("serverValueTimestamp", ServerValue.TIMESTAMP); +//// return constants; +//// } +//} diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseReference.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseReference.java index c05f1cf2..714999f1 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseReference.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabaseReference.java @@ -55,6 +55,7 @@ public class RNFirebaseDatabaseReference { /** * Listen for a single 'value' event from firebase. + * * @param promise */ void addOnceValueEventListener(final Promise promise) { @@ -78,6 +79,7 @@ public class RNFirebaseDatabaseReference { /** * Listen for single 'child_X' event from firebase. + * * @param eventName * @param promise */ @@ -130,14 +132,22 @@ public class RNFirebaseDatabaseReference { } + void on(String eventName) { + } - - - - - - + /** + * + * @param eventName + * @param promise + */ + void once(String eventName, Promise promise) { + if (eventName.equals("value")) { + addOnceValueEventListener(promise); + } else { + addChildOnceEventListener(eventName, promise); + } + } // todo cleanup all below @@ -212,7 +222,6 @@ public class RNFirebaseDatabaseReference { } - void removeEventListener(int listenerId, String eventName) { if ("value".equals(eventName)) { this.removeValueEventListener(listenerId); diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index 593c9cbb..1b059ee2 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -11,18 +11,29 @@ import ModuleBase from './../../utils/ModuleBase'; /** * @class Database */ - export default class Database extends ModuleBase { constructor(firebaseApp: Object, options: Object = {}) { super(firebaseApp, options, 'Database', true); + this._serverTimeOffset = 0; this._transactionHandler = new TransactionHandler(this); - if (this._options.persistence) this._native.setPersistence(this._options.persistence); + + if (this._options.persistence) { + this._native.setPersistence(this._options.persistence); + } // todo event & error listeners // todo serverTimeOffset event/listener - make ref natively and switch to events // todo use nativeToJSError for on/off error events } + /** + * + * @return {number} + */ + getServerTime() { + return new Date().getTime() + this._serverTimeOffset; + } + /** * */ @@ -45,6 +56,14 @@ export default class Database extends ModuleBase { ref(path: string) { return new Reference(this, path); } + + + /** + * INTERNALS + */ + + // todo handleDbEvent + // todo handleDbError } export const statics = { diff --git a/lib/modules/database/index.old.js b/lib/modules/database/index.old.js index b02316b0..6b549ab8 100644 --- a/lib/modules/database/index.old.js +++ b/lib/modules/database/index.old.js @@ -57,6 +57,7 @@ export default class Database extends ModuleBase { const { listenerId, eventName } = listener; this.log.debug('on() : ', ref.refId, listenerId, eventName); this.references[refId] = ref; + // todo pointless promise, doesn't need to return anything return promisify('on', this._native)(refId, path, query.getModifiers(), listenerId, eventName); } @@ -105,9 +106,9 @@ export default class Database extends ModuleBase { /** * INTERNALS */ - _getServerTime() { - return new Date().getTime() + this.serverTimeOffset; - } + // _getServerTime() { + // return new Date().getTime() + this.serverTimeOffset; + // } // /** // * Enabled / disable database persistence diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index 351d2843..7cc4e478 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -609,7 +609,6 @@ export default class Reference extends ReferenceBase { if (!isFunction(successCallback)) throw new Error('Query.on failed: Second argument must be a valid function.'); if (arguments.length > 2 && !failureCallbackOrContext) throw new Error('Query.on failed: third argument must either be a cancel callback or a context object.'); - // TODO this.log.debug('adding reference.on', this._refId, eventType); let _failureCallback; let _context; @@ -632,7 +631,7 @@ export default class Reference extends ReferenceBase { failureCallbackOrContext(error); }; } - + // brb, helping someone let _successCallback; if (_context) { diff --git a/lib/modules/database/transaction.js b/lib/modules/database/transaction.js index 3dfcdd99..f632714a 100644 --- a/lib/modules/database/transaction.js +++ b/lib/modules/database/transaction.js @@ -20,7 +20,7 @@ export default class TransactionHandler { } /** - * Add a new transaction and begin starts it natively. + * Add a new transaction and start it natively. * @param reference * @param transactionUpdater * @param onComplete diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 516751bb..1600c1bd 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -26,6 +26,9 @@ const NATIVE_MODULE_EVENTS = { ], Database: [ 'database_transaction_event', + 'database_event', + 'database_error', + 'database_server_offset', ], };