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 1 commit
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,101 @@ 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":
{
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be in a block?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't, I was trying to be consistent with the others but maybe it's better not to do a block. I've removed the braces for the methods that don't take arguments.

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