Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"cloud_firestore","dependencies":["firebase_core"]},{"name":"firebase_core","dependencies":[]}]}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should not be checked in to version control

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no idea where this is coming from; I'll remove it from the PR, and add it to .gitignore

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' show hashValues, hashList;

import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart';

import 'package:collection/collection.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,11 @@ class DocumentReference {
/// If [merge] is true, the provided data will be merged into an
/// existing document instead of overwriting.
Future<void> setData(Map<String, dynamic> data, {bool merge = false}) {
return Firestore.channel.invokeMethod<void>(
'DocumentReference#setData',
<String, dynamic>{
'app': firestore.app.name,
'path': path,
'data': data,
'options': <String, bool>{'merge': merge},
},
return Firestore.platform.setDocumentReferenceData(
firestore.app.name,
path: path,
data: data,
options: <String, bool>{'merge': merge},
);
}

Expand All @@ -66,13 +63,10 @@ class DocumentReference {
///
/// If no document exists yet, the update will fail.
Future<void> updateData(Map<String, dynamic> data) {
return Firestore.channel.invokeMethod<void>(
'DocumentReference#updateData',
<String, dynamic>{
'app': firestore.app.name,
'path': path,
'data': data,
},
return Firestore.platform.updateDocumentReferenceData(
firestore.app.name,
path: path,
data: data,
);
}

Expand All @@ -81,14 +75,12 @@ class DocumentReference {
/// If no document exists, the read will return null.
Future<DocumentSnapshot> get({Source source = Source.serverAndCache}) async {
final Map<String, dynamic> data =
await Firestore.channel.invokeMapMethod<String, dynamic>(
'DocumentReference#get',
<String, dynamic>{
'app': firestore.app.name,
'path': path,
'source': _getSourceString(source),
},
await Firestore.platform.getDocumentReference(
firestore.app.name,
path: path,
source: _getSourceString(source),
);

return DocumentSnapshot._(
data['path'],
_asStringKeyedMap(data['data']),
Expand All @@ -100,9 +92,9 @@ class DocumentReference {

/// Deletes the document referred to by this [DocumentReference].
Future<void> delete() {
return Firestore.channel.invokeMethod<void>(
'DocumentReference#delete',
<String, dynamic>{'app': firestore.app.name, 'path': path},
return Firestore.platform.deleteDocumentReference(
firestore.app.name,
path: path,
);
}

Expand All @@ -118,34 +110,19 @@ class DocumentReference {
// TODO(jackson): Reduce code duplication with [Query]
Stream<DocumentSnapshot> snapshots({bool includeMetadataChanges = false}) {
assert(includeMetadataChanges != null);
Future<int> _handle;
// It's fine to let the StreamController be garbage collected once all the
// subscribers have cancelled; this analyzer warning is safe to ignore.
StreamController<DocumentSnapshot> controller; // ignore: close_sinks
controller = StreamController<DocumentSnapshot>.broadcast(
onListen: () {
_handle = Firestore.channel.invokeMethod<int>(
'DocumentReference#addSnapshotListener',
<String, dynamic>{
'app': firestore.app.name,
'path': path,
'includeMetadataChanges': includeMetadataChanges,
},
).then<int>((dynamic result) => result);
_handle.then((int handle) {
Firestore._documentObservers[handle] = controller;
});
},
onCancel: () {
_handle.then((int handle) async {
await Firestore.channel.invokeMethod<void>(
'removeListener',
<String, dynamic>{'handle': handle},
);
Firestore._documentObservers.remove(handle);
});
},
);
return controller.stream;

return Firestore.platform
.getDocumentReferenceSnapshots(
firestore.app.name,
path: path,
includeMetadataChanges: includeMetadataChanges,
)
.map((dynamic data) => DocumentSnapshot._(
data['path'],
_asStringKeyedMap(data['data']),
SnapshotMetadata._(data['metadata']['hasPendingWrites'],
data['metadata']['isFromCache']),
firestore,
));
}
}
82 changes: 25 additions & 57 deletions packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,6 @@ part of cloud_firestore;
class Firestore {
Firestore({FirebaseApp app}) : app = app ?? FirebaseApp.instance {
if (_initialized) return;
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be removed now.

channel.setMethodCallHandler((MethodCall call) async {
if (call.method == 'QuerySnapshot') {
final QuerySnapshot snapshot = QuerySnapshot._(call.arguments, this);
_queryObservers[call.arguments['handle']].add(snapshot);
} else if (call.method == 'DocumentSnapshot') {
final DocumentSnapshot snapshot = DocumentSnapshot._(
call.arguments['path'],
_asStringKeyedMap(call.arguments['data']),
SnapshotMetadata._(call.arguments['metadata']['hasPendingWrites'],
call.arguments['metadata']['isFromCache']),
this,
);
_documentObservers[call.arguments['handle']].add(snapshot);
} else if (call.method == 'DoTransaction') {
final int transactionId = call.arguments['transactionId'];
final Transaction transaction = Transaction(transactionId, this);
final dynamic result =
await _transactionHandlers[transactionId](transaction);
await transaction._finish();
return result;
}
});
_initialized = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be removed now.

}

Expand All @@ -46,20 +24,7 @@ class Firestore {
static bool _initialized = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be removed now.


@visibleForTesting
static const MethodChannel channel = MethodChannel(
'plugins.flutter.io/cloud_firestore',
StandardMethodCodec(FirestoreMessageCodec()),
);

static final Map<int, StreamController<QuerySnapshot>> _queryObservers =
<int, StreamController<QuerySnapshot>>{};

static final Map<int, StreamController<DocumentSnapshot>> _documentObservers =
<int, StreamController<DocumentSnapshot>>{};

static final Map<int, TransactionHandler> _transactionHandlers =
<int, TransactionHandler>{};
static int _transactionHandlerId = 0;
static CloudFirestorePlatform platform = CloudFirestorePlatform.instance;

@override
bool operator ==(dynamic o) => o is Firestore && o.app == app;
Expand Down Expand Up @@ -123,39 +88,42 @@ class Firestore {
{Duration timeout = const Duration(seconds: 5)}) async {
assert(timeout.inMilliseconds > 0,
'Transaction timeout must be more than 0 milliseconds');
final int transactionId = _transactionHandlerId++;
_transactionHandlers[transactionId] = transactionHandler;
final Map<String, dynamic> result = await channel
.invokeMapMethod<String, dynamic>(
'Firestore#runTransaction', <String, dynamic>{
'app': app.name,
'transactionId': transactionId,
'transactionTimeout': timeout.inMilliseconds
});

// Wrap the incoming [TransactionHandler] into something that can be passed
// to the Platform implementation.
final PlatformTransactionHandler handler = (int transactionId) async {
Transaction transaction = Transaction(transactionId, this);
final dynamic result = await transactionHandler(transaction);
await transaction._finish();
return result;
};

final Map<String, dynamic> result = await platform.runTransaction(
app.name,
transactionHandler: handler,
transactionTimeout: timeout.inMilliseconds,
);
return result ?? <String, dynamic>{};
}

@deprecated
Future<void> enablePersistence(bool enable) async {
assert(enable != null);
await channel
.invokeMethod<void>('Firestore#enablePersistence', <String, dynamic>{
'app': app.name,
'enable': enable,
});
await platform.enablePersistence(
app.name,
enable: enable,
);
}

Future<void> settings(
{bool persistenceEnabled,
String host,
bool sslEnabled,
int cacheSizeBytes}) async {
await channel.invokeMethod<void>('Firestore#settings', <String, dynamic>{
'app': app.name,
'persistenceEnabled': persistenceEnabled,
'host': host,
'sslEnabled': sslEnabled,
'cacheSizeBytes': cacheSizeBytes,
});
await platform.settings(app.name,
persistenceEnabled: persistenceEnabled,
host: host,
sslEnabled: sslEnabled,
cacheSizeBytes: cacheSizeBytes);
Copy link
Contributor

Choose a reason for hiding this comment

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

readability nit: my preference would be a trailing comma and give each argument its own line here, assuming the formatter agrees.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Absolutely, I was trying to convince dartfmt to do it automatically for me (that's why I left the trailing comma at the end), but it didn't take my hint. I'll format all of these manually :'(

}
}
56 changes: 16 additions & 40 deletions packages/cloud_firestore/cloud_firestore/lib/src/query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,53 +52,29 @@ class Query {
// TODO(jackson): Reduce code duplication with [DocumentReference]
Stream<QuerySnapshot> snapshots({bool includeMetadataChanges = false}) {
assert(includeMetadataChanges != null);
Future<int> _handle;
// It's fine to let the StreamController be garbage collected once all the
// subscribers have cancelled; this analyzer warning is safe to ignore.
StreamController<QuerySnapshot> controller; // ignore: close_sinks
controller = StreamController<QuerySnapshot>.broadcast(
onListen: () {
_handle = Firestore.channel.invokeMethod<int>(
'Query#addSnapshotListener',
<String, dynamic>{
'app': firestore.app.name,
'path': _path,
'isCollectionGroup': _isCollectionGroup,
'parameters': _parameters,
'includeMetadataChanges': includeMetadataChanges,
},
).then<int>((dynamic result) => result);
_handle.then((int handle) {
Firestore._queryObservers[handle] = controller;
});
},
onCancel: () {
_handle.then((int handle) async {
await Firestore.channel.invokeMethod<void>(
'removeListener',
<String, dynamic>{'handle': handle},
);
Firestore._queryObservers.remove(handle);
});
},
);
return controller.stream;

return Firestore.platform
.getQuerySnapshots(
firestore.app.name,
path: _path,
isCollectionGroup: _isCollectionGroup,
parameters: _parameters,
includeMetadataChanges: includeMetadataChanges,
)
.map((dynamic data) => QuerySnapshot._(data, firestore));
}

/// Fetch the documents for this query
Future<QuerySnapshot> getDocuments(
{Source source = Source.serverAndCache}) async {
assert(source != null);
final Map<dynamic, dynamic> data =
await Firestore.channel.invokeMapMethod<String, dynamic>(
'Query#getDocuments',
<String, dynamic>{
'app': firestore.app.name,
'path': _path,
'isCollectionGroup': _isCollectionGroup,
'parameters': _parameters,
'source': _getSourceString(source),
},
await Firestore.platform.getQueryDocuments(
firestore.app.name,
path: _path,
isCollectionGroup: _isCollectionGroup,
parameters: _parameters,
source: _getSourceString(source),
);
return QuerySnapshot._(data, firestore);
}
Expand Down
47 changes: 21 additions & 26 deletions packages/cloud_firestore/cloud_firestore/lib/src/transaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ class Transaction {
}

Future<DocumentSnapshot> _get(DocumentReference documentReference) async {
final Map<String, dynamic> result = await Firestore.channel
.invokeMapMethod<String, dynamic>('Transaction#get', <String, dynamic>{
'app': _firestore.app.name,
'transactionId': _transactionId,
'path': documentReference.path,
});
final Map<String, dynamic> result = await Firestore.platform.getTransaction(
_firestore.app.name,
transactionId: _transactionId,
path: documentReference.path,
);

if (result != null) {
return DocumentSnapshot._(
documentReference.path,
Expand All @@ -52,12 +52,11 @@ class Transaction {
}

Future<void> _delete(DocumentReference documentReference) async {
return Firestore.channel
.invokeMethod<void>('Transaction#delete', <String, dynamic>{
'app': _firestore.app.name,
'transactionId': _transactionId,
'path': documentReference.path,
});
return Firestore.platform.deleteTransaction(
_firestore.app.name,
transactionId: _transactionId,
path: documentReference.path,
);
}

/// Updates fields in the document referred to by [documentReference].
Expand All @@ -74,13 +73,10 @@ class Transaction {

Future<void> _update(
DocumentReference documentReference, Map<String, dynamic> data) async {
return Firestore.channel
.invokeMethod<void>('Transaction#update', <String, dynamic>{
'app': _firestore.app.name,
'transactionId': _transactionId,
'path': documentReference.path,
'data': data,
});
return Firestore.platform.updateTransaction(_firestore.app.name,
transactionId: _transactionId,
path: documentReference.path,
data: data);
}

/// Writes to the document referred to by the provided [DocumentReference].
Expand All @@ -98,12 +94,11 @@ class Transaction {

Future<void> _set(
DocumentReference documentReference, Map<String, dynamic> data) async {
return Firestore.channel
.invokeMethod<void>('Transaction#set', <String, dynamic>{
'app': _firestore.app.name,
'transactionId': _transactionId,
'path': documentReference.path,
'data': data,
});
return Firestore.platform.setTransaction(
_firestore.app.name,
transactionId: _transactionId,
path: documentReference.path,
data: data,
);
}
}
Loading