From 805cb06df665cf63fbf4818d57998937c31993f5 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 04:23:36 -0700 Subject: [PATCH 1/9] Multiple app support for cloud_firestore --- packages/cloud_firestore/CHANGELOG.md | 4 + .../cloud_firestore/android/gradle.properties | 1 - .../cloudfirestore/CloudFirestorePlugin.java | 28 +++- .../cloud_firestore/example/lib/main.dart | 35 ++++- packages/cloud_firestore/example/pubspec.yaml | 2 + .../ios/Classes/CloudFirestorePlugin.h | 2 +- .../ios/Classes/CloudFirestorePlugin.m | 125 +++++++++--------- .../ios/cloud_firestore.podspec | 1 + .../cloud_firestore/lib/cloud_firestore.dart | 1 + .../lib/src/collection_reference.dart | 6 +- .../lib/src/document_reference.dart | 31 +++-- .../cloud_firestore/lib/src/firestore.dart | 30 +++-- .../lib/src/firestore_message_codec.dart | 10 +- packages/cloud_firestore/lib/src/query.dart | 17 ++- .../cloud_firestore/lib/src/transaction.dart | 8 +- .../cloud_firestore/lib/src/write_batch.dart | 14 +- packages/cloud_firestore/pubspec.yaml | 1 + .../test/cloud_firestore_test.dart | 115 ++++++++++++---- 18 files changed, 294 insertions(+), 137 deletions(-) delete mode 100755 packages/cloud_firestore/android/gradle.properties diff --git a/packages/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/CHANGELOG.md index c64355cbfca7..0eb705dbb0e5 100644 --- a/packages/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +* Support for multiple Firebase apps + ## 0.4.0 * **Breaking change**. Hide Firestore codec class from public API. diff --git a/packages/cloud_firestore/android/gradle.properties b/packages/cloud_firestore/android/gradle.properties deleted file mode 100755 index 8bd86f680510..000000000000 --- a/packages/cloud_firestore/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M diff --git a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java index 491351ee914a..2aef904affc2 100644 --- a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java +++ b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java @@ -13,6 +13,7 @@ import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; import com.google.android.gms.tasks.Tasks; +import com.google.firebase.FirebaseApp; import com.google.firebase.firestore.CollectionReference; import com.google.firebase.firestore.DocumentChange; import com.google.firebase.firestore.DocumentReference; @@ -72,14 +73,19 @@ private CloudFirestorePlugin(MethodChannel channel) { this.channel = channel; } + private FirebaseFirestore getFirestore(Map arguments) { + String appName = (String) arguments.get("app"); + return FirebaseFirestore.getInstance(FirebaseApp.getInstance(appName)); + } + private CollectionReference getCollectionReference(Map arguments) { String path = (String) arguments.get("path"); - return FirebaseFirestore.getInstance().collection(path); + return getFirestore(arguments).collection(path); } private DocumentReference getDocumentReference(Map arguments) { String path = (String) arguments.get("path"); - return FirebaseFirestore.getInstance().document(path); + return getFirestore(arguments).document(path); } private Map parseQuerySnapshot(QuerySnapshot querySnapshot) { @@ -248,7 +254,7 @@ public void onMethodCall(MethodCall call, final Result result) { final Task> transactionTCSTask = transactionTCS.getTask(); final Map arguments = call.arguments(); - FirebaseFirestore.getInstance() + getFirestore(arguments) .runTransaction( new Transaction.Function() { @Nullable @@ -379,7 +385,8 @@ protected Void doInBackground(Void... voids) { case "WriteBatch#create": { int handle = nextBatchHandle++; - WriteBatch batch = FirebaseFirestore.getInstance().batch(); + final Map arguments = call.arguments(); + WriteBatch batch = getFirestore(arguments).batch(); batches.put(handle, batch); result.success(handle); break; @@ -573,6 +580,9 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) { writeDouble(stream, ((GeoPoint) value).getLongitude()); } else if (value instanceof DocumentReference) { stream.write(DOCUMENT_REFERENCE); + // TODO(jackson): Null checking + writeBytes( + stream, ((DocumentReference) value).getFirestore().getApp().getName().getBytes(UTF8)); writeBytes(stream, ((DocumentReference) value).getPath().getBytes(UTF8)); } else { super.writeValue(stream, value); @@ -588,9 +598,13 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) { readAlignment(buffer, 8); return new GeoPoint(buffer.getDouble(), buffer.getDouble()); case DOCUMENT_REFERENCE: - final byte[] bytes = readBytes(buffer); - final String path = new String(bytes, UTF8); - return FirebaseFirestore.getInstance().document(path); + final byte[] appNameBytes = readBytes(buffer); + String appName = new String(appNameBytes, UTF8); + final FirebaseFirestore firestore = + FirebaseFirestore.getInstance(FirebaseApp.getInstance(appName)); + final byte[] pathBytes = readBytes(buffer); + final String path = new String(pathBytes, UTF8); + return firestore.document(path); default: return super.readValueOfType(type, buffer); } diff --git a/packages/cloud_firestore/example/lib/main.dart b/packages/cloud_firestore/example/lib/main.dart index ed4d01a05cd5..c7025e9d0a0a 100755 --- a/packages/cloud_firestore/example/lib/main.dart +++ b/packages/cloud_firestore/example/lib/main.dart @@ -5,17 +5,35 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; -void main() { - runApp(new MaterialApp(title: 'Firestore Example', home: new MyHomePage())); +Future main() async { + final FirebaseOptions options = const FirebaseOptions( + googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd', + gcmSenderID: '79601577497', + apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU', + projectID: 'flutter-firestore', + ); + FirebaseApp.configure( + name: 'test', + options: options, + ); + final Firestore firestore = new Firestore(app: new FirebaseApp.named('test')); + + runApp(new MaterialApp( + title: 'Firestore Example', home: new MyHomePage(firestore: firestore))); } class MessageList extends StatelessWidget { + MessageList({this.firestore}); + + final Firestore firestore; + @override Widget build(BuildContext context) { return new StreamBuilder( - stream: Firestore.instance.collection('messages').snapshots, + stream: firestore.collection('messages').snapshots, builder: (BuildContext context, AsyncSnapshot snapshot) { if (!snapshot.hasData) return const Text('Loading...'); final int messageCount = snapshot.data.documents.length; @@ -35,10 +53,15 @@ class MessageList extends StatelessWidget { } class MyHomePage extends StatelessWidget { - CollectionReference get messages => Firestore.instance.collection('messages'); + MyHomePage({this.firestore}); + final Firestore firestore; + CollectionReference get messages => firestore.collection('messages'); Future _addMessage() async { - messages.document().setData({'message': 'Hello world!'}); + final DocumentReference document = messages.document(); + document.setData({ + 'message': 'Hello world!', + }); } @override @@ -47,7 +70,7 @@ class MyHomePage extends StatelessWidget { appBar: new AppBar( title: const Text('Firestore Example'), ), - body: new MessageList(), + body: new MessageList(firestore: firestore), floatingActionButton: new FloatingActionButton( onPressed: _addMessage, tooltip: 'Increment', diff --git a/packages/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/example/pubspec.yaml index dc933215c2df..95444630d83a 100755 --- a/packages/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/example/pubspec.yaml @@ -6,6 +6,8 @@ dependencies: sdk: flutter cloud_firestore: path: ../ + firebase_core: # "^0.1.2" + path: ../../firebase_core flutter: uses-material-design: true diff --git a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h index 156faca7c01e..3a9035a10fd9 100644 --- a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h +++ b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h @@ -4,5 +4,5 @@ #import -@interface FLTCloudFirestorePlugin : NSObject +@interface FLTCloudFirestorePlugin : NSObject @end diff --git a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m index 863357f83f7e..6019647db5f3 100644 --- a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m +++ b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m @@ -18,8 +18,17 @@ - (FlutterError *)flutterError { } @end +FIRFirestore *getFirestore(NSDictionary *arguments) { + FIRApp *app = [FIRApp appNamed:arguments[@"app"]]; + return [FIRFirestore firestoreForApp:app]; +} + +FIRDocumentReference *getDocumentReference(NSDictionary *arguments) { + return [getFirestore(arguments) documentWithPath:arguments[@"path"]]; +} + FIRQuery *getQuery(NSDictionary *arguments) { - FIRQuery *query = [[FIRFirestore firestore] collectionWithPath:arguments[@"path"]]; + FIRQuery *query = [getFirestore(arguments) collectionWithPath:arguments[@"path"]]; NSDictionary *parameters = arguments[@"parameters"]; NSArray *whereConditions = parameters[@"where"]; for (id item in whereConditions) { @@ -139,9 +148,10 @@ - (void)writeValue:(id)value { [self writeBytes:(UInt8 *)&latitude length:8]; [self writeBytes:(UInt8 *)&longitude length:8]; } else if ([value isKindOfClass:[FIRDocumentReference class]]) { - FIRDocumentReference *documentReference = value; - NSString *documentPath = [documentReference path]; + FIRDocumentReference *document = value; + NSString *documentPath = [document path]; [self writeByte:DOCUMENT_REFERENCE]; + [self writeUTF8:document.firestore.app.name]; [self writeUTF8:documentPath]; } else { [super writeValue:value]; @@ -171,8 +181,10 @@ - (id)readValueOfType:(UInt8)type { return [[FIRGeoPoint alloc] initWithLatitude:latitude longitude:longitude]; } case DOCUMENT_REFERENCE: { + NSString *appName = [self readUTF8]; + FIRFirestore *firestore = [FIRFirestore firestoreForApp:[FIRApp appNamed:appName]]; NSString *documentPath = [self readUTF8]; - return [[FIRFirestore firestore] documentWithPath:documentPath]; + return [firestore documentWithPath:documentPath]; } default: return [super readValueOfType:type]; @@ -240,27 +252,28 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result(error.flutterError); }; if ([@"Firestore#runTransaction" isEqualToString:call.method]) { - [[FIRFirestore firestore] runTransactionWithBlock:^id(FIRTransaction *transaction, - NSError **pError) { - NSNumber *transactionId = call.arguments[@"transactionId"]; - NSNumber *transactionTimeout = call.arguments[@"transactionTimeout"]; + [getFirestore(call.arguments) + runTransactionWithBlock:^id(FIRTransaction *transaction, NSError **pError) { + NSNumber *transactionId = call.arguments[@"transactionId"]; + NSNumber *transactionTimeout = call.arguments[@"transactionTimeout"]; - transactions[transactionId] = transaction; + transactions[transactionId] = transaction; - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - [self.channel invokeMethod:@"DoTransaction" - arguments:call.arguments - result:^(id doTransactionResult) { - transactionResults[transactionId] = doTransactionResult; - dispatch_semaphore_signal(semaphore); - }]; + [self.channel invokeMethod:@"DoTransaction" + arguments:call.arguments + result:^(id doTransactionResult) { + transactionResults[transactionId] = doTransactionResult; + dispatch_semaphore_signal(semaphore); + }]; - dispatch_semaphore_wait( - semaphore, dispatch_time(DISPATCH_TIME_NOW, [transactionTimeout integerValue] * 1000000)); + dispatch_semaphore_wait( + semaphore, + dispatch_time(DISPATCH_TIME_NOW, [transactionTimeout integerValue] * 1000000)); - return transactionResults[transactionId]; - } + return transactionResults[transactionId]; + } completion:^(id transactionResult, NSError *error) { if (error != nil) { result([FlutterError errorWithCode:[NSString stringWithFormat:@"%ld", error.code] @@ -272,12 +285,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([@"Transaction#get" isEqualToString:call.method]) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSNumber *transactionId = call.arguments[@"transactionId"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *documentReference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRTransaction *transaction = transactions[transactionId]; NSError *error = [[NSError alloc] init]; - FIRDocumentSnapshot *snapshot = [transaction getDocument:documentReference error:&error]; + FIRDocumentSnapshot *snapshot = [transaction getDocument:document error:&error]; if (error != nil) { result([FlutterError errorWithCode:[NSString stringWithFormat:@"%tu", [error code]] @@ -297,58 +309,51 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([@"Transaction#update" isEqualToString:call.method]) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSNumber *transactionId = call.arguments[@"transactionId"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *documentReference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRTransaction *transaction = transactions[transactionId]; - [transaction updateData:call.arguments[@"data"] forDocument:documentReference]; + [transaction updateData:call.arguments[@"data"] forDocument:document]; result(nil); }); } else if ([@"Transaction#set" isEqualToString:call.method]) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSNumber *transactionId = call.arguments[@"transactionId"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *documentReference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRTransaction *transaction = transactions[transactionId]; - [transaction setData:call.arguments[@"data"] forDocument:documentReference]; + [transaction setData:call.arguments[@"data"] forDocument:document]; result(nil); }); } else if ([@"Transaction#delete" isEqualToString:call.method]) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSNumber *transactionId = call.arguments[@"transactionId"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *documentReference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRTransaction *transaction = transactions[transactionId]; - [transaction deleteDocument:documentReference]; + [transaction deleteDocument:document]; result(nil); }); } else if ([@"DocumentReference#setData" isEqualToString:call.method]) { - NSString *path = call.arguments[@"path"]; NSDictionary *options = call.arguments[@"options"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); if (![options isEqual:[NSNull null]] && [options[@"merge"] isEqual:[NSNumber numberWithBool:YES]]) { - [reference setData:call.arguments[@"data"] - options:[FIRSetOptions merge] - completion:defaultCompletionBlock]; + [document setData:call.arguments[@"data"] + options:[FIRSetOptions merge] + completion:defaultCompletionBlock]; } else { - [reference setData:call.arguments[@"data"] completion:defaultCompletionBlock]; + [document setData:call.arguments[@"data"] completion:defaultCompletionBlock]; } } else if ([@"DocumentReference#updateData" isEqualToString:call.method]) { - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; - [reference updateData:call.arguments[@"data"] completion:defaultCompletionBlock]; + FIRDocumentReference *document = getDocumentReference(call.arguments); + [document updateData:call.arguments[@"data"] completion:defaultCompletionBlock]; } else if ([@"DocumentReference#delete" isEqualToString:call.method]) { - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; - [reference deleteDocumentWithCompletion:defaultCompletionBlock]; + FIRDocumentReference *document = getDocumentReference(call.arguments); + [document deleteDocumentWithCompletion:defaultCompletionBlock]; } else if ([@"DocumentReference#get" isEqualToString:call.method]) { - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; - [reference getDocumentWithCompletion:^(FIRDocumentSnapshot *_Nullable snapshot, - NSError *_Nullable error) { + FIRDocumentReference *document = getDocumentReference(call.arguments); + [document getDocumentWithCompletion:^(FIRDocumentSnapshot *_Nullable snapshot, + NSError *_Nullable error) { if (error) { result(error.flutterError); } else { @@ -379,10 +384,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result(handle); } else if ([@"Query#addDocumentListener" isEqualToString:call.method]) { __block NSNumber *handle = [NSNumber numberWithInt:_nextListenerHandle++]; - FIRDocumentReference *reference = - [[FIRFirestore firestore] documentWithPath:call.arguments[@"path"]]; + FIRDocumentReference *document = getDocumentReference(call.arguments); id listener = - [reference addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) { + [document addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) { if (error) result(error.flutterError); [self.channel invokeMethod:@"DocumentSnapshot" arguments:@{ @@ -414,35 +418,32 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result(nil); } else if ([@"WriteBatch#create" isEqualToString:call.method]) { __block NSNumber *handle = [NSNumber numberWithInt:_nextBatchHandle++]; - FIRWriteBatch *batch = [[FIRFirestore firestore] batch]; + FIRWriteBatch *batch = [getFirestore(call.arguments) batch]; _batches[handle] = batch; result(handle); } else if ([@"WriteBatch#setData" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; - NSString *path = call.arguments[@"path"]; NSDictionary *options = call.arguments[@"options"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRWriteBatch *batch = [_batches objectForKey:handle]; if (![options isEqual:[NSNull null]] && [options[@"merge"] isEqual:[NSNumber numberWithBool:YES]]) { - [batch setData:call.arguments[@"data"] forDocument:reference options:[FIRSetOptions merge]]; + [batch setData:call.arguments[@"data"] forDocument:document options:[FIRSetOptions merge]]; } else { - [batch setData:call.arguments[@"data"] forDocument:reference]; + [batch setData:call.arguments[@"data"] forDocument:document]; } result(nil); } else if ([@"WriteBatch#updateData" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRWriteBatch *batch = [_batches objectForKey:handle]; - [batch updateData:call.arguments[@"data"] forDocument:reference]; + [batch updateData:call.arguments[@"data"] forDocument:document]; result(nil); } else if ([@"WriteBatch#delete" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; - NSString *path = call.arguments[@"path"]; - FIRDocumentReference *reference = [[FIRFirestore firestore] documentWithPath:path]; + FIRDocumentReference *document = getDocumentReference(call.arguments); FIRWriteBatch *batch = [_batches objectForKey:handle]; - [batch deleteDocument:reference]; + [batch deleteDocument:document]; result(nil); } else if ([@"WriteBatch#commit" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; diff --git a/packages/cloud_firestore/ios/cloud_firestore.podspec b/packages/cloud_firestore/ios/cloud_firestore.podspec index a1f806f7cd61..13e247093549 100755 --- a/packages/cloud_firestore/ios/cloud_firestore.podspec +++ b/packages/cloud_firestore/ios/cloud_firestore.podspec @@ -20,6 +20,7 @@ Firestore plugin for Flutter. s.dependency 'Firebase/Core' s.dependency 'Firebase/Auth' s.dependency 'Firebase/Firestore' + s.dependency 'firebase_core' s.pod_target_xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/**', 'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup' diff --git a/packages/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/lib/cloud_firestore.dart index 161244f52486..a2c456c69dbf 100755 --- a/packages/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/lib/cloud_firestore.dart @@ -8,6 +8,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ui' show hashValues, hashList; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:meta/meta.dart'; diff --git a/packages/cloud_firestore/lib/src/collection_reference.dart b/packages/cloud_firestore/lib/src/collection_reference.dart index 2c640e2b99e6..f71e67fb19ce 100644 --- a/packages/cloud_firestore/lib/src/collection_reference.dart +++ b/packages/cloud_firestore/lib/src/collection_reference.dart @@ -19,7 +19,9 @@ class CollectionReference extends Query { return null; } return new CollectionReference._( - _firestore, (new List.from(_pathComponents)..removeLast())); + firestore, + (new List.from(_pathComponents)..removeLast()), + ); } /// Returns a `DocumentReference` with the provided path. @@ -37,7 +39,7 @@ class CollectionReference extends Query { childPath = new List.from(_pathComponents) ..addAll(path.split(('/'))); } - return new DocumentReference._(_firestore, childPath); + return new DocumentReference._(firestore, childPath); } /// Returns a `DocumentReference` with an auto-generated ID, after diff --git a/packages/cloud_firestore/lib/src/document_reference.dart b/packages/cloud_firestore/lib/src/document_reference.dart index 7884a7070a40..decbac58c626 100644 --- a/packages/cloud_firestore/lib/src/document_reference.dart +++ b/packages/cloud_firestore/lib/src/document_reference.dart @@ -11,17 +11,18 @@ part of cloud_firestore; /// A [DocumentReference] can also be used to create a [CollectionReference] /// to a subcollection. class DocumentReference { - DocumentReference._(Firestore firestore, List pathComponents) - : _firestore = firestore, - _pathComponents = pathComponents, + DocumentReference._(this.firestore, List pathComponents) + : _pathComponents = pathComponents, assert(firestore != null); - final Firestore _firestore; + /// The Firestore instance associated with this document reference + final Firestore firestore; + final List _pathComponents; @override bool operator ==(dynamic o) => - o is DocumentReference && o._firestore == _firestore && o.path == path; + o is DocumentReference && o.firestore == firestore && o.path == path; @override int get hashCode => hashList(_pathComponents); @@ -38,7 +39,12 @@ class DocumentReference { Future setData(Map data, [SetOptions options]) { return Firestore.channel.invokeMethod( 'DocumentReference#setData', - {'path': path, 'data': data, 'options': options?._data}, + { + 'app': firestore.app.name, + 'path': path, + 'data': data, + 'options': options?._data, + }, ); } @@ -48,7 +54,11 @@ class DocumentReference { Future updateData(Map data) { return Firestore.channel.invokeMethod( 'DocumentReference#updateData', - {'path': path, 'data': data}, + { + 'app': firestore.app.name, + 'path': path, + 'data': data, + }, ); } @@ -58,7 +68,7 @@ class DocumentReference { Future get() async { final Map data = await Firestore.channel.invokeMethod( 'DocumentReference#get', - {'path': path}, + {'app': firestore.app.name, 'path': path}, ); return new DocumentSnapshot._( data['path'], @@ -71,14 +81,14 @@ class DocumentReference { Future delete() { return Firestore.channel.invokeMethod( 'DocumentReference#delete', - {'path': path}, + {'app': firestore.app.name, 'path': path}, ); } /// Returns the reference of a collection contained inside of this /// document. CollectionReference getCollection(String collectionPath) { - return _firestore.collection( + return firestore.collection( [path, collectionPath].join('/'), ); } @@ -95,6 +105,7 @@ class DocumentReference { _handle = Firestore.channel.invokeMethod( 'Query#addDocumentListener', { + 'app': firestore.app.name, 'path': path, }, ).then((dynamic result) => result); diff --git a/packages/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/lib/src/firestore.dart index db7868df8ff8..884b034ad632 100644 --- a/packages/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/lib/src/firestore.dart @@ -24,7 +24,10 @@ class Firestore { {}; static int _transactionHandlerId = 0; - Firestore._() { + static bool _initialized = false; + + Firestore({FirebaseApp app}) : this.app = app ?? FirebaseApp.instance { + if (_initialized) return; channel.setMethodCallHandler((MethodCall call) { if (call.method == 'QuerySnapshot') { final QuerySnapshot snapshot = @@ -40,16 +43,26 @@ class Firestore { } else if (call.method == 'DoTransaction') { final int transactionId = call.arguments['transactionId']; return _transactionHandlers[transactionId]( - new Transaction(transactionId), + new Transaction(transactionId, this), ); } }); + _initialized = true; } - static Firestore _instance = new Firestore._(); - /// Gets the instance of Firestore for the default Firebase app. - static Firestore get instance => _instance; + static final Firestore instance = new Firestore(); + + /// The [FirebaseApp] instance to which this [FirebaseDatabase] belongs. + /// + /// If null, the default [FirebaseApp] is used. + final FirebaseApp app; + + @override + bool operator ==(dynamic o) => o is Firestore && o.app == app; + + @override + int get hashCode => app.hashCode; /// Gets a [CollectionReference] for the specified Firestore path. CollectionReference collection(String path) { @@ -68,7 +81,7 @@ class Firestore { /// /// Unlike transactions, write batches are persisted offline and therefore are /// preferable when you don’t need to condition your writes on read data. - WriteBatch batch() => new WriteBatch._(); + WriteBatch batch() => new WriteBatch._(this); /// Executes the given TransactionHandler and then attempts to commit the /// changes applied within an atomic transaction. @@ -98,8 +111,9 @@ class Firestore { 'Transaction timeout must be more than 0 milliseconds'); final int transactionId = _transactionHandlerId++; _transactionHandlers[transactionId] = transactionHandler; - final Map result = await channel.invokeMethod( - 'Firestore#runTransaction', { + final Map result = await channel + .invokeMethod('Firestore#runTransaction', { + 'app': app.name, 'transactionId': transactionId, 'transactionTimeout': timeout.inMilliseconds }); diff --git a/packages/cloud_firestore/lib/src/firestore_message_codec.dart b/packages/cloud_firestore/lib/src/firestore_message_codec.dart index 8d30b3f6c895..2a4f767b13b7 100644 --- a/packages/cloud_firestore/lib/src/firestore_message_codec.dart +++ b/packages/cloud_firestore/lib/src/firestore_message_codec.dart @@ -23,6 +23,9 @@ class FirestoreMessageCodec extends StandardMessageCodec { buffer.putFloat64(value.longitude); } else if (value is DocumentReference) { buffer.putUint8(_kDocumentReference); + final List appName = utf8.encoder.convert(value.firestore.app.name); + writeSize(buffer, appName.length); + buffer.putUint8List(appName); final List bytes = utf8.encoder.convert(value.path); writeSize(buffer, bytes.length); buffer.putUint8List(bytes); @@ -39,9 +42,14 @@ class FirestoreMessageCodec extends StandardMessageCodec { case _kGeoPoint: return new GeoPoint(buffer.getFloat64(), buffer.getFloat64()); case _kDocumentReference: + final int appNameLength = readSize(buffer); + final String appName = + utf8.decoder.convert(buffer.getUint8List(appNameLength)); + final FirebaseApp app = new FirebaseApp(name: appName); + final Firestore firestore = new Firestore(app: app); final int length = readSize(buffer); final String path = utf8.decoder.convert(buffer.getUint8List(length)); - return Firestore.instance.document(path); + return firestore.document(path); default: return super.readValueOfType(type, buffer); } diff --git a/packages/cloud_firestore/lib/src/query.dart b/packages/cloud_firestore/lib/src/query.dart index c3566504398a..d9fa3361eff0 100644 --- a/packages/cloud_firestore/lib/src/query.dart +++ b/packages/cloud_firestore/lib/src/query.dart @@ -7,11 +7,10 @@ part of cloud_firestore; /// Represents a query over the data at a particular location. class Query { Query._( - {@required Firestore firestore, + {@required this.firestore, @required List pathComponents, Map parameters}) - : _firestore = firestore, - _pathComponents = pathComponents, + : _pathComponents = pathComponents, _parameters = parameters ?? new Map.unmodifiable({ 'where': new List>.unmodifiable(>[]), @@ -21,7 +20,9 @@ class Query { assert(firestore != null), assert(pathComponents != null); - final Firestore _firestore; + /// The Firestore instance associated with this query + final Firestore firestore; + final List _pathComponents; final Map _parameters; @@ -31,7 +32,7 @@ class Query { Query _copyWithParameters(Map parameters) { return new Query._( - firestore: _firestore, + firestore: firestore, pathComponents: _pathComponents, parameters: new Map.unmodifiable( new Map.from(_parameters)..addAll(parameters), @@ -58,6 +59,7 @@ class Query { _handle = Firestore.channel.invokeMethod( 'Query#addSnapshotListener', { + 'app': firestore.app.name, 'path': path, 'parameters': _parameters, }, @@ -84,16 +86,17 @@ class Query { final Map data = await Firestore.channel.invokeMethod( 'Query#getDocuments', { + 'app': firestore.app.name, 'path': path, 'parameters': _parameters, }, ); - return new QuerySnapshot._(data, _firestore); + return new QuerySnapshot._(data, firestore); } /// Obtains a CollectionReference corresponding to this query's location. CollectionReference reference() => - new CollectionReference._(_firestore, _pathComponents); + new CollectionReference._(firestore, _pathComponents); /// Creates and returns a new [Query] with additional filter on specified /// [field]. diff --git a/packages/cloud_firestore/lib/src/transaction.dart b/packages/cloud_firestore/lib/src/transaction.dart index fde6d1151d19..de201b00c164 100644 --- a/packages/cloud_firestore/lib/src/transaction.dart +++ b/packages/cloud_firestore/lib/src/transaction.dart @@ -8,12 +8,15 @@ typedef Future TransactionHandler(Transaction transaction); class Transaction { int _transactionId; + Firestore _firestore; - Transaction(this._transactionId); + @visibleForTesting + Transaction(this._transactionId, this._firestore); Future get(DocumentReference documentReference) async { final dynamic result = await Firestore.channel .invokeMethod('Transaction#get', { + 'app': _firestore.app.name, 'transactionId': _transactionId, 'path': documentReference.path, }); @@ -28,6 +31,7 @@ class Transaction { Future delete(DocumentReference documentReference) async { return Firestore.channel .invokeMethod('Transaction#delete', { + 'app': _firestore.app.name, 'transactionId': _transactionId, 'path': documentReference.path, }); @@ -37,6 +41,7 @@ class Transaction { DocumentReference documentReference, Map data) async { return Firestore.channel .invokeMethod('Transaction#update', { + 'app': _firestore.app.name, 'transactionId': _transactionId, 'path': documentReference.path, 'data': data, @@ -46,6 +51,7 @@ class Transaction { Future set( DocumentReference documentReference, Map data) async { return Firestore.channel.invokeMethod('Transaction#set', { + 'app': _firestore.app.name, 'transactionId': _transactionId, 'path': documentReference.path, 'data': data, diff --git a/packages/cloud_firestore/lib/src/write_batch.dart b/packages/cloud_firestore/lib/src/write_batch.dart index d2b325d39322..7c5c28e32537 100644 --- a/packages/cloud_firestore/lib/src/write_batch.dart +++ b/packages/cloud_firestore/lib/src/write_batch.dart @@ -11,11 +11,11 @@ part of cloud_firestore; /// Once committed, no further operations can be performed on the [WriteBatch], /// nor can it be committed again. class WriteBatch { - WriteBatch._() + WriteBatch._(this._firestore) : _handle = Firestore.channel.invokeMethod( - 'WriteBatch#create', - ); + 'WriteBatch#create', {'app': _firestore.app.name}); + final Firestore _firestore; Future _handle; final List> _actions = >[]; @@ -43,7 +43,11 @@ class WriteBatch { _actions.add( Firestore.channel.invokeMethod( 'WriteBatch#delete', - {'handle': handle, 'path': document.path}, + { + 'app': _firestore.app.name, + 'handle': handle, + 'path': document.path, + }, ), ); }); @@ -67,6 +71,7 @@ class WriteBatch { Firestore.channel.invokeMethod( 'WriteBatch#setData', { + 'app': _firestore.app.name, 'handle': handle, 'path': document.path, 'data': data, @@ -91,6 +96,7 @@ class WriteBatch { Firestore.channel.invokeMethod( 'WriteBatch#updateData', { + 'app': _firestore.app.name, 'handle': handle, 'path': document.path, 'data': data, diff --git a/packages/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/pubspec.yaml index 1124a233ae06..e3fecfc4df26 100755 --- a/packages/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/pubspec.yaml @@ -14,6 +14,7 @@ flutter: dependencies: flutter: sdk: flutter + firebase_core: "^0.2.0" meta: "^1.0.5" collection: "^1.14.3" diff --git a/packages/cloud_firestore/test/cloud_firestore_test.dart b/packages/cloud_firestore/test/cloud_firestore_test.dart index fe40ebf95a10..d980dd6321e5 100755 --- a/packages/cloud_firestore/test/cloud_firestore_test.dart +++ b/packages/cloud_firestore/test/cloud_firestore_test.dart @@ -6,34 +6,47 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('$Firestore', () { - const MethodChannel channel = const MethodChannel( - 'plugins.flutter.io/cloud_firestore', - ); - int mockHandleId = 0; - final Firestore firestore = Firestore.instance; + FirebaseApp app; + Firestore firestore; final List log = []; - final CollectionReference collectionReference = firestore.collection('foo'); - final Transaction transaction = new Transaction(0); + CollectionReference collectionReference; + Transaction transaction; const Map kMockDocumentSnapshotData = const {'1': 2}; setUp(() async { mockHandleId = 0; - channel.setMockMethodCallHandler((MethodCall methodCall) async { + // Required for FirebaseApp.configure + FirebaseApp.channel.setMockMethodCallHandler( + (MethodCall methodCall) async {}, + ); + app = await FirebaseApp.configure( + name: 'testApp', + options: const FirebaseOptions( + googleAppID: '1:1234567890:ios:42424242424242', + gcmSenderID: '1234567890', + ), + ); + firestore = new Firestore(app: app); + collectionReference = firestore.collection('foo'); + transaction = new Transaction(0, firestore); + Firestore.channel.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); switch (methodCall.method) { case 'Query#addSnapshotListener': final int handle = mockHandleId++; BinaryMessages.handlePlatformMessage( - channel.name, - channel.codec.encodeMethodCall( + Firestore.channel.name, + Firestore.channel.codec.encodeMethodCall( new MethodCall('QuerySnapshot', { + 'app': app.name, 'handle': handle, 'paths': ["${methodCall.arguments['path']}/0"], 'documents': [kMockDocumentSnapshotData], @@ -53,8 +66,8 @@ void main() { case 'Query#addDocumentListener': final int handle = mockHandleId++; BinaryMessages.handlePlatformMessage( - channel.name, - channel.codec.encodeMethodCall( + Firestore.channel.name, + Firestore.channel.codec.encodeMethodCall( new MethodCall('DocumentSnapshot', { 'handle': handle, 'path': methodCall.arguments['path'], @@ -111,6 +124,12 @@ void main() { log.clear(); }); + test('multiple apps', () async { + expect(Firestore.instance, equals(new Firestore())); + final FirebaseApp app = new FirebaseApp(name: firestore.app.name); + expect(firestore, equals(new Firestore(app: app))); + }); + group('Transaction', () { test('runTransaction', () async { final Map result = await firestore.runTransaction( @@ -119,6 +138,7 @@ void main() { expect(log, [ isMethodCall('Firestore#runTransaction', arguments: { + 'app': app.name, 'transactionId': 0, 'transactionTimeout': 3000 }), @@ -128,10 +148,11 @@ void main() { test('get', () async { final DocumentReference documentReference = - Firestore.instance.document('foo/bar'); + firestore.document('foo/bar'); await transaction.get(documentReference); expect(log, [ isMethodCall('Transaction#get', arguments: { + 'app': app.name, 'transactionId': 0, 'path': documentReference.path }) @@ -140,10 +161,11 @@ void main() { test('delete', () async { final DocumentReference documentReference = - Firestore.instance.document('foo/bar'); + firestore.document('foo/bar'); await transaction.delete(documentReference); expect(log, [ isMethodCall('Transaction#delete', arguments: { + 'app': app.name, 'transactionId': 0, 'path': documentReference.path }) @@ -152,15 +174,18 @@ void main() { test('update', () async { final DocumentReference documentReference = - Firestore.instance.document('foo/bar'); + firestore.document('foo/bar'); final DocumentSnapshot documentSnapshot = await documentReference.get(); final Map data = documentSnapshot.data; data['key2'] = 'val2'; await transaction.set(documentReference, data); expect(log, [ - isMethodCall('DocumentReference#get', - arguments: {'path': 'foo/bar'}), + isMethodCall('DocumentReference#get', arguments: { + 'app': app.name, + 'path': 'foo/bar', + }), isMethodCall('Transaction#set', arguments: { + 'app': app.name, 'transactionId': 0, 'path': documentReference.path, 'data': {'key1': 'val1', 'key2': 'val2'} @@ -170,15 +195,18 @@ void main() { test('set', () async { final DocumentReference documentReference = - Firestore.instance.document('foo/bar'); + firestore.document('foo/bar'); final DocumentSnapshot documentSnapshot = await documentReference.get(); final Map data = documentSnapshot.data; data['key2'] = 'val2'; await transaction.set(documentReference, data); expect(log, [ - isMethodCall('DocumentReference#get', - arguments: {'path': 'foo/bar'}), + isMethodCall('DocumentReference#get', arguments: { + 'app': app.name, + 'path': 'foo/bar', + }), isMethodCall('Transaction#set', arguments: { + 'app': app.name, 'transactionId': 0, 'path': documentReference.path, 'data': {'key1': 'val1', 'key2': 'val2'} @@ -201,6 +229,7 @@ void main() { isMethodCall( 'Query#addSnapshotListener', arguments: { + 'app': app.name, 'path': 'foo', 'parameters': { 'where': >[], @@ -228,6 +257,7 @@ void main() { isMethodCall( 'Query#addSnapshotListener', arguments: { + 'app': app.name, 'path': 'foo', 'parameters': { 'where': >[ @@ -258,6 +288,7 @@ void main() { isMethodCall( 'Query#addSnapshotListener', arguments: { + 'app': app.name, 'path': 'foo', 'parameters': { 'where': >[ @@ -288,6 +319,7 @@ void main() { isMethodCall( 'Query#addSnapshotListener', arguments: { + 'app': app.name, 'path': 'foo', 'parameters': { 'where': >[], @@ -309,7 +341,7 @@ void main() { group('DocumentReference', () { test('listen', () async { final DocumentSnapshot snapshot = - await Firestore.instance.document('path/to/foo').snapshots.first; + await firestore.document('path/to/foo').snapshots.first; expect(snapshot.documentID, equals('foo')); expect(snapshot.reference.path, equals('path/to/foo')); expect(snapshot.data, equals(kMockDocumentSnapshotData)); @@ -321,6 +353,7 @@ void main() { isMethodCall( 'Query#addDocumentListener', arguments: { + 'app': app.name, 'path': 'path/to/foo', }, ), @@ -341,6 +374,7 @@ void main() { isMethodCall( 'DocumentReference#setData', arguments: { + 'app': app.name, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, 'options': null, @@ -360,6 +394,7 @@ void main() { isMethodCall( 'DocumentReference#setData', arguments: { + 'app': app.name, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, 'options': {'merge': true}, @@ -378,6 +413,7 @@ void main() { isMethodCall( 'DocumentReference#updateData', arguments: { + 'app': app.name, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, }, @@ -392,7 +428,10 @@ void main() { equals([ isMethodCall( 'DocumentReference#delete', - arguments: {'path': 'foo/bar'}, + arguments: { + 'app': app.name, + 'path': 'foo/bar', + }, ), ]), ); @@ -405,7 +444,10 @@ void main() { equals([ isMethodCall( 'DocumentReference#get', - arguments: {'path': 'foo/bar'}, + arguments: { + 'app': app.name, + 'path': 'foo/bar', + }, ), ]), ); @@ -443,6 +485,7 @@ void main() { isMethodCall( 'Query#getDocuments', arguments: { + 'app': app.name, 'path': 'foo', 'parameters': { 'where': >[], @@ -489,10 +532,13 @@ void main() { expect( log, [ - isMethodCall('WriteBatch#create', arguments: null), + isMethodCall('WriteBatch#create', arguments: { + 'app': app.name, + }), isMethodCall( 'WriteBatch#setData', arguments: { + 'app': app.name, 'handle': 1, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, @@ -520,8 +566,11 @@ void main() { expect( log, [ - isMethodCall('WriteBatch#create', arguments: null), + isMethodCall('WriteBatch#create', arguments: { + 'app': app.name, + }), isMethodCall('WriteBatch#setData', arguments: { + 'app': app.name, 'handle': 1, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, @@ -546,10 +595,16 @@ void main() { expect( log, [ - isMethodCall('WriteBatch#create', arguments: null), + isMethodCall( + 'WriteBatch#create', + arguments: { + 'app': app.name, + }, + ), isMethodCall( 'WriteBatch#updateData', arguments: { + 'app': app.name, 'handle': 1, 'path': 'foo/bar', 'data': {'bazKey': 'quxValue'}, @@ -571,10 +626,16 @@ void main() { expect( log, [ - isMethodCall('WriteBatch#create', arguments: null), + isMethodCall( + 'WriteBatch#create', + arguments: { + 'app': app.name, + }, + ), isMethodCall( 'WriteBatch#delete', arguments: { + 'app': app.name, 'handle': 1, 'path': 'foo/bar', }, From afea3bf114ea0cbf9c45ad3caa63a56276af32c1 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 05:14:42 -0700 Subject: [PATCH 2/9] Remove extraneous todo --- .../plugins/firebase/cloudfirestore/CloudFirestorePlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java index 2aef904affc2..d28c7ed7de91 100644 --- a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java +++ b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java @@ -580,7 +580,6 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) { writeDouble(stream, ((GeoPoint) value).getLongitude()); } else if (value instanceof DocumentReference) { stream.write(DOCUMENT_REFERENCE); - // TODO(jackson): Null checking writeBytes( stream, ((DocumentReference) value).getFirestore().getApp().getName().getBytes(UTF8)); writeBytes(stream, ((DocumentReference) value).getPath().getBytes(UTF8)); From 5e48b2288b102c10660f536824da3a1b3652a5c8 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 05:16:17 -0700 Subject: [PATCH 3/9] Update firebase_core dependency of example --- packages/cloud_firestore/example/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/example/pubspec.yaml index 95444630d83a..ac93d077ad9b 100755 --- a/packages/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/example/pubspec.yaml @@ -6,8 +6,7 @@ dependencies: sdk: flutter cloud_firestore: path: ../ - firebase_core: # "^0.1.2" - path: ../../firebase_core + firebase_core: "^0.2.0" flutter: uses-material-design: true From 8f3d1fa294def49c16b85403480f174f924605ea Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 05:18:38 -0700 Subject: [PATCH 4/9] Remove unused dependency from podspec --- packages/cloud_firestore/ios/cloud_firestore.podspec | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cloud_firestore/ios/cloud_firestore.podspec b/packages/cloud_firestore/ios/cloud_firestore.podspec index 13e247093549..a1f806f7cd61 100755 --- a/packages/cloud_firestore/ios/cloud_firestore.podspec +++ b/packages/cloud_firestore/ios/cloud_firestore.podspec @@ -20,7 +20,6 @@ Firestore plugin for Flutter. s.dependency 'Firebase/Core' s.dependency 'Firebase/Auth' s.dependency 'Firebase/Firestore' - s.dependency 'firebase_core' s.pod_target_xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/**', 'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup' From c880071e7ac4b477684c4cd181b613968619d757 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 15:27:09 -0700 Subject: [PATCH 5/9] Code review feedback (pathLength) --- packages/cloud_firestore/lib/src/firestore_message_codec.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cloud_firestore/lib/src/firestore_message_codec.dart b/packages/cloud_firestore/lib/src/firestore_message_codec.dart index 2a4f767b13b7..87d491c7c8fb 100644 --- a/packages/cloud_firestore/lib/src/firestore_message_codec.dart +++ b/packages/cloud_firestore/lib/src/firestore_message_codec.dart @@ -47,8 +47,8 @@ class FirestoreMessageCodec extends StandardMessageCodec { utf8.decoder.convert(buffer.getUint8List(appNameLength)); final FirebaseApp app = new FirebaseApp(name: appName); final Firestore firestore = new Firestore(app: app); - final int length = readSize(buffer); - final String path = utf8.decoder.convert(buffer.getUint8List(length)); + final int pathLength = readSize(buffer); + final String path = utf8.decoder.convert(buffer.getUint8List(pathLength)); return firestore.document(path); default: return super.readValueOfType(type, buffer); From ffeab2bb29d5cb061aed60700c25142e19a7fb2f Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Apr 2018 15:45:00 -0700 Subject: [PATCH 6/9] Simplify sample app --- packages/cloud_firestore/example/lib/main.dart | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/cloud_firestore/example/lib/main.dart b/packages/cloud_firestore/example/lib/main.dart index c7025e9d0a0a..6e95d5a351fe 100755 --- a/packages/cloud_firestore/example/lib/main.dart +++ b/packages/cloud_firestore/example/lib/main.dart @@ -9,17 +9,16 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; Future main() async { - final FirebaseOptions options = const FirebaseOptions( - googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd', - gcmSenderID: '79601577497', - apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU', - projectID: 'flutter-firestore', - ); - FirebaseApp.configure( + final FirebaseApp app = await FirebaseApp.configure( name: 'test', - options: options, + options: const FirebaseOptions( + googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd', + gcmSenderID: '79601577497', + apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU', + projectID: 'flutter-firestore', + ), ); - final Firestore firestore = new Firestore(app: new FirebaseApp.named('test')); + final Firestore firestore = new Firestore(app: app); runApp(new MaterialApp( title: 'Firestore Example', home: new MyHomePage(firestore: firestore))); From 77c29665c9181ce74af466b586093e556f5bacfb Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Tue, 10 Apr 2018 11:29:45 -0700 Subject: [PATCH 7/9] reformat --- .../cloud_firestore/example/lib/main.dart | 2 +- .../ios/Classes/CloudFirestorePlugin.h | 2 +- .../ios/Classes/CloudFirestorePlugin.m | 33 +++++++++---------- .../lib/src/firestore_message_codec.dart | 3 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/cloud_firestore/example/lib/main.dart b/packages/cloud_firestore/example/lib/main.dart index 6e95d5a351fe..3566054a122f 100755 --- a/packages/cloud_firestore/example/lib/main.dart +++ b/packages/cloud_firestore/example/lib/main.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; -Future main() async { +Future main() async { final FirebaseApp app = await FirebaseApp.configure( name: 'test', options: const FirebaseOptions( diff --git a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h index 3a9035a10fd9..156faca7c01e 100644 --- a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h +++ b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.h @@ -4,5 +4,5 @@ #import -@interface FLTCloudFirestorePlugin : NSObject +@interface FLTCloudFirestorePlugin : NSObject @end diff --git a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m index 6019647db5f3..b97013a59876 100644 --- a/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m +++ b/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m @@ -252,28 +252,27 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result(error.flutterError); }; if ([@"Firestore#runTransaction" isEqualToString:call.method]) { - [getFirestore(call.arguments) - runTransactionWithBlock:^id(FIRTransaction *transaction, NSError **pError) { - NSNumber *transactionId = call.arguments[@"transactionId"]; - NSNumber *transactionTimeout = call.arguments[@"transactionTimeout"]; + [getFirestore(call.arguments) runTransactionWithBlock:^id(FIRTransaction *transaction, + NSError **pError) { + NSNumber *transactionId = call.arguments[@"transactionId"]; + NSNumber *transactionTimeout = call.arguments[@"transactionTimeout"]; - transactions[transactionId] = transaction; + transactions[transactionId] = transaction; - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - [self.channel invokeMethod:@"DoTransaction" - arguments:call.arguments - result:^(id doTransactionResult) { - transactionResults[transactionId] = doTransactionResult; - dispatch_semaphore_signal(semaphore); - }]; + [self.channel invokeMethod:@"DoTransaction" + arguments:call.arguments + result:^(id doTransactionResult) { + transactionResults[transactionId] = doTransactionResult; + dispatch_semaphore_signal(semaphore); + }]; - dispatch_semaphore_wait( - semaphore, - dispatch_time(DISPATCH_TIME_NOW, [transactionTimeout integerValue] * 1000000)); + dispatch_semaphore_wait( + semaphore, dispatch_time(DISPATCH_TIME_NOW, [transactionTimeout integerValue] * 1000000)); - return transactionResults[transactionId]; - } + return transactionResults[transactionId]; + } completion:^(id transactionResult, NSError *error) { if (error != nil) { result([FlutterError errorWithCode:[NSString stringWithFormat:@"%ld", error.code] diff --git a/packages/cloud_firestore/lib/src/firestore_message_codec.dart b/packages/cloud_firestore/lib/src/firestore_message_codec.dart index 87d491c7c8fb..ab2b0a2e66fe 100644 --- a/packages/cloud_firestore/lib/src/firestore_message_codec.dart +++ b/packages/cloud_firestore/lib/src/firestore_message_codec.dart @@ -48,7 +48,8 @@ class FirestoreMessageCodec extends StandardMessageCodec { final FirebaseApp app = new FirebaseApp(name: appName); final Firestore firestore = new Firestore(app: app); final int pathLength = readSize(buffer); - final String path = utf8.decoder.convert(buffer.getUint8List(pathLength)); + final String path = + utf8.decoder.convert(buffer.getUint8List(pathLength)); return firestore.document(path); default: return super.readValueOfType(type, buffer); From 94d06e96ff6c82b48254cea10ed8a5415c4f0e9c Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Tue, 10 Apr 2018 11:59:20 -0700 Subject: [PATCH 8/9] Remove merge marker --- packages/cloud_firestore/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/CHANGELOG.md index c630462473ce..c38d559d5352 100644 --- a/packages/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/CHANGELOG.md @@ -7,7 +7,6 @@ * **Breaking change**. Move path getter to CollectionReference * Add id getter to CollectionReference ->>>>>>> 989ebbf4cd2e45980068c05d0c246bee52245faa ## 0.4.0 From a36400bcb1adad34cc3f91187737443b22ffe707 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Tue, 10 Apr 2018 12:01:08 -0700 Subject: [PATCH 9/9] Bump firebase_core dependency --- packages/cloud_firestore/example/pubspec.yaml | 2 +- packages/cloud_firestore/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/example/pubspec.yaml index ac93d077ad9b..cc6d671528a6 100755 --- a/packages/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/example/pubspec.yaml @@ -6,7 +6,7 @@ dependencies: sdk: flutter cloud_firestore: path: ../ - firebase_core: "^0.2.0" + firebase_core: "^0.2.1" flutter: uses-material-design: true diff --git a/packages/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/pubspec.yaml index f8ba151847fd..f8d4079cdaa4 100755 --- a/packages/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/pubspec.yaml @@ -14,7 +14,7 @@ flutter: dependencies: flutter: sdk: flutter - firebase_core: "^0.2.0" + firebase_core: "^0.2.1" meta: "^1.0.5" collection: "^1.14.3"