Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/firebase_database/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.0.6

* Various APIs added to FirebaseDatabase and Query
* Added removal and priority to DatabaseReference
* Improved documentation
* Added unit tests

## 0.0.5

* Fixed analyzer warnings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,38 +118,95 @@ public void onDataChange(DataSnapshot snapshot) {
@SuppressWarnings("unchecked")
@Override
public void onMethodCall(MethodCall call, final Result result) {
Map<String, ?> arguments = (Map<String, ?>) call.arguments;
if (call.method.equals("DatabaseReference#set")) {
Object value = arguments.get("value");
getReference(arguments).setValue(value, new DefaultCompletionListener(result));
} else if (call.method.equals("Query#observe")) {
String eventType = (String) arguments.get("eventType");
int handle = nextHandle++;
EventObserver observer = new EventObserver(eventType, handle);
observers.put(handle, observer);
if (eventType.equals(EVENT_TYPE_VALUE)) {
getReference(arguments).addValueEventListener(observer);
} else {
getReference(arguments).addChildEventListener(observer);
}
result.success(handle);
} else if (call.method.equals("Query#removeObserver")) {
DatabaseReference reference = getReference(arguments);
int handle = (Integer) arguments.get("handle");
EventObserver observer = observers.get(handle);
if (observer != null) {
if (observer.requestedEventType.equals(EVENT_TYPE_VALUE)) {
reference.removeEventListener((ValueEventListener) observer);
} else {
reference.removeEventListener((ChildEventListener) observer);
Map<String, Object> arguments = (Map<String, Object>) call.arguments;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the unchecked cast warning, do

Map<String, Object> arguments = call.arguments();

switch (call.method) {
case "FirebaseDatabase#goOnline":
FirebaseDatabase.getInstance().goOnline();
break;

case "FirebaseDatabase#goOffline":
FirebaseDatabase.getInstance().goOffline();
break;

case "FirebaseDatabase#purgeOutstandingWrites":
FirebaseDatabase.getInstance().purgeOutstandingWrites();
break;

case "FirebaseDatabase#setPersistenceEnabled":
{
boolean isEnabled = (boolean) arguments.get("enabled");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] You can avoid cast with

Boolean isEnabled = arguments.get("enabled");

Similarly below.

FirebaseDatabase.getInstance().setPersistenceEnabled(isEnabled);
break;
}

case "FirebaseDatabase#setPersistenceCacheSizeBytes":
{
long cacheSize = (long) arguments.get("cacheSize");
FirebaseDatabase.getInstance().setPersistenceCacheSizeBytes(cacheSize);
break;
}

case "DatabaseReference#set":
{
Object value = arguments.get("value");
Object priority = arguments.get("priority");
DatabaseReference reference = getReference(arguments);
if (priority != null) {
reference.setValue(value, priority, new DefaultCompletionListener(result));
} else {
reference.setValue(value, new DefaultCompletionListener(result));
}
break;
}

case "DatabaseReference#setPriority":
{
Object priority = arguments.get("priority");
DatabaseReference reference = getReference(arguments);
reference.setPriority(priority, new DefaultCompletionListener(result));
break;
}

case "Query#observe":
{
String eventType = (String) arguments.get("eventType");
int handle = nextHandle++;
EventObserver observer = new EventObserver(eventType, handle);
observers.put(handle, observer);
if (eventType.equals(EVENT_TYPE_VALUE)) {
getReference(arguments).addValueEventListener(observer);
} else {
getReference(arguments).addChildEventListener(observer);
}
result.success(handle);
break;
}

case "Query#removeObserver":
{
DatabaseReference reference = getReference(arguments);
int handle = (Integer) arguments.get("handle");
EventObserver observer = observers.get(handle);
if (observer != null) {
if (observer.requestedEventType.equals(EVENT_TYPE_VALUE)) {
reference.removeEventListener((ValueEventListener) observer);
} else {
reference.removeEventListener((ChildEventListener) observer);
}
observers.delete(handle);
result.success(null);
break;
} else {
result.error("unknown_handle", "removeObserver called on an unknown handle", null);
break;
}
}

default:
{
result.notImplemented();
break;
}
observers.delete(handle);
result.success(null);
} else {
result.error("unknown_handle", "removeObserver called on an unknown handle", null);
}
} else {
result.notImplemented();
}
}
}
61 changes: 58 additions & 3 deletions packages/firebase_database/ios/Classes/FirebaseDatabasePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,42 @@ - (FlutterError *)flutterError {
return ref;
}

FIRDatabaseQuery *getQuery(NSDictionary *arguments) {
FIRDatabaseQuery *query = getReference(arguments);
NSDictionary *parameters = arguments[@"parameters"];
NSString *orderBy = parameters[@"orderBy"];
if ([orderBy isEqualToString:@"child"]) {
query = [query queryOrderedByChild:parameters[@"orderByChildKey"]];
} else if ([orderBy isEqualToString:@"key"]) {
query = [query queryOrderedByKey];
} else if ([orderBy isEqualToString:@"value"]) {
query = [query queryOrderedByValue];
} else if ([orderBy isEqualToString:@"priority"]) {
query = [query queryOrderedByPriority];
}
id startAt = parameters[@"startAt"];
if (startAt) {
query = [query queryStartingAtValue:startAt childKey:parameters[@"endAtKey"]];
}
id endAt = parameters[@"endAt"];
if (endAt) {
query = [query queryEndingAtValue:endAt childKey:parameters[@"endAtKey"]];
}
id equalTo = parameters[@"equalTo"];
if (equalTo) {
query = [query queryEqualToValue:equalTo];
}
NSNumber *limitToFirst = parameters[@"limitToFirst"];
if (limitToFirst) {
query = [query queryLimitedToFirst:limitToFirst.intValue];
}
NSNumber *limitToLast = parameters[@"limitToLast"];
if (limitToLast) {
query = [query queryLimitedToLast:limitToLast.intValue];
}
return query;
}

FIRDataEventType parseEventType(NSString *eventTypeString) {
if ([@"_EventType.childAdded" isEqual:eventTypeString]) {
return FIRDataEventTypeChildAdded;
Expand Down Expand Up @@ -67,12 +103,28 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
^(NSError *error, FIRDatabaseReference *ref) {
result(error.flutterError);
};
if ([@"DatabaseReference#set" isEqualToString:call.method]) {
if ([@"FirebaseDatabase#goOnline" isEqualToString:call.method]) {
[[FIRDatabase database] goOnline];
} else if ([@"FirebaseDatabase#goOffline" isEqualToString:call.method]) {
[[FIRDatabase database] goOffline];
} else if ([@"FirebaseDatabase#purgeOutstandingWrites" isEqualToString:call.method]) {
[[FIRDatabase database] purgeOutstandingWrites];
} else if ([@"FirebaseDatabase#setPersistenceEnabled" isEqualToString:call.method]) {
NSNumber *value = call.arguments[@"value"];
[FIRDatabase database].persistenceEnabled = value.boolValue;
} else if ([@"FirebaseDatabase#setPersistenceCacheSizeBytes" isEqualToString:call.method]) {
NSNumber *value = call.arguments[@"value"];
[FIRDatabase database].persistenceCacheSizeBytes = value.unsignedIntegerValue;
} else if ([@"DatabaseReference#set" isEqualToString:call.method]) {
[getReference(call.arguments) setValue:call.arguments[@"value"]
andPriority:call.arguments[@"priority"]
withCompletionBlock:defaultCompletionBlock];
} else if ([@"DatabaseReference#setPriority" isEqualToString:call.method]) {
[getReference(call.arguments) setPriority:call.arguments[@"priority"]
withCompletionBlock:defaultCompletionBlock];
} else if ([@"Query#observe" isEqualToString:call.method]) {
FIRDataEventType eventType = parseEventType(call.arguments[@"eventType"]);
__block FIRDatabaseHandle handle = [getReference(call.arguments)
__block FIRDatabaseHandle handle = [getQuery(call.arguments)
observeEventType:eventType
andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *previousSiblingKey) {
[self.channel invokeMethod:@"Event"
Expand All @@ -88,8 +140,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
result([NSNumber numberWithUnsignedInteger:handle]);
} else if ([@"Query#removeObserver" isEqualToString:call.method]) {
FIRDatabaseHandle handle = [call.arguments[@"handle"] unsignedIntegerValue];
[getReference(call.arguments) removeObserverWithHandle:handle];
[getQuery(call.arguments) removeObserverWithHandle:handle];
result(nil);
} else if ([@"Query#keepSynced" isEqualToString:call.method]) {
NSNumber *value = call.arguments[@"value"];
[getQuery(call.arguments) keepSynced:value];
} else {
result(FlutterMethodNotImplemented);
}
Expand Down
51 changes: 46 additions & 5 deletions packages/firebase_database/lib/src/database_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ part of firebase_database;
/// `DatabaseReference`s (ie. `child`).
class DatabaseReference extends Query {
DatabaseReference._(FirebaseDatabase database, List<String> pathComponents)
: super._(database, pathComponents);
: super._(database: database, pathComponents: pathComponents);

/// Gets a DatabaseReference for the location at the specified relative
/// path. The relative path can either be a simple child key (e.g. ‘fred’) or
Expand Down Expand Up @@ -60,7 +60,7 @@ class DatabaseReference extends Query {
return new DatabaseReference._(_database, childPath);
}

/// Write data to this Firebase Database location.
/// Write `value` to the location with the specified `priority` if applicable.
///
/// This will overwrite any data at this location and all child locations.
///
Expand All @@ -72,12 +72,53 @@ class DatabaseReference extends Query {
///
/// Passing null for the new value means all data at this location or any
/// child location will be deleted.
Future<Null> set(dynamic value) async {
await _database._channel.invokeMethod(
Future<Null> set(dynamic value, { dynamic priority }) {
return _database._channel.invokeMethod(
'DatabaseReference#set',
{ 'path': path, 'value': value },
{ 'path': path, 'value': value, 'priority': priority },
);
}

/// Sets a priority for the data at this Firebase Database location.
///
/// Priorities can be used to provide a custom ordering for the children at a
/// location (if no priorities are specified, the children are ordered by
/// key).
///
/// You cannot set a priority on an empty location. For this reason
/// set() should be used when setting initial data with a specific priority
/// and setPriority() should be used when updating the priority of existing
/// data.
///
/// Children are sorted based on this priority using the following rules:
///
/// Children with no priority come first. Children with a number as their
/// priority come next. They are sorted numerically by priority (small to
/// large). Children with a string as their priority come last. They are
/// sorted lexicographically by priority. Whenever two children have the same
/// priority (including no priority), they are sorted by key. Numeric keys
/// come first (sorted numerically), followed by the remaining keys (sorted
/// lexicographically).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing /// here?

/// Note that priorities are parsed and ordered as IEEE 754 double-precision
/// floating-point numbers. Keys are always stored as strings and are treated
/// as numbers only when they can be parsed as a 32-bit integer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Missing . at the end.

Future<Null> setPriority(dynamic priority) async {
return _database._channel.invokeMethod(
'DatabaseReference#setPriority',
{ 'path': path, 'priority': priority },
);
}

/// Remove the data at this Firebase Database location. Any data at child
/// locations will also be deleted.
///
/// The effect of the delete will be visible immediately and the corresponding
/// events will be triggered. Synchronization of the delete to the Firebase
/// Database servers will also be started.
///
/// remove() is equivalent to calling set(null)
Future<Null> remove() => set(null);
}
class ServerValue {
static const timestamp = const {'.sv' : 'timestamp'};
Expand Down
2 changes: 1 addition & 1 deletion packages/firebase_database/lib/src/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum _EventType {
childRemoved,
childChanged,
childMoved,
value
value,
}

/// `Event` encapsulates a DataSnapshot and possibly also the key of its
Expand Down
Loading