Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 7537198

Browse files
committed
Merge branch 'master' into add-annotations
2 parents 62b3f4f + 2570771 commit 7537198

36 files changed

Lines changed: 612 additions & 266 deletions

File tree

packages/cloud_firestore/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 0.12.9
2+
3+
* New optional `includeMetadataChanges` parameter added to `DocumentReference.snapshots()`
4+
and `Query.snapshots()`
5+
* Fix example app crash when the `message` field was not a string
6+
* Internal renaming of method names.
7+
8+
## 0.12.8+1
9+
10+
* Add `metadata` to `QuerySnapshot`.
11+
112
## 0.12.8
213

314
* Updated how document ids are generated to more closely match native implementations.

packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.google.firebase.firestore.FirebaseFirestoreSettings;
3232
import com.google.firebase.firestore.GeoPoint;
3333
import com.google.firebase.firestore.ListenerRegistration;
34+
import com.google.firebase.firestore.MetadataChanges;
3435
import com.google.firebase.firestore.Query;
3536
import com.google.firebase.firestore.QuerySnapshot;
3637
import com.google.firebase.firestore.SetOptions;
@@ -192,6 +193,11 @@ private Map<String, Object> parseQuerySnapshot(QuerySnapshot querySnapshot) {
192193
}
193194
data.put("documentChanges", documentChanges);
194195

196+
Map<String, Object> metadata = new HashMap<>();
197+
metadata.put("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites());
198+
metadata.put("isFromCache", querySnapshot.getMetadata().isFromCache());
199+
data.put("metadata", metadata);
200+
195201
return data;
196202
}
197203

@@ -619,22 +625,32 @@ public void run() {
619625
int handle = nextListenerHandle++;
620626
EventObserver observer = new EventObserver(handle);
621627
observers.put(handle, observer);
622-
listenerRegistrations.put(handle, getQuery(arguments).addSnapshotListener(observer));
628+
MetadataChanges metadataChanges =
629+
(Boolean) arguments.get("includeMetadataChanges")
630+
? MetadataChanges.INCLUDE
631+
: MetadataChanges.EXCLUDE;
632+
listenerRegistrations.put(
633+
handle, getQuery(arguments).addSnapshotListener(metadataChanges, observer));
623634
result.success(handle);
624635
break;
625636
}
626-
case "Query#addDocumentListener":
637+
case "DocumentReference#addSnapshotListener":
627638
{
628639
Map<String, Object> arguments = call.arguments();
629640
int handle = nextListenerHandle++;
630641
DocumentObserver observer = new DocumentObserver(handle);
631642
documentObservers.put(handle, observer);
643+
MetadataChanges metadataChanges =
644+
(Boolean) arguments.get("includeMetadataChanges")
645+
? MetadataChanges.INCLUDE
646+
: MetadataChanges.EXCLUDE;
632647
listenerRegistrations.put(
633-
handle, getDocumentReference(arguments).addSnapshotListener(observer));
648+
handle,
649+
getDocumentReference(arguments).addSnapshotListener(metadataChanges, observer));
634650
result.success(handle);
635651
break;
636652
}
637-
case "Query#removeListener":
653+
case "removeListener":
638654
{
639655
Map<String, Object> arguments = call.arguments();
640656
int handle = (Integer) arguments.get("handle");

packages/cloud_firestore/example/lib/main.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ class MessageList extends StatelessWidget {
4141
itemCount: messageCount,
4242
itemBuilder: (_, int index) {
4343
final DocumentSnapshot document = snapshot.data.documents[index];
44+
final dynamic message = document['message'];
4445
return ListTile(
45-
title: Text(document['message'] ?? '<No message retrieved>'),
46+
title: Text(
47+
message != null ? message.toString() : '<No message retrieved>',
48+
),
4649
subtitle: Text('Message ${index + 1} of $messageCount'),
4750
);
4851
},
@@ -54,7 +57,9 @@ class MessageList extends StatelessWidget {
5457

5558
class MyHomePage extends StatelessWidget {
5659
MyHomePage({this.firestore});
60+
5761
final Firestore firestore;
62+
5863
CollectionReference get messages => firestore.collection('messages');
5964

6065
Future<void> _addMessage() async {

packages/cloud_firestore/example/test_driver/cloud_firestore.dart

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import 'dart:async';
2-
import 'package:flutter_driver/driver_extension.dart';
3-
import 'package:flutter_test/flutter_test.dart';
2+
43
import 'package:cloud_firestore/cloud_firestore.dart';
54
import 'package:firebase_core/firebase_core.dart';
5+
import 'package:flutter_driver/driver_extension.dart';
6+
import 'package:flutter_test/flutter_test.dart';
67

78
void main() {
89
final Completer<String> completer = Completer<String>();
@@ -51,6 +52,7 @@ void main() {
5152
.where('message', isEqualTo: 'Hello world!')
5253
.limit(1);
5354
final QuerySnapshot querySnapshot = await query.getDocuments();
55+
expect(querySnapshot.metadata, isNotNull);
5456
expect(querySnapshot.documents.first['message'], 'Hello world!');
5557
final DocumentReference firstDoc =
5658
querySnapshot.documents.first.reference;
@@ -70,6 +72,7 @@ void main() {
7072
.limit(1);
7173
final QuerySnapshot querySnapshot = await query.getDocuments();
7274
expect(querySnapshot.documents.first['stars'], 5);
75+
expect(querySnapshot.metadata, isNotNull);
7376
});
7477

7578
test('increment', () async {
@@ -103,6 +106,36 @@ void main() {
103106
await ref.delete();
104107
});
105108

109+
test('includeMetadataChanges', () async {
110+
final DocumentReference ref = firestore.collection('messages').document();
111+
final Stream<DocumentSnapshot> snapshotWithoutMetadataChanges =
112+
ref.snapshots(includeMetadataChanges: false).take(1);
113+
final Stream<DocumentSnapshot> snapshotsWithMetadataChanges =
114+
ref.snapshots(includeMetadataChanges: true).take(3);
115+
116+
ref.setData(<String, dynamic>{'hello': 'world'});
117+
118+
final DocumentSnapshot snapshot =
119+
await snapshotWithoutMetadataChanges.first;
120+
expect(snapshot.metadata.hasPendingWrites, true);
121+
expect(snapshot.metadata.isFromCache, true);
122+
expect(snapshot.data['hello'], 'world');
123+
124+
final List<DocumentSnapshot> snapshots =
125+
await snapshotsWithMetadataChanges.toList();
126+
expect(snapshots[0].metadata.hasPendingWrites, true);
127+
expect(snapshots[0].metadata.isFromCache, true);
128+
expect(snapshots[0].data['hello'], 'world');
129+
expect(snapshots[1].metadata.hasPendingWrites, true);
130+
expect(snapshots[1].metadata.isFromCache, false);
131+
expect(snapshots[1].data['hello'], 'world');
132+
expect(snapshots[2].metadata.hasPendingWrites, false);
133+
expect(snapshots[2].metadata.isFromCache, false);
134+
expect(snapshots[2].data['hello'], 'world');
135+
136+
await ref.delete();
137+
});
138+
106139
test('runTransaction', () async {
107140
final DocumentReference ref = firestore.collection('messages').document();
108141
await ref.setData(<String, dynamic>{

packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ static FIRFirestoreSource getSource(NSDictionary *arguments) {
203203
@"documentChanges" : documentChanges,
204204
@"documents" : documents,
205205
@"metadatas" : metadatas,
206+
@"metadata" : @{
207+
@"hasPendingWrites" : @(snapshot.metadata.hasPendingWrites),
208+
@"isFromCache" : @(snapshot.metadata.isFromCache),
209+
}
206210
};
207211
}
208212

@@ -522,39 +526,52 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
522526
message:[exception name]
523527
details:[exception reason]]);
524528
}
529+
NSNumber *includeMetadataChanges = call.arguments[@"includeMetadataChanges"];
525530
id<FIRListenerRegistration> listener = [query
526-
addSnapshotListener:^(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error) {
527-
if (snapshot == nil) {
528-
result(getFlutterError(error));
529-
return;
530-
}
531-
NSMutableDictionary *arguments = [parseQuerySnapshot(snapshot) mutableCopy];
532-
[arguments setObject:handle forKey:@"handle"];
533-
[weakSelf.channel invokeMethod:@"QuerySnapshot" arguments:arguments];
534-
}];
531+
addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges.boolValue
532+
listener:^(FIRQuerySnapshot *_Nullable snapshot,
533+
NSError *_Nullable error) {
534+
if (snapshot == nil) {
535+
result(getFlutterError(error));
536+
return;
537+
}
538+
NSMutableDictionary *arguments =
539+
[parseQuerySnapshot(snapshot) mutableCopy];
540+
[arguments setObject:handle forKey:@"handle"];
541+
[weakSelf.channel invokeMethod:@"QuerySnapshot"
542+
arguments:arguments];
543+
}];
535544
_listeners[handle] = listener;
536545
result(handle);
537-
} else if ([@"Query#addDocumentListener" isEqualToString:call.method]) {
546+
} else if ([@"DocumentReference#addSnapshotListener" isEqualToString:call.method]) {
538547
__block NSNumber *handle = [NSNumber numberWithInt:_nextListenerHandle++];
539548
FIRDocumentReference *document = getDocumentReference(call.arguments);
540-
id<FIRListenerRegistration> listener =
541-
[document addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) {
542-
if (snapshot == nil) {
543-
result(getFlutterError(error));
544-
return;
545-
}
546-
[weakSelf.channel invokeMethod:@"DocumentSnapshot"
547-
arguments:@{
548-
@"handle" : handle,
549-
@"path" : snapshot ? snapshot.reference.path : [NSNull null],
550-
@"data" : snapshot.exists ? snapshot.data : [NSNull null],
551-
@"metadata" : snapshot ? @{
552-
@"hasPendingWrites" : @(snapshot.metadata.hasPendingWrites),
553-
@"isFromCache" : @(snapshot.metadata.isFromCache),
554-
}
555-
: [NSNull null],
556-
}];
557-
}];
549+
NSNumber *includeMetadataChanges = call.arguments[@"includeMetadataChanges"];
550+
id<FIRListenerRegistration> listener = [document
551+
addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges.boolValue
552+
listener:^(FIRDocumentSnapshot *snapshot,
553+
NSError *_Nullable error) {
554+
if (snapshot == nil) {
555+
result(getFlutterError(error));
556+
return;
557+
}
558+
[weakSelf.channel
559+
invokeMethod:@"DocumentSnapshot"
560+
arguments:@{
561+
@"handle" : handle,
562+
@"path" : snapshot ? snapshot.reference.path
563+
: [NSNull null],
564+
@"data" : snapshot.exists ? snapshot.data
565+
: [NSNull null],
566+
@"metadata" : snapshot ? @{
567+
@"hasPendingWrites" :
568+
@(snapshot.metadata.hasPendingWrites),
569+
@"isFromCache" :
570+
@(snapshot.metadata.isFromCache),
571+
}
572+
: [NSNull null],
573+
}];
574+
}];
558575
_listeners[handle] = listener;
559576
result(handle);
560577
} else if ([@"Query#getDocuments" isEqualToString:call.method]) {
@@ -577,7 +594,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
577594
}
578595
result(parseQuerySnapshot(snapshot));
579596
}];
580-
} else if ([@"Query#removeListener" isEqualToString:call.method]) {
597+
} else if ([@"removeListener" isEqualToString:call.method]) {
581598
NSNumber *handle = call.arguments[@"handle"];
582599
[[_listeners objectForKey:handle] remove];
583600
[_listeners removeObjectForKey:handle];

packages/cloud_firestore/lib/src/document_reference.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,20 @@ class DocumentReference {
116116

117117
/// Notifies of documents at this location
118118
// TODO(jackson): Reduce code duplication with [Query]
119-
Stream<DocumentSnapshot> snapshots() {
119+
Stream<DocumentSnapshot> snapshots({bool includeMetadataChanges = false}) {
120+
assert(includeMetadataChanges != null);
120121
Future<int> _handle;
121122
// It's fine to let the StreamController be garbage collected once all the
122123
// subscribers have cancelled; this analyzer warning is safe to ignore.
123124
StreamController<DocumentSnapshot> controller; // ignore: close_sinks
124125
controller = StreamController<DocumentSnapshot>.broadcast(
125126
onListen: () {
126127
_handle = Firestore.channel.invokeMethod<int>(
127-
'Query#addDocumentListener',
128+
'DocumentReference#addSnapshotListener',
128129
<String, dynamic>{
129130
'app': firestore.app.name,
130131
'path': path,
132+
'includeMetadataChanges': includeMetadataChanges,
131133
},
132134
).then<int>((dynamic result) => result);
133135
_handle.then((int handle) {
@@ -137,7 +139,7 @@ class DocumentReference {
137139
onCancel: () {
138140
_handle.then((int handle) async {
139141
await Firestore.channel.invokeMethod<void>(
140-
'Query#removeListener',
142+
'removeListener',
141143
<String, dynamic>{'handle': handle},
142144
);
143145
Firestore._documentObservers.remove(handle);

packages/cloud_firestore/lib/src/query.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class Query {
5050

5151
/// Notifies of query results at this location
5252
// TODO(jackson): Reduce code duplication with [DocumentReference]
53-
Stream<QuerySnapshot> snapshots() {
53+
Stream<QuerySnapshot> snapshots({bool includeMetadataChanges = false}) {
54+
assert(includeMetadataChanges != null);
5455
Future<int> _handle;
5556
// It's fine to let the StreamController be garbage collected once all the
5657
// subscribers have cancelled; this analyzer warning is safe to ignore.
@@ -64,6 +65,7 @@ class Query {
6465
'path': _path,
6566
'isCollectionGroup': _isCollectionGroup,
6667
'parameters': _parameters,
68+
'includeMetadataChanges': includeMetadataChanges,
6769
},
6870
).then<int>((dynamic result) => result);
6971
_handle.then((int handle) {
@@ -73,7 +75,7 @@ class Query {
7375
onCancel: () {
7476
_handle.then((int handle) async {
7577
await Firestore.channel.invokeMethod<void>(
76-
'Query#removeListener',
78+
'removeListener',
7779
<String, dynamic>{'handle': handle},
7880
);
7981
Firestore._queryObservers.remove(handle);

packages/cloud_firestore/lib/src/query_snapshot.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ class QuerySnapshot {
2525
data['documentChanges'][index],
2626
_firestore,
2727
);
28-
});
28+
}),
29+
metadata = SnapshotMetadata._(
30+
data['metadata']['hasPendingWrites'],
31+
data['metadata']['isFromCache'],
32+
);
2933

3034
/// Gets a list of all the documents included in this snapshot
3135
final List<DocumentSnapshot> documents;
@@ -34,5 +38,7 @@ class QuerySnapshot {
3438
/// is the first snapshot, all documents will be in the list as Added changes.
3539
final List<DocumentChange> documentChanges;
3640

41+
final SnapshotMetadata metadata;
42+
3743
final Firestore _firestore;
3844
}

packages/cloud_firestore/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Cloud Firestore, a cloud-hosted, noSQL database
33
live synchronization and offline support on Android and iOS.
44
author: Flutter Team <flutter-dev@googlegroups.com>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore
6-
version: 0.12.8
6+
version: 0.12.9
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)