Skip to content

Commit

Permalink
[cloud_firestore] Migrate to platform interface (firebase#1945)
Browse files Browse the repository at this point in the history
Migrate the cloud_firestore core plugin to use the platform_interface package. All the "method channel" implementation now lives in the platform_interface package.

The plugin is now ready to support federated implementations.

Co-authored-by: David Iglesias <[email protected]>
Co-authored-by: Collin Jackson <[email protected]>
  • Loading branch information
3 people authored Feb 6, 2020
1 parent 29eb495 commit 1b45082
Show file tree
Hide file tree
Showing 31 changed files with 414 additions and 2,553 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,3 @@ build/
.project
.classpath
.settings
.flutter-plugins-dependencies

2 changes: 2 additions & 0 deletions packages/cloud_firestore/cloud_firestore/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
ios/Classes/UserAgent.h
.flutter-plugins-dependencies
generated_plugin_registrant.dart
4 changes: 4 additions & 0 deletions packages/cloud_firestore/cloud_firestore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.13.1

* Migrate to `cloud_firestore_platform_interface`.

## 0.13.0+2

* Fixed `persistenceEnabled`, `sslEnabled`, and `timestampsInSnapshotsEnabled` on iOS.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
# This is a temporary file to allow us to land a new set of linter rules in a
# series of manageable patches instead of one gigantic PR. It disables some of
# the new lints that are already failing on this plugin, for this plugin. It
# should be deleted and the failing lints addressed as soon as possible.

include: ../../../analysis_options.yaml

analyzer:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableJetifier=true
android.enableR8=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#

Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => '[email protected]' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework'
end
75 changes: 74 additions & 1 deletion packages/cloud_firestore/cloud_firestore/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ class MessageList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('messages').snapshots(),
stream: firestore
.collection("messages")
.orderBy("created_at", descending: true)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int messageCount = snapshot.data.documents.length;
Expand All @@ -43,6 +46,10 @@ class MessageList extends StatelessWidget {
final DocumentSnapshot document = snapshot.data.documents[index];
final dynamic message = document['message'];
return ListTile(
trailing: IconButton(
onPressed: () => document.reference.delete(),
icon: Icon(Icons.delete),
),
title: Text(
message != null ? message.toString() : '<No message retrieved>',
),
Expand All @@ -69,11 +76,77 @@ class MyHomePage extends StatelessWidget {
});
}

Future<void> _runTransaction() async {
firestore.runTransaction((Transaction transaction) async {
final allDocs = await firestore.collection("messages").getDocuments();
final toBeRetrieved =
allDocs.documents.sublist(allDocs.documents.length ~/ 2);
final toBeDeleted =
allDocs.documents.sublist(0, allDocs.documents.length ~/ 2);
await Future.forEach(toBeDeleted, (DocumentSnapshot snapshot) async {
await transaction.delete(snapshot.reference);
});

await Future.forEach(toBeRetrieved, (DocumentSnapshot snapshot) async {
await transaction.update(snapshot.reference, {
"message": "Updated from Transaction",
"created_at": FieldValue.serverTimestamp()
});
});
});

await Future.forEach(List.generate(2, (index) => index), (item) async {
await firestore.runTransaction((Transaction transaction) async {
await Future.forEach(List.generate(10, (index) => index), (item) async {
await transaction.set(firestore.collection("messages").document(), {
"message": "Created from Transaction $item",
"created_at": FieldValue.serverTimestamp()
});
});
});
});
}

Future<void> _runBatchWrite() async {
final batchWrite = firestore.batch();
final querySnapshot = await firestore
.collection("messages")
.orderBy("created_at")
.limit(12)
.getDocuments();
querySnapshot.documents
.sublist(0, querySnapshot.documents.length - 3)
.forEach((DocumentSnapshot doc) {
batchWrite.updateData(doc.reference, {
"message": "Batched message",
"created_at": FieldValue.serverTimestamp()
});
});
batchWrite.setData(firestore.collection("messages").document(), {
"message": "Batched message created",
"created_at": FieldValue.serverTimestamp()
});
batchWrite.delete(
querySnapshot.documents[querySnapshot.documents.length - 2].reference);
batchWrite.delete(querySnapshot.documents.last.reference);
await batchWrite.commit();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firestore Example'),
actions: <Widget>[
FlatButton(
onPressed: _runTransaction,
child: Text("Run Transaction"),
),
FlatButton(
onPressed: _runBatchWrite,
child: Text("Batch Write"),
)
],
),
body: MessageList(firestore: firestore),
floatingActionButton: FloatingActionButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void main() {
Firestore firestore;
Firestore firestoreWithSettings;

setUp(() async {
setUpAll(() async {
final FirebaseOptions firebaseOptions = const FirebaseOptions(
googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd',
gcmSenderID: '79601577497',
Expand Down
21 changes: 7 additions & 14 deletions packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,25 @@
library cloud_firestore;

import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' show hashValues, hashList;
import 'dart:ui' show hashList;

import 'package:collection/collection.dart';
import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'
as platform;
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';

import 'src/utils/auto_id_generator.dart';
export 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'
show FieldPath, Blob, GeoPoint, Timestamp, Source, DocumentChangeType;

part 'src/blob.dart';
part 'src/collection_reference.dart';
part 'src/document_change.dart';
part 'src/utils/platform_utils.dart';
part 'src/document_reference.dart';
part 'src/document_snapshot.dart';
part 'src/field_path.dart';
part 'src/field_value.dart';
part 'src/firestore.dart';
part 'src/firestore_message_codec.dart';
part 'src/geo_point.dart';
part 'src/query.dart';
part 'src/query_snapshot.dart';
part 'src/utils/codec_utility.dart';
part 'src/snapshot_metadata.dart';
part 'src/timestamp.dart';
part 'src/transaction.dart';
part 'src/write_batch.dart';
part 'src/source.dart';
19 changes: 0 additions & 19 deletions packages/cloud_firestore/cloud_firestore/lib/src/blob.dart

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ part of cloud_firestore;
/// document references, and querying for documents (using the methods
/// inherited from [Query]).
class CollectionReference extends Query {
CollectionReference._(Firestore firestore, List<String> pathComponents)
: super._(firestore: firestore, pathComponents: pathComponents);
final platform.CollectionReferencePlatform _delegate;

CollectionReference._(this._delegate, Firestore firestore)
: super._(_delegate, firestore);

/// ID of the referenced collection.
String get id => _pathComponents.isEmpty ? null : _pathComponents.last;
Expand All @@ -21,10 +23,7 @@ class CollectionReference extends Query {
if (_pathComponents.length < 2) {
return null;
}
return DocumentReference._(
firestore,
(List<String>.from(_pathComponents)..removeLast()),
);
return DocumentReference._(_delegate.parent(), firestore);
}

/// A string containing the slash-separated path to this CollectionReference
Expand All @@ -37,16 +36,8 @@ class CollectionReference extends Query {
///
/// The unique key generated is prefixed with a client-generated timestamp
/// so that the resulting list will be chronologically-sorted.
DocumentReference document([String path]) {
List<String> childPath;
if (path == null) {
final String key = AutoIdGenerator.autoId();
childPath = List<String>.from(_pathComponents)..add(key);
} else {
childPath = List<String>.from(_pathComponents)..addAll(path.split(('/')));
}
return DocumentReference._(firestore, childPath);
}
DocumentReference document([String path]) =>
DocumentReference._(_delegate.document(path), firestore);

/// Returns a `DocumentReference` with an auto-generated ID, after
/// populating it with provided [data].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,36 @@

part of cloud_firestore;

/// An enumeration of document change types.
enum DocumentChangeType {
/// Indicates a new document was added to the set of documents matching the
/// query.
added,

/// Indicates a document within the query was modified.
modified,

/// Indicates a document within the query was removed (either deleted or no
/// longer matches the query.
removed,
}

/// A DocumentChange represents a change to the documents matching a query.
///
/// It contains the document affected and the type of change that occurred
/// (added, modified, or removed).
class DocumentChange {
DocumentChange._(Map<dynamic, dynamic> data, Firestore firestore)
: oldIndex = data['oldIndex'],
newIndex = data['newIndex'],
document = DocumentSnapshot._(
data['path'],
_asStringKeyedMap(data['document']),
SnapshotMetadata._(data["metadata"]["hasPendingWrites"],
data["metadata"]["isFromCache"]),
firestore,
),
type = DocumentChangeType.values.firstWhere((DocumentChangeType type) {
return type.toString() == data['type'];
});
final platform.DocumentChangePlatform _delegate;
final Firestore _firestore;

DocumentChange._(this._delegate, this._firestore) {
platform.DocumentChangePlatform.verifyExtends(_delegate);
}

/// The type of change that occurred (added, modified, or removed).
final DocumentChangeType type;
platform.DocumentChangeType get type => _delegate.type;

/// The index of the changed document in the result set immediately prior to
/// this [DocumentChange] (i.e. supposing that all prior DocumentChange objects
/// have been applied).
///
/// -1 for [DocumentChangeType.added] events.
final int oldIndex;
int get oldIndex => _delegate.oldIndex;

/// The index of the changed document in the result set immediately after this
/// DocumentChange (i.e. supposing that all prior [DocumentChange] objects
/// and the current [DocumentChange] object have been applied).
///
/// -1 for [DocumentChangeType.removed] events.
final int newIndex;
int get newIndex => _delegate.newIndex;

/// The document affected by this change.
final DocumentSnapshot document;
DocumentSnapshot get document =>
DocumentSnapshot._(_delegate.document, _firestore);
}
Loading

0 comments on commit 1b45082

Please sign in to comment.