MOD: removed packages no used
|
@ -11,7 +11,6 @@ In the future flutter_web will be merged with flutter master. At that time this
|
|||
|
||||
Working Plugins
|
||||
---------------
|
||||
|
||||
* provider
|
||||
- works as expected
|
||||
* flutter_progress_button
|
||||
|
@ -20,7 +19,7 @@ Working Plugins
|
|||
|
||||
Not Working Plugins (for your referrence)
|
||||
-----------------------------------------
|
||||
These packages are listed for referrence. These packages were an early attempt to get working, but failed for the reasons below:
|
||||
These plugins are listed for referrence. These plugins were an early attempt to get working, but failed for the reasons below:
|
||||
* firebase_core
|
||||
- cannot run on web because it is only a wrapper. this plugin depends on native code for Android/iOS. also developers intentionally added an exception that throws when trying to use this on flutter_web. "this is not compatible with flutter web preview".
|
||||
* cloud_firestore
|
||||
|
|
|
@ -1,381 +0,0 @@
|
|||
## 0.12.5
|
||||
|
||||
* Makes `startAtDocument`, `startAfterDocument`, `endAtDocument` and `endBeforeDocument` work
|
||||
with `Query.collectionGroup` queries.
|
||||
* Fixes `startAtDocument`, `startAfterDocument`, `endAtDocument` and `endBeforeDocument` to
|
||||
also work with a descending order as the last explicit sort order.
|
||||
* Fixed an integration test by increasing the value of `cacheSizeBytes` to a valid value.
|
||||
|
||||
## 0.12.4
|
||||
|
||||
* Added support for `Query.collectionGroup`.
|
||||
|
||||
## 0.12.3
|
||||
|
||||
* Added support for `cacheSizeBytes` to `Firestore.settings`.
|
||||
|
||||
## 0.12.2
|
||||
|
||||
* Ensure that all channel calls to the Dart side from the Java side are done
|
||||
on the UI thread. This change allows Transactions to work with upcoming
|
||||
Engine restrictions, which require channel calls be made on the UI thread.
|
||||
**Note** this is an Android only change, the iOS implementation was not impacted.
|
||||
* Updated the Firebase reporting string to `flutter-fire-fst` to be consistent
|
||||
with other reporting libraries.
|
||||
|
||||
## 0.12.1
|
||||
|
||||
* Added support for `Source` to `Query.getDocuments()` and `DocumentReference.get()`.
|
||||
|
||||
## 0.12.0+2
|
||||
|
||||
* Bump the minimum Flutter version to 1.5.
|
||||
* Replace invokeMethod with invokeMapMethod wherever necessary.
|
||||
|
||||
## 0.12.0+1
|
||||
|
||||
* Send user agent to Firebase.
|
||||
|
||||
## 0.12.0
|
||||
|
||||
* **Breaking change**. Fixed `CollectionReference.parent` to correctly return a `DocumentReference`.
|
||||
If you were using the method previously to obtain the parent
|
||||
document's id via `collectionReference.parent().id`,
|
||||
you will have to use `collectionReference.parent().documentID` now.
|
||||
* Added `DocumentReference.parent`.
|
||||
|
||||
## 0.11.0+2
|
||||
|
||||
* Remove iOS dependency on Firebase/Database and Firebase/Auth CocoaPods.
|
||||
|
||||
## 0.11.0+1
|
||||
|
||||
* Update iOS CocoaPod dependencies to '~> 6.0' to ensure support for `FieldValue.increment`.
|
||||
|
||||
## 0.11.0
|
||||
|
||||
* Update Android dependencies to latest.
|
||||
|
||||
## 0.10.1
|
||||
|
||||
* Support for `startAtDocument`, `startAfterDocument`, `endAtDocument`, `endBeforeDocument`.
|
||||
* Added additional unit and integration tests.
|
||||
|
||||
## 0.10.0
|
||||
|
||||
* Support for `FieldValue.increment`.
|
||||
* Remove `FieldValue.type` and `FieldValue.value` from public API.
|
||||
* Additional integration testing.
|
||||
|
||||
## 0.9.13+1
|
||||
|
||||
* Added an integration test for transactions.
|
||||
|
||||
## 0.9.13
|
||||
|
||||
* Remove Gradle BoM to avoid Gradle version issues.
|
||||
|
||||
## 0.9.12
|
||||
|
||||
* Move Android dependency to Gradle BoM to help maintain compatibility
|
||||
with other FlutterFire plugins.
|
||||
|
||||
## 0.9.11
|
||||
|
||||
* Bump Android dependencies to latest.
|
||||
|
||||
# 0.9.10
|
||||
|
||||
* Support for cloud_firestore running in the background on Android.
|
||||
* Fixed a bug in cleanup for DocumentReference.snapshots().
|
||||
* Additional integration testing.
|
||||
|
||||
## 0.9.9
|
||||
|
||||
* Remove `invokeMapMethod` calls to prevent crash.
|
||||
|
||||
## 0.9.8
|
||||
|
||||
* Add metadata field to DocumentSnapshot.
|
||||
|
||||
## 0.9.7+2
|
||||
|
||||
* Bump the minimum Flutter version to 1.2.0.
|
||||
* Add template type parameter to `invokeMethod` calls.
|
||||
|
||||
## 0.9.7+1
|
||||
|
||||
* Update README with example of getting a document.
|
||||
|
||||
## 0.9.7
|
||||
|
||||
* Fixes a NoSuchMethodError when using getDocuments on iOS (introduced in 0.9.6).
|
||||
* Adds a driver test for getDocuments.
|
||||
|
||||
## 0.9.6
|
||||
|
||||
* On iOS, update null checking to match the recommended pattern usage in the Firebase documentation.
|
||||
* Fixes a case where snapshot errors might result in plugin crash.
|
||||
|
||||
## 0.9.5+2
|
||||
|
||||
* Fixing PlatformException(Error 0, null, null) which happened when a successful operation was performed.
|
||||
|
||||
## 0.9.5+1
|
||||
|
||||
* Log messages about automatic configuration of the default app are now less confusing.
|
||||
|
||||
## 0.9.5
|
||||
|
||||
* Fix an issue on some iOS devices that results in reading incorrect dates.
|
||||
|
||||
## 0.9.4
|
||||
|
||||
* No longer sends empty snapshot events on iOS when encountering errors.
|
||||
|
||||
## 0.9.3
|
||||
|
||||
* Fix transactions on iOS when getting snapshot that doesn't exist.
|
||||
|
||||
## 0.9.2
|
||||
|
||||
* Fix IllegalStateException errors when using transactions on Android.
|
||||
|
||||
## 0.9.1
|
||||
|
||||
* Fixed Firebase multiple app support in transactions and document snapshots.
|
||||
|
||||
## 0.9.0+2
|
||||
|
||||
* Remove categories.
|
||||
|
||||
## 0.9.0+1
|
||||
|
||||
* Log a more detailed warning at build time about the previous AndroidX
|
||||
migration.
|
||||
|
||||
## 0.9.0
|
||||
|
||||
* **Breaking change**. Migrate from the deprecated original Android Support
|
||||
Library to AndroidX. This shouldn't result in any functional changes, but it
|
||||
requires any Android apps using this plugin to [also
|
||||
migrate](https://developer.android.com/jetpack/androidx/migrate) if they're
|
||||
using the original support library.
|
||||
|
||||
## 0.8.2+3
|
||||
|
||||
* Resolved "explicit self reference" and "loses accuracy" compiler warnings.
|
||||
|
||||
## 0.8.2+2
|
||||
|
||||
* Clean up Android build logs. @SuppressWarnings("unchecked")
|
||||
|
||||
## 0.8.2+1
|
||||
|
||||
* Avoid crash in document snapshot callback.
|
||||
|
||||
## 0.8.2
|
||||
|
||||
* Added `Firestore.settings`
|
||||
* Added `Timestamp` class
|
||||
|
||||
## 0.8.1+1
|
||||
|
||||
* Bump Android dependencies to latest.
|
||||
|
||||
## 0.8.1
|
||||
|
||||
* Fixed bug where updating arrays in with `FieldValue` always throws an Exception on Android.
|
||||
|
||||
## 0.8.0
|
||||
|
||||
Note: this version depends on features available in iOS SDK versions 5.5.0 or later.
|
||||
To update iOS SDK in existing projects run `pod update Firebase/Firestore`.
|
||||
|
||||
* Added `Firestore.enablePersistence`
|
||||
* Added `FieldValue` with all currently supported values: `arrayUnion`, `arrayRemove`, `delete` and
|
||||
`serverTimestamp`.
|
||||
* Added `arrayContains` argument in `Query.where` method.
|
||||
|
||||
## 0.7.4
|
||||
|
||||
* Bump Android and Firebase dependency versions.
|
||||
|
||||
## 0.7.3
|
||||
|
||||
* Updated Gradle tooling to match Android Studio 3.1.2.
|
||||
|
||||
## 0.7.2
|
||||
|
||||
* Fixes crash on Android if a FirebaseFirestoreException happened.
|
||||
|
||||
## 0.7.1
|
||||
|
||||
* Updated iOS implementation to reflect Firebase API changes.
|
||||
* Fixed bug in Transaction.get that would fail on no data.
|
||||
* Fixed error in README.md code sample.
|
||||
|
||||
## 0.7.0+2
|
||||
|
||||
* Update transactions example in README to add `await`.
|
||||
|
||||
## 0.7.0+1
|
||||
|
||||
* Add transactions example to README.
|
||||
|
||||
## 0.7.0
|
||||
|
||||
* **Breaking change**. `snapshots` is now a method instead of a getter.
|
||||
* **Breaking change**. `setData` uses named arguments instead of `SetOptions`.
|
||||
|
||||
## 0.6.3
|
||||
|
||||
* Updated Google Play Services dependencies to version 15.0.0.
|
||||
|
||||
## 0.6.2
|
||||
|
||||
* Support for BLOB data type.
|
||||
|
||||
## 0.6.1
|
||||
|
||||
* Simplified podspec for Cocoapods 1.5.0, avoiding link issues in app archives.
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* **Breaking change**. Renamed 'getCollection()' to 'collection().'
|
||||
|
||||
## 0.5.1
|
||||
|
||||
* Expose the Firebase app corresponding to a Firestore
|
||||
* Expose a constructor for a Firestore with a non-default Firebase app
|
||||
|
||||
## 0.5.0
|
||||
|
||||
* **Breaking change**. Move path getter to CollectionReference
|
||||
* Add id getter to CollectionReference
|
||||
|
||||
## 0.4.0
|
||||
|
||||
* **Breaking change**. Hide Firestore codec class from public API.
|
||||
* Adjusted Flutter SDK constraint to match Flutter release with extensible
|
||||
platform message codec, required already by version 0.3.1.
|
||||
* Move each class into separate files
|
||||
|
||||
## 0.3.2
|
||||
|
||||
* Support for batched writes.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
* Add GeoPoint class
|
||||
* Allow for reading and writing DocumentReference, DateTime, and GeoPoint
|
||||
values from and to Documents.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
* **Breaking change**. Set SDK constraints to match the Flutter beta release.
|
||||
|
||||
## 0.2.12
|
||||
|
||||
* Fix handling of `null` document snapshots (document not exists).
|
||||
* Add `DocumentSnapshot.exists`.
|
||||
|
||||
## 0.2.11
|
||||
* Fix Dart 2 type errors.
|
||||
|
||||
## 0.2.10
|
||||
* Fix Dart 2 type errors.
|
||||
|
||||
## 0.2.9
|
||||
* Relax sdk upper bound constraint to '<2.0.0' to allow 'edge' dart sdk use.
|
||||
|
||||
## 0.2.8
|
||||
* Support for Query.getDocuments
|
||||
|
||||
## 0.2.7
|
||||
|
||||
* Add transaction support.
|
||||
|
||||
## 0.2.6
|
||||
|
||||
* Build fixes for iOS
|
||||
* Null checking in newly added Query methods
|
||||
|
||||
## 0.2.5
|
||||
|
||||
* Query can now have more than one orderBy field.
|
||||
* startAt, startAfter, endAt, and endBefore support
|
||||
* limit support
|
||||
|
||||
## 0.2.4
|
||||
|
||||
* Support for DocumentReference.documentID
|
||||
* Support for CollectionReference.add
|
||||
|
||||
## 0.2.3
|
||||
|
||||
* Simplified and upgraded Android project template to Android SDK 27.
|
||||
* Updated package description.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
* Add `get` to DocumentReference.
|
||||
|
||||
## 0.2.1
|
||||
|
||||
* Fix bug on Android where removeListener is sometimes called without a handle
|
||||
|
||||
## 0.2.0
|
||||
|
||||
* **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin
|
||||
3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in
|
||||
order to use this version of the plugin. Instructions can be found
|
||||
[here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1).
|
||||
* Relaxed GMS dependency to [11.4.0,12.0[
|
||||
|
||||
## 0.1.2
|
||||
|
||||
* Support for `DocumentReference` update and merge writes
|
||||
* Suppress unchecked warnings and package name warnings on Android
|
||||
|
||||
## 0.1.1
|
||||
|
||||
* Added FLT prefix to iOS types.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
* Added reference to DocumentSnapshot
|
||||
* Breaking: removed path from DocumentSnapshot
|
||||
* Additional test coverage for reading collections and documents
|
||||
* Fixed typo in DocumentChange documentation
|
||||
|
||||
## 0.0.6
|
||||
|
||||
* Support for getCollection
|
||||
|
||||
## 0.0.5
|
||||
|
||||
* Support `isNull` filtering in `Query.where`
|
||||
* Fixed `DocumentChange.oldIndex` and `DocumentChange.newIndex` to be signed
|
||||
integers (iOS)
|
||||
|
||||
## 0.0.4
|
||||
|
||||
* Support for where clauses
|
||||
* Support for deletion
|
||||
|
||||
## 0.0.3
|
||||
|
||||
* Renamed package to cloud_firestore
|
||||
|
||||
## 0.0.2
|
||||
|
||||
* Add path property to DocumentSnapshot
|
||||
|
||||
## 0.0.1+1
|
||||
|
||||
* Update project homepage
|
||||
|
||||
## 0.0.1
|
||||
|
||||
* Initial Release
|
|
@ -1,26 +0,0 @@
|
|||
Copyright 2017, the Chromium project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,104 +0,0 @@
|
|||
# Cloud Firestore Plugin for Flutter
|
||||
|
||||
A Flutter plugin to use the [Cloud Firestore API](https://firebase.google.com/docs/firestore/).
|
||||
|
||||
[](https://pub.dartlang.org/packages/cloud_firestore)
|
||||
|
||||
For Flutter plugins for other Firebase products, see [FlutterFire.md](https://github.com/flutter/plugins/blob/master/FlutterFire.md).
|
||||
|
||||
*Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/flutter/flutter/issues) and [Pull Requests](https://github.com/flutter/plugins/pulls) are most welcome!
|
||||
|
||||
## Setup
|
||||
|
||||
To use this plugin:
|
||||
|
||||
1. Using the [Firebase Console](http://console.firebase.google.com/), add an Android app to your project:
|
||||
Follow the assistant, download the generated google-services.json file and place it inside android/app. Next,
|
||||
modify the android/build.gradle file and the android/app/build.gradle file to add the Google services plugin
|
||||
as described by the Firebase assistant. Ensure that your `android/build.gradle` file contains the
|
||||
`maven.google.com` as [described here](https://firebase.google.com/docs/android/setup#add_the_sdk).
|
||||
1. Using the [Firebase Console](http://console.firebase.google.com/), add an iOS app to your project:
|
||||
Follow the assistant, download the generated GoogleService-Info.plist file, open ios/Runner.xcworkspace
|
||||
with Xcode, and within Xcode place the file inside ios/Runner. Don't follow the steps named
|
||||
"Add Firebase SDK" and "Add initialization code" in the Firebase assistant.
|
||||
1. Add `cloud_firestore` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).
|
||||
|
||||
## Usage
|
||||
|
||||
```dart
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
```
|
||||
|
||||
Adding a new `DocumentReference`:
|
||||
|
||||
```dart
|
||||
Firestore.instance.collection('books').document()
|
||||
.setData({ 'title': 'title', 'author': 'author' });
|
||||
```
|
||||
|
||||
Binding a `CollectionReference` to a `ListView`:
|
||||
|
||||
```dart
|
||||
class BookList extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<QuerySnapshot>(
|
||||
stream: Firestore.instance.collection('books').snapshots(),
|
||||
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
|
||||
if (snapshot.hasError)
|
||||
return new Text('Error: ${snapshot.error}');
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.waiting: return new Text('Loading...');
|
||||
default:
|
||||
return new ListView(
|
||||
children: snapshot.data.documents.map((DocumentSnapshot document) {
|
||||
return new ListTile(
|
||||
title: new Text(document['title']),
|
||||
subtitle: new Text(document['author']),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Performing a query:
|
||||
```dart
|
||||
Firestore.instance
|
||||
.collection('talks')
|
||||
.where("topic", isEqualTo: "flutter")
|
||||
.snapshots()
|
||||
.listen((data) =>
|
||||
data.documents.forEach((doc) => print(doc["title"])));
|
||||
```
|
||||
|
||||
Get a specific document:
|
||||
|
||||
```dart
|
||||
Firestore.instance
|
||||
.collection('talks')
|
||||
.document('document-name')
|
||||
.get()
|
||||
.then((DocumentSnapshot ds) {
|
||||
// use ds as a snapshot
|
||||
});
|
||||
```
|
||||
|
||||
Running a transaction:
|
||||
|
||||
```dart
|
||||
final DocumentReference postRef = Firestore.instance.document('posts/123');
|
||||
Firestore.instance.runTransaction((Transaction tx) async {
|
||||
DocumentSnapshot postSnapshot = await tx.get(postRef);
|
||||
if (postSnapshot.exists) {
|
||||
await tx.update(postRef, <String, dynamic>{'likesCount': postSnapshot.data['likesCount'] + 1});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
See the `example` directory for a complete sample app using Cloud Firestore.
|
|
@ -1,54 +0,0 @@
|
|||
def PLUGIN = "cloud_firestore";
|
||||
def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning";
|
||||
gradle.buildFinished { buildResult ->
|
||||
if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) {
|
||||
println ' *********************************************************'
|
||||
println 'WARNING: This version of ' + PLUGIN + ' will break your Android build if it or its dependencies aren\'t compatible with AndroidX.'
|
||||
println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.'
|
||||
println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.'
|
||||
println ' *********************************************************'
|
||||
rootProject.ext.set(ANDROIDX_WARNING, true);
|
||||
}
|
||||
}
|
||||
|
||||
group 'io.flutter.plugins.firebase.firestore'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
dependencies {
|
||||
api 'com.google.firebase:firebase-firestore:19.0.0'
|
||||
implementation 'com.google.firebase:firebase-common:16.1.0'
|
||||
implementation 'androidx.annotation:annotation:1.0.0'
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
rootProject.name = 'cloud_firestore'
|
|
@ -1,9 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.flutter.plugins.firebase.firestore">
|
||||
<application>
|
||||
<service android:name="com.google.firebase.components.ComponentDiscoveryService">
|
||||
<meta-data android:name="com.google.firebase.components:io.flutter.plugins.firebase.cloudfirestore.FlutterFirebaseAppRegistrar"
|
||||
android:value="com.google.firebase.components.ComponentRegistrar" />
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
|
@ -1,881 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.plugins.firebase.cloudfirestore;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.OnFailureListener;
|
||||
import com.google.android.gms.tasks.OnSuccessListener;
|
||||
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.Timestamp;
|
||||
import com.google.firebase.firestore.Blob;
|
||||
import com.google.firebase.firestore.CollectionReference;
|
||||
import com.google.firebase.firestore.DocumentChange;
|
||||
import com.google.firebase.firestore.DocumentReference;
|
||||
import com.google.firebase.firestore.DocumentSnapshot;
|
||||
import com.google.firebase.firestore.EventListener;
|
||||
import com.google.firebase.firestore.FieldPath;
|
||||
import com.google.firebase.firestore.FieldValue;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.FirebaseFirestoreException;
|
||||
import com.google.firebase.firestore.FirebaseFirestoreSettings;
|
||||
import com.google.firebase.firestore.GeoPoint;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QuerySnapshot;
|
||||
import com.google.firebase.firestore.SetOptions;
|
||||
import com.google.firebase.firestore.Source;
|
||||
import com.google.firebase.firestore.Transaction;
|
||||
import com.google.firebase.firestore.WriteBatch;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
||||
import io.flutter.plugin.common.MethodChannel.Result;
|
||||
import io.flutter.plugin.common.PluginRegistry;
|
||||
import io.flutter.plugin.common.StandardMessageCodec;
|
||||
import io.flutter.plugin.common.StandardMethodCodec;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CloudFirestorePlugin implements MethodCallHandler {
|
||||
|
||||
private static final String TAG = "CloudFirestorePlugin";
|
||||
private final MethodChannel channel;
|
||||
private final Activity activity;
|
||||
|
||||
// Handles are ints used as indexes into the sparse array of active observers
|
||||
private int nextListenerHandle = 0;
|
||||
private int nextBatchHandle = 0;
|
||||
private final SparseArray<EventObserver> observers = new SparseArray<>();
|
||||
private final SparseArray<DocumentObserver> documentObservers = new SparseArray<>();
|
||||
private final SparseArray<ListenerRegistration> listenerRegistrations = new SparseArray<>();
|
||||
private final SparseArray<WriteBatch> batches = new SparseArray<>();
|
||||
private final SparseArray<Transaction> transactions = new SparseArray<>();
|
||||
private final SparseArray<TaskCompletionSource> completionTasks = new SparseArray<>();
|
||||
|
||||
public static void registerWith(PluginRegistry.Registrar registrar) {
|
||||
final MethodChannel channel =
|
||||
new MethodChannel(
|
||||
registrar.messenger(),
|
||||
"plugins.flutter.io/cloud_firestore",
|
||||
new StandardMethodCodec(FirestoreMessageCodec.INSTANCE));
|
||||
channel.setMethodCallHandler(new CloudFirestorePlugin(channel, registrar.activity()));
|
||||
}
|
||||
|
||||
private CloudFirestorePlugin(MethodChannel channel, Activity activity) {
|
||||
this.channel = channel;
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
private FirebaseFirestore getFirestore(Map<String, Object> arguments) {
|
||||
String appName = (String) arguments.get("app");
|
||||
return FirebaseFirestore.getInstance(FirebaseApp.getInstance(appName));
|
||||
}
|
||||
|
||||
private Query getReference(Map<String, Object> arguments) {
|
||||
if ((boolean) arguments.get("isCollectionGroup")) return getCollectionGroupReference(arguments);
|
||||
else return getCollectionReference(arguments);
|
||||
}
|
||||
|
||||
private Query getCollectionGroupReference(Map<String, Object> arguments) {
|
||||
String path = (String) arguments.get("path");
|
||||
return getFirestore(arguments).collectionGroup(path);
|
||||
}
|
||||
|
||||
private CollectionReference getCollectionReference(Map<String, Object> arguments) {
|
||||
String path = (String) arguments.get("path");
|
||||
return getFirestore(arguments).collection(path);
|
||||
}
|
||||
|
||||
private DocumentReference getDocumentReference(Map<String, Object> arguments) {
|
||||
String path = (String) arguments.get("path");
|
||||
return getFirestore(arguments).document(path);
|
||||
}
|
||||
|
||||
private Source getSource(Map<String, Object> arguments) {
|
||||
String source = (String) arguments.get("source");
|
||||
switch (source) {
|
||||
case "server":
|
||||
return Source.SERVER;
|
||||
case "cache":
|
||||
return Source.CACHE;
|
||||
default:
|
||||
return Source.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
private Query implicitOrderBy(Query query, List<List<Object>> orderBy) {
|
||||
boolean descending = (boolean) orderBy.get(orderBy.size() - 1).get(1);
|
||||
Query.Direction direction = descending ? Query.Direction.DESCENDING : Query.Direction.ASCENDING;
|
||||
return query.orderBy(FieldPath.documentId(), direction);
|
||||
}
|
||||
|
||||
private Object[] getDocumentValues(
|
||||
Map<String, Object> document, List<List<Object>> orderBy, Map<String, Object> arguments) {
|
||||
String documentId = (String) document.get("id");
|
||||
Map<String, Object> documentData = (Map<String, Object>) document.get("data");
|
||||
List<Object> data = new ArrayList<>();
|
||||
if (orderBy != null) {
|
||||
for (List<Object> order : orderBy) {
|
||||
String orderByFieldName = (String) order.get(0);
|
||||
data.add(documentData.get(orderByFieldName));
|
||||
}
|
||||
}
|
||||
data.add((boolean) arguments.get("isCollectionGroup") ? document.get("path") : documentId);
|
||||
return data.toArray();
|
||||
}
|
||||
|
||||
private Map<String, Object> parseQuerySnapshot(QuerySnapshot querySnapshot) {
|
||||
if (querySnapshot == null) return new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
List<String> paths = new ArrayList<>();
|
||||
List<Map<String, Object>> documents = new ArrayList<>();
|
||||
List<Map<String, Object>> metadatas = new ArrayList<>();
|
||||
for (DocumentSnapshot document : querySnapshot.getDocuments()) {
|
||||
paths.add(document.getReference().getPath());
|
||||
documents.add(document.getData());
|
||||
Map<String, Object> metadata = new HashMap<String, Object>();
|
||||
metadata.put("hasPendingWrites", document.getMetadata().hasPendingWrites());
|
||||
metadata.put("isFromCache", document.getMetadata().isFromCache());
|
||||
metadatas.add(metadata);
|
||||
}
|
||||
data.put("paths", paths);
|
||||
data.put("documents", documents);
|
||||
data.put("metadatas", metadatas);
|
||||
|
||||
List<Map<String, Object>> documentChanges = new ArrayList<>();
|
||||
for (DocumentChange documentChange : querySnapshot.getDocumentChanges()) {
|
||||
Map<String, Object> change = new HashMap<>();
|
||||
String type = null;
|
||||
switch (documentChange.getType()) {
|
||||
case ADDED:
|
||||
type = "DocumentChangeType.added";
|
||||
break;
|
||||
case MODIFIED:
|
||||
type = "DocumentChangeType.modified";
|
||||
break;
|
||||
case REMOVED:
|
||||
type = "DocumentChangeType.removed";
|
||||
break;
|
||||
}
|
||||
change.put("type", type);
|
||||
change.put("oldIndex", documentChange.getOldIndex());
|
||||
change.put("newIndex", documentChange.getNewIndex());
|
||||
change.put("document", documentChange.getDocument().getData());
|
||||
change.put("path", documentChange.getDocument().getReference().getPath());
|
||||
Map<String, Object> metadata = new HashMap();
|
||||
metadata.put(
|
||||
"hasPendingWrites", documentChange.getDocument().getMetadata().hasPendingWrites());
|
||||
metadata.put("isFromCache", documentChange.getDocument().getMetadata().isFromCache());
|
||||
change.put("metadata", metadata);
|
||||
documentChanges.add(change);
|
||||
}
|
||||
data.put("documentChanges", documentChanges);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private Transaction getTransaction(Map<String, Object> arguments) {
|
||||
return transactions.get((Integer) arguments.get("transactionId"));
|
||||
}
|
||||
|
||||
private Query getQuery(Map<String, Object> arguments) {
|
||||
Query query = getReference(arguments);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> parameters = (Map<String, Object>) arguments.get("parameters");
|
||||
if (parameters == null) return query;
|
||||
@SuppressWarnings("unchecked")
|
||||
List<List<Object>> whereConditions = (List<List<Object>>) parameters.get("where");
|
||||
for (List<Object> condition : whereConditions) {
|
||||
String fieldName = (String) condition.get(0);
|
||||
String operator = (String) condition.get(1);
|
||||
Object value = condition.get(2);
|
||||
if ("==".equals(operator)) {
|
||||
query = query.whereEqualTo(fieldName, value);
|
||||
} else if ("<".equals(operator)) {
|
||||
query = query.whereLessThan(fieldName, value);
|
||||
} else if ("<=".equals(operator)) {
|
||||
query = query.whereLessThanOrEqualTo(fieldName, value);
|
||||
} else if (">".equals(operator)) {
|
||||
query = query.whereGreaterThan(fieldName, value);
|
||||
} else if (">=".equals(operator)) {
|
||||
query = query.whereGreaterThanOrEqualTo(fieldName, value);
|
||||
} else if ("array-contains".equals(operator)) {
|
||||
query = query.whereArrayContains(fieldName, value);
|
||||
} else {
|
||||
// Invalid operator.
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Number limit = (Number) parameters.get("limit");
|
||||
if (limit != null) query = query.limit(limit.longValue());
|
||||
@SuppressWarnings("unchecked")
|
||||
List<List<Object>> orderBy = (List<List<Object>>) parameters.get("orderBy");
|
||||
if (orderBy == null) return query;
|
||||
for (List<Object> order : orderBy) {
|
||||
String orderByFieldName = (String) order.get(0);
|
||||
boolean descending = (boolean) order.get(1);
|
||||
Query.Direction direction =
|
||||
descending ? Query.Direction.DESCENDING : Query.Direction.ASCENDING;
|
||||
query = query.orderBy(orderByFieldName, direction);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> startAtDocument = (Map<String, Object>) parameters.get("startAtDocument");
|
||||
if (startAtDocument != null) {
|
||||
query =
|
||||
implicitOrderBy(query, orderBy)
|
||||
.startAt(getDocumentValues(startAtDocument, orderBy, arguments));
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> startAfterDocument =
|
||||
(Map<String, Object>) parameters.get("startAfterDocument");
|
||||
if (startAfterDocument != null) {
|
||||
query =
|
||||
implicitOrderBy(query, orderBy)
|
||||
.startAfter(getDocumentValues(startAfterDocument, orderBy, arguments));
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> startAt = (List<Object>) parameters.get("startAt");
|
||||
if (startAt != null) query = query.startAt(startAt.toArray());
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> startAfter = (List<Object>) parameters.get("startAfter");
|
||||
if (startAfter != null) query = query.startAfter(startAfter.toArray());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> endAtDocument = (Map<String, Object>) parameters.get("endAtDocument");
|
||||
if (endAtDocument != null) {
|
||||
query =
|
||||
implicitOrderBy(query, orderBy)
|
||||
.endAt(getDocumentValues(endAtDocument, orderBy, arguments));
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> endBeforeDocument =
|
||||
(Map<String, Object>) parameters.get("endBeforeDocument");
|
||||
if (endBeforeDocument != null) {
|
||||
query =
|
||||
implicitOrderBy(query, orderBy)
|
||||
.endBefore(getDocumentValues(endBeforeDocument, orderBy, arguments));
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> endAt = (List<Object>) parameters.get("endAt");
|
||||
if (endAt != null) query = query.endAt(endAt.toArray());
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> endBefore = (List<Object>) parameters.get("endBefore");
|
||||
if (endBefore != null) query = query.endBefore(endBefore.toArray());
|
||||
return query;
|
||||
}
|
||||
|
||||
private class DocumentObserver implements EventListener<DocumentSnapshot> {
|
||||
private int handle;
|
||||
|
||||
DocumentObserver(int handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
|
||||
if (e != null) {
|
||||
// TODO: send error
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
Map<String, Object> metadata = new HashMap<>();
|
||||
arguments.put("handle", handle);
|
||||
metadata.put("hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites());
|
||||
metadata.put("isFromCache", documentSnapshot.getMetadata().isFromCache());
|
||||
arguments.put("metadata", metadata);
|
||||
if (documentSnapshot.exists()) {
|
||||
arguments.put("data", documentSnapshot.getData());
|
||||
arguments.put("path", documentSnapshot.getReference().getPath());
|
||||
} else {
|
||||
arguments.put("data", null);
|
||||
arguments.put("path", documentSnapshot.getReference().getPath());
|
||||
}
|
||||
channel.invokeMethod("DocumentSnapshot", arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private class EventObserver implements EventListener<QuerySnapshot> {
|
||||
private int handle;
|
||||
|
||||
EventObserver(int handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(QuerySnapshot querySnapshot, FirebaseFirestoreException e) {
|
||||
if (e != null) {
|
||||
// TODO: send error
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> arguments = parseQuerySnapshot(querySnapshot);
|
||||
arguments.put("handle", handle);
|
||||
|
||||
channel.invokeMethod("QuerySnapshot", arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private void addDefaultListeners(final String description, Task<Void> task, final Result result) {
|
||||
task.addOnSuccessListener(
|
||||
new OnSuccessListener<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void ignored) {
|
||||
result.success(null);
|
||||
}
|
||||
});
|
||||
task.addOnFailureListener(
|
||||
new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
result.error("Error performing " + description, e.getMessage(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(MethodCall call, final Result result) {
|
||||
switch (call.method) {
|
||||
case "Firestore#runTransaction":
|
||||
{
|
||||
final TaskCompletionSource<Map<String, Object>> transactionTCS =
|
||||
new TaskCompletionSource<>();
|
||||
final Task<Map<String, Object>> transactionTCSTask = transactionTCS.getTask();
|
||||
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
getFirestore(arguments)
|
||||
.runTransaction(
|
||||
new Transaction.Function<Map<String, Object>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Map<String, Object> apply(@NonNull Transaction transaction) {
|
||||
// Store transaction.
|
||||
int transactionId = (Integer) arguments.get("transactionId");
|
||||
transactions.append(transactionId, transaction);
|
||||
completionTasks.append(transactionId, transactionTCS);
|
||||
|
||||
// Start operations on Dart side.
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
channel.invokeMethod(
|
||||
"DoTransaction",
|
||||
arguments,
|
||||
new Result() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void success(Object doTransactionResult) {
|
||||
transactionTCS.trySetResult(
|
||||
(Map<String, Object>) doTransactionResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(
|
||||
String errorCode,
|
||||
String errorMessage,
|
||||
Object errorDetails) {
|
||||
transactionTCS.trySetException(
|
||||
new Exception("Do transaction failed."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
transactionTCS.trySetException(
|
||||
new Exception("DoTransaction not implemented"));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Wait till transaction is complete.
|
||||
try {
|
||||
String timeoutKey = "transactionTimeout";
|
||||
long timeout = ((Number) arguments.get(timeoutKey)).longValue();
|
||||
final Map<String, Object> transactionResult =
|
||||
Tasks.await(transactionTCSTask, timeout, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Once transaction completes return the result to the Dart side.
|
||||
return transactionResult;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
result.error("Error performing transaction", e.getMessage(), null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.addOnCompleteListener(
|
||||
new OnCompleteListener<Map<String, Object>>() {
|
||||
@Override
|
||||
public void onComplete(Task<Map<String, Object>> task) {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(task.getResult());
|
||||
} else {
|
||||
result.error(
|
||||
"Error performing transaction", task.getException().getMessage(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "Transaction#get":
|
||||
{
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
final Transaction transaction = getTransaction(arguments);
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
try {
|
||||
DocumentSnapshot documentSnapshot =
|
||||
transaction.get(getDocumentReference(arguments));
|
||||
final Map<String, Object> snapshotMap = new HashMap<>();
|
||||
snapshotMap.put("path", documentSnapshot.getReference().getPath());
|
||||
if (documentSnapshot.exists()) {
|
||||
snapshotMap.put("data", documentSnapshot.getData());
|
||||
} else {
|
||||
snapshotMap.put("data", null);
|
||||
}
|
||||
Map<String, Object> metadata = new HashMap();
|
||||
metadata.put("hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites());
|
||||
metadata.put("isFromCache", documentSnapshot.getMetadata().isFromCache());
|
||||
snapshotMap.put("metadata", metadata);
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(snapshotMap);
|
||||
}
|
||||
});
|
||||
} catch (final FirebaseFirestoreException e) {
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.error("Error performing Transaction#get", e.getMessage(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
break;
|
||||
}
|
||||
case "Transaction#update":
|
||||
{
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
final Transaction transaction = getTransaction(arguments);
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
Map<String, Object> data = (Map<String, Object>) arguments.get("data");
|
||||
try {
|
||||
transaction.update(getDocumentReference(arguments), data);
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(null);
|
||||
}
|
||||
});
|
||||
} catch (final IllegalStateException e) {
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.error("Error performing Transaction#update", e.getMessage(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
break;
|
||||
}
|
||||
case "Transaction#set":
|
||||
{
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
final Transaction transaction = getTransaction(arguments);
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
Map<String, Object> data = (Map<String, Object>) arguments.get("data");
|
||||
transaction.set(getDocumentReference(arguments), data);
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "sending set success");
|
||||
result.success(null);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
break;
|
||||
}
|
||||
case "Transaction#delete":
|
||||
{
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
final Transaction transaction = getTransaction(arguments);
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
transaction.delete(getDocumentReference(arguments));
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(null);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
break;
|
||||
}
|
||||
case "WriteBatch#create":
|
||||
{
|
||||
int handle = nextBatchHandle++;
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
WriteBatch batch = getFirestore(arguments).batch();
|
||||
batches.put(handle, batch);
|
||||
result.success(handle);
|
||||
break;
|
||||
}
|
||||
case "WriteBatch#setData":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = (Integer) arguments.get("handle");
|
||||
DocumentReference reference = getDocumentReference(arguments);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> options = (Map<String, Object>) arguments.get("options");
|
||||
WriteBatch batch = batches.get(handle);
|
||||
if (options != null && (boolean) options.get("merge")) {
|
||||
batch.set(reference, arguments.get("data"), SetOptions.merge());
|
||||
} else {
|
||||
batch.set(reference, arguments.get("data"));
|
||||
}
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
case "WriteBatch#updateData":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = (Integer) arguments.get("handle");
|
||||
DocumentReference reference = getDocumentReference(arguments);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> data = (Map<String, Object>) arguments.get("data");
|
||||
WriteBatch batch = batches.get(handle);
|
||||
batch.update(reference, data);
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
case "WriteBatch#delete":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = (Integer) arguments.get("handle");
|
||||
DocumentReference reference = getDocumentReference(arguments);
|
||||
WriteBatch batch = batches.get(handle);
|
||||
batch.delete(reference);
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
case "WriteBatch#commit":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = (Integer) arguments.get("handle");
|
||||
WriteBatch batch = batches.get(handle);
|
||||
Task<Void> task = batch.commit();
|
||||
batches.delete(handle);
|
||||
addDefaultListeners("commit", task, result);
|
||||
break;
|
||||
}
|
||||
case "Query#addSnapshotListener":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = nextListenerHandle++;
|
||||
EventObserver observer = new EventObserver(handle);
|
||||
observers.put(handle, observer);
|
||||
listenerRegistrations.put(handle, getQuery(arguments).addSnapshotListener(observer));
|
||||
result.success(handle);
|
||||
break;
|
||||
}
|
||||
case "Query#addDocumentListener":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = nextListenerHandle++;
|
||||
DocumentObserver observer = new DocumentObserver(handle);
|
||||
documentObservers.put(handle, observer);
|
||||
listenerRegistrations.put(
|
||||
handle, getDocumentReference(arguments).addSnapshotListener(observer));
|
||||
result.success(handle);
|
||||
break;
|
||||
}
|
||||
case "Query#removeListener":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
int handle = (Integer) arguments.get("handle");
|
||||
listenerRegistrations.get(handle).remove();
|
||||
listenerRegistrations.remove(handle);
|
||||
observers.remove(handle);
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
case "Query#getDocuments":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
Query query = getQuery(arguments);
|
||||
Source source = getSource(arguments);
|
||||
Task<QuerySnapshot> task = query.get(source);
|
||||
task.addOnSuccessListener(
|
||||
new OnSuccessListener<QuerySnapshot>() {
|
||||
@Override
|
||||
public void onSuccess(QuerySnapshot querySnapshot) {
|
||||
result.success(parseQuerySnapshot(querySnapshot));
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(
|
||||
new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
result.error("Error performing getDocuments", e.getMessage(), null);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "DocumentReference#setData":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
DocumentReference documentReference = getDocumentReference(arguments);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> options = (Map<String, Object>) arguments.get("options");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> data = (Map<String, Object>) arguments.get("data");
|
||||
Task<Void> task;
|
||||
if (options != null && (boolean) options.get("merge")) {
|
||||
task = documentReference.set(data, SetOptions.merge());
|
||||
} else {
|
||||
task = documentReference.set(data);
|
||||
}
|
||||
addDefaultListeners("setData", task, result);
|
||||
break;
|
||||
}
|
||||
case "DocumentReference#updateData":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
DocumentReference documentReference = getDocumentReference(arguments);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> data = (Map<String, Object>) arguments.get("data");
|
||||
Task<Void> task = documentReference.update(data);
|
||||
addDefaultListeners("updateData", task, result);
|
||||
break;
|
||||
}
|
||||
case "DocumentReference#get":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
DocumentReference documentReference = getDocumentReference(arguments);
|
||||
Source source = getSource(arguments);
|
||||
Task<DocumentSnapshot> task = documentReference.get(source);
|
||||
task.addOnSuccessListener(
|
||||
new OnSuccessListener<DocumentSnapshot>() {
|
||||
@Override
|
||||
public void onSuccess(DocumentSnapshot documentSnapshot) {
|
||||
Map<String, Object> snapshotMap = new HashMap<>();
|
||||
Map<String, Object> metadata = new HashMap<>();
|
||||
metadata.put(
|
||||
"hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites());
|
||||
metadata.put("isFromCache", documentSnapshot.getMetadata().isFromCache());
|
||||
snapshotMap.put("metadata", metadata);
|
||||
snapshotMap.put("path", documentSnapshot.getReference().getPath());
|
||||
if (documentSnapshot.exists()) {
|
||||
snapshotMap.put("data", documentSnapshot.getData());
|
||||
} else {
|
||||
snapshotMap.put("data", null);
|
||||
}
|
||||
result.success(snapshotMap);
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(
|
||||
new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
result.error("Error performing get", e.getMessage(), null);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "DocumentReference#delete":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
DocumentReference documentReference = getDocumentReference(arguments);
|
||||
Task<Void> task = documentReference.delete();
|
||||
addDefaultListeners("delete", task, result);
|
||||
break;
|
||||
}
|
||||
case "Firestore#enablePersistence":
|
||||
{
|
||||
Map<String, Object> arguments = call.arguments();
|
||||
boolean enable = (boolean) arguments.get("enable");
|
||||
FirebaseFirestoreSettings.Builder builder = new FirebaseFirestoreSettings.Builder();
|
||||
builder.setPersistenceEnabled(enable);
|
||||
FirebaseFirestoreSettings settings = builder.build();
|
||||
getFirestore(arguments).setFirestoreSettings(settings);
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
case "Firestore#settings":
|
||||
{
|
||||
final Map<String, Object> arguments = call.arguments();
|
||||
final FirebaseFirestoreSettings.Builder builder = new FirebaseFirestoreSettings.Builder();
|
||||
|
||||
if (arguments.get("persistenceEnabled") != null) {
|
||||
builder.setPersistenceEnabled((boolean) arguments.get("persistenceEnabled"));
|
||||
}
|
||||
|
||||
if (arguments.get("host") != null) {
|
||||
builder.setHost((String) arguments.get("host"));
|
||||
}
|
||||
|
||||
if (arguments.get("sslEnabled") != null) {
|
||||
builder.setSslEnabled((boolean) arguments.get("sslEnabled"));
|
||||
}
|
||||
|
||||
if (arguments.get("timestampsInSnapshotsEnabled") != null) {
|
||||
builder.setTimestampsInSnapshotsEnabled(
|
||||
(boolean) arguments.get("timestampsInSnapshotsEnabled"));
|
||||
}
|
||||
|
||||
if (arguments.get("cacheSizeBytes") != null) {
|
||||
builder.setCacheSizeBytes(((Integer) arguments.get("cacheSizeBytes")).longValue());
|
||||
}
|
||||
|
||||
FirebaseFirestoreSettings settings = builder.build();
|
||||
getFirestore(arguments).setFirestoreSettings(settings);
|
||||
result.success(null);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
result.notImplemented();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class FirestoreMessageCodec extends StandardMessageCodec {
|
||||
public static final FirestoreMessageCodec INSTANCE = new FirestoreMessageCodec();
|
||||
private static final Charset UTF8 = Charset.forName("UTF8");
|
||||
private static final byte DATE_TIME = (byte) 128;
|
||||
private static final byte GEO_POINT = (byte) 129;
|
||||
private static final byte DOCUMENT_REFERENCE = (byte) 130;
|
||||
private static final byte BLOB = (byte) 131;
|
||||
private static final byte ARRAY_UNION = (byte) 132;
|
||||
private static final byte ARRAY_REMOVE = (byte) 133;
|
||||
private static final byte DELETE = (byte) 134;
|
||||
private static final byte SERVER_TIMESTAMP = (byte) 135;
|
||||
private static final byte TIMESTAMP = (byte) 136;
|
||||
private static final byte INCREMENT_DOUBLE = (byte) 137;
|
||||
private static final byte INCREMENT_INTEGER = (byte) 138;
|
||||
|
||||
@Override
|
||||
protected void writeValue(ByteArrayOutputStream stream, Object value) {
|
||||
if (value instanceof Date) {
|
||||
stream.write(DATE_TIME);
|
||||
writeLong(stream, ((Date) value).getTime());
|
||||
} else if (value instanceof Timestamp) {
|
||||
stream.write(TIMESTAMP);
|
||||
writeLong(stream, ((Timestamp) value).getSeconds());
|
||||
writeInt(stream, ((Timestamp) value).getNanoseconds());
|
||||
} else if (value instanceof GeoPoint) {
|
||||
stream.write(GEO_POINT);
|
||||
writeAlignment(stream, 8);
|
||||
writeDouble(stream, ((GeoPoint) value).getLatitude());
|
||||
writeDouble(stream, ((GeoPoint) value).getLongitude());
|
||||
} else if (value instanceof DocumentReference) {
|
||||
stream.write(DOCUMENT_REFERENCE);
|
||||
writeBytes(
|
||||
stream, ((DocumentReference) value).getFirestore().getApp().getName().getBytes(UTF8));
|
||||
writeBytes(stream, ((DocumentReference) value).getPath().getBytes(UTF8));
|
||||
} else if (value instanceof Blob) {
|
||||
stream.write(BLOB);
|
||||
writeBytes(stream, ((Blob) value).toBytes());
|
||||
} else {
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object readValueOfType(byte type, ByteBuffer buffer) {
|
||||
switch (type) {
|
||||
case DATE_TIME:
|
||||
return new Date(buffer.getLong());
|
||||
case TIMESTAMP:
|
||||
return new Timestamp(buffer.getLong(), buffer.getInt());
|
||||
case GEO_POINT:
|
||||
readAlignment(buffer, 8);
|
||||
return new GeoPoint(buffer.getDouble(), buffer.getDouble());
|
||||
case DOCUMENT_REFERENCE:
|
||||
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);
|
||||
case BLOB:
|
||||
final byte[] bytes = readBytes(buffer);
|
||||
return Blob.fromBytes(bytes);
|
||||
case ARRAY_UNION:
|
||||
return FieldValue.arrayUnion(toArray(readValue(buffer)));
|
||||
case ARRAY_REMOVE:
|
||||
return FieldValue.arrayRemove(toArray(readValue(buffer)));
|
||||
case DELETE:
|
||||
return FieldValue.delete();
|
||||
case SERVER_TIMESTAMP:
|
||||
return FieldValue.serverTimestamp();
|
||||
case INCREMENT_INTEGER:
|
||||
final Number integerIncrementValue = (Number) readValue(buffer);
|
||||
return FieldValue.increment(integerIncrementValue.intValue());
|
||||
case INCREMENT_DOUBLE:
|
||||
final Number doubleIncrementValue = (Number) readValue(buffer);
|
||||
return FieldValue.increment(doubleIncrementValue.doubleValue());
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private Object[] toArray(Object source) {
|
||||
if (source instanceof List) {
|
||||
return ((List) source).toArray();
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
String sourceType = source.getClass().getCanonicalName();
|
||||
String message = "java.util.List was expected, unable to convert '%s' to an object array";
|
||||
throw new IllegalArgumentException(String.format(message, sourceType));
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package io.flutter.plugins.firebase.cloudfirestore;
|
||||
|
||||
import com.google.firebase.components.Component;
|
||||
import com.google.firebase.components.ComponentRegistrar;
|
||||
import com.google.firebase.platforminfo.LibraryVersionComponent;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FlutterFirebaseAppRegistrar implements ComponentRegistrar {
|
||||
private static final String LIBRARY_NAME = "flutter-fire-fst";
|
||||
private static final String LIBRARY_VERSION = "0.12.5";
|
||||
|
||||
@Override
|
||||
public List<Component<?>> getComponents() {
|
||||
return Collections.<Component<?>>singletonList(
|
||||
LibraryVersionComponent.create(LIBRARY_NAME, LIBRARY_VERSION));
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
cloud_firestore=/Volumes/D1/dev/flutter/google-oem-plugins/packages/cloud_firestore/
|
||||
firebase_core=/Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-0.4.0+3/
|
|
@ -1,64 +0,0 @@
|
|||
# Generated by pub on 2019-06-10 21:12:02.134413.
|
||||
analyzer:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-0.36.3/lib/
|
||||
args:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/args-1.5.2/lib/
|
||||
async:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.2.0/lib/
|
||||
boolean_selector:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.4/lib/
|
||||
charcode:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.2/lib/
|
||||
cloud_firestore:../lib/
|
||||
collection:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.14.11/lib/
|
||||
convert:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/convert-2.1.1/lib/
|
||||
crypto:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/crypto-2.0.6/lib/
|
||||
csslib:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/csslib-0.16.0/lib/
|
||||
file:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/file-5.0.8/lib/
|
||||
firebase_core:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-0.4.0+3/lib/
|
||||
flutter:file:///Users/j3g/apps/flutter/packages/flutter/lib/
|
||||
flutter_driver:file:///Users/j3g/apps/flutter/packages/flutter_driver/lib/
|
||||
flutter_test:file:///Users/j3g/apps/flutter/packages/flutter_test/lib/
|
||||
front_end:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/front_end-0.1.18/lib/
|
||||
fuchsia_remote_debug_protocol:file:///Users/j3g/apps/flutter/packages/fuchsia_remote_debug_protocol/lib/
|
||||
glob:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/glob-1.1.7/lib/
|
||||
html:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/html-0.14.0+2/lib/
|
||||
http:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.12.0+2/lib/
|
||||
http_multi_server:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/http_multi_server-2.1.0/lib/
|
||||
http_parser:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.3/lib/
|
||||
intl:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/intl-0.15.8/lib/
|
||||
io:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/
|
||||
js:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.1+1/lib/
|
||||
json_rpc_2:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/json_rpc_2-2.1.0/lib/
|
||||
kernel:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/kernel-0.3.18/lib/
|
||||
matcher:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.5/lib/
|
||||
meta:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.1.6/lib/
|
||||
mime:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/mime-0.9.6+3/lib/
|
||||
multi_server_socket:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/multi_server_socket-1.0.2/lib/
|
||||
node_preamble:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/node_preamble-1.4.4/lib/
|
||||
package_config:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/package_config-1.0.5/lib/
|
||||
package_resolver:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/package_resolver-1.0.10/lib/
|
||||
path:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.6.2/lib/
|
||||
pedantic:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.7.0/lib/
|
||||
platform:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/platform-2.2.0/lib/
|
||||
pool:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/pool-1.4.0/lib/
|
||||
process:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/process-3.0.9/lib/
|
||||
pub_semver:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.4.2/lib/
|
||||
quiver:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/quiver-2.0.3/lib/
|
||||
shelf:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/shelf-0.7.5/lib/
|
||||
shelf_packages_handler:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_packages_handler-1.0.4/lib/
|
||||
shelf_static:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_static-0.2.8/lib/
|
||||
shelf_web_socket:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.3/lib/
|
||||
sky_engine:file:///Users/j3g/apps/flutter/bin/cache/pkg/sky_engine/lib/
|
||||
source_map_stack_trace:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-1.1.5/lib/
|
||||
source_maps:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.8/lib/
|
||||
source_span:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/
|
||||
stack_trace:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/
|
||||
stream_channel:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/
|
||||
string_scanner:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.4/lib/
|
||||
term_glyph:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/
|
||||
test:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/test-1.6.3/lib/
|
||||
test_api:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.5/lib/
|
||||
test_core:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/test_core-0.2.5/lib/
|
||||
typed_data:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.6/lib/
|
||||
vector_math:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.0.8/lib/
|
||||
vm_service_client:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/vm_service_client-0.2.6+2/lib/
|
||||
watcher:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/watcher-0.9.7+10/lib/
|
||||
web_socket_channel:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.0.13/lib/
|
||||
yaml:file:///Users/j3g/apps/flutter/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.15/lib/
|
||||
firestore_example:lib/
|
|
@ -1,8 +0,0 @@
|
|||
# firestore_example
|
||||
|
||||
Demonstrates how to use the firestore plugin.
|
||||
|
||||
## Getting Started
|
||||
|
||||
For help getting started with Flutter, view our online
|
||||
[documentation](http://flutter.io/).
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/android">
|
||||
<sourceFolder url="file://$MODULE_DIR$/android/app/src/main/java" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,63 +0,0 @@
|
|||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'io.flutter.plugins.firebase.firestoreexample'
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "159623150305",
|
||||
"firebase_url": "https://flutter-firebase-plugins.firebaseio.com",
|
||||
"project_id": "flutter-firebase-plugins",
|
||||
"storage_bucket": "flutter-firebase-plugins.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:159623150305:android:236f9daea101f77e",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.firestoreexample"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "159623150305-q05bbbtsutr02abhips3suj7hujfk4bg.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyChk3KEG7QYrs4kQPLP1tjJNxBTbfCAdgg"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"analytics_service": {
|
||||
"status": 1
|
||||
},
|
||||
"appinvite_service": {
|
||||
"status": 1,
|
||||
"other_platform_oauth_client": []
|
||||
},
|
||||
"ads_service": {
|
||||
"status": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
|
@ -1,5 +0,0 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
|
@ -1,19 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.flutter.plugins.firebase.firestoreexample">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application android:name="io.flutter.app.FlutterApplication" android:label="firestore_example" android:icon="@mipmap/ic_launcher">
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
|
@ -1,27 +0,0 @@
|
|||
package io.flutter.plugins;
|
||||
|
||||
import io.flutter.plugin.common.PluginRegistry;
|
||||
import io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin;
|
||||
import io.flutter.plugins.firebase.core.FirebaseCorePlugin;
|
||||
|
||||
/**
|
||||
* Generated file. Do not edit.
|
||||
*/
|
||||
public final class GeneratedPluginRegistrant {
|
||||
public static void registerWith(PluginRegistry registry) {
|
||||
if (alreadyRegisteredWith(registry)) {
|
||||
return;
|
||||
}
|
||||
CloudFirestorePlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin"));
|
||||
FirebaseCorePlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebase.core.FirebaseCorePlugin"));
|
||||
}
|
||||
|
||||
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
|
||||
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
|
||||
if (registry.hasPlugin(key)) {
|
||||
return true;
|
||||
}
|
||||
registry.registrarFor(key);
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.plugins.firebase.firestoreexample;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.plugins.firebasedatabaseexample;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 721 B |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1,32 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = '../build'
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
|
@ -1,5 +0,0 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
|
@ -1,2 +0,0 @@
|
|||
sdk.dir=/usr/local/opt/android-sdk
|
||||
flutter.sdk=/Users/j3g/apps/flutter
|
|
@ -1,15 +0,0 @@
|
|||
include ':app'
|
||||
|
||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withInputStream { stream -> plugins.load(stream) }
|
||||
}
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="FLUTTER_MODULE_TYPE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="application" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,2 +0,0 @@
|
|||
#include "Generated.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
|
@ -1,7 +0,0 @@
|
|||
// This is a generated file; do not edit or check into version control.
|
||||
FLUTTER_ROOT=/Users/j3g/apps/flutter
|
||||
FLUTTER_APPLICATION_PATH=/Volumes/D1/dev/flutter/google-oem-plugins/packages/cloud_firestore/example
|
||||
FLUTTER_TARGET=lib/main.dart
|
||||
FLUTTER_BUILD_DIR=build
|
||||
SYMROOT=${SOURCE_ROOT}/../build/ios
|
||||
FLUTTER_FRAMEWORK_DIR=/Users/j3g/apps/flutter/bin/cache/artifacts/engine/ios
|
|
@ -1,2 +0,0 @@
|
|||
#include "Generated.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
|
@ -1,72 +0,0 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def parse_KV_file(file, separator='=')
|
||||
file_abs_path = File.expand_path(file)
|
||||
if !File.exists? file_abs_path
|
||||
return [];
|
||||
end
|
||||
pods_ary = []
|
||||
skip_line_start_symbols = ["#", "/"]
|
||||
File.foreach(file_abs_path) { |line|
|
||||
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
|
||||
plugin = line.split(pattern=separator)
|
||||
if plugin.length == 2
|
||||
podname = plugin[0].strip()
|
||||
path = plugin[1].strip()
|
||||
podpath = File.expand_path("#{path}", file_abs_path)
|
||||
pods_ary.push({:name => podname, :path => podpath});
|
||||
else
|
||||
puts "Invalid plugin specification: #{line}"
|
||||
end
|
||||
}
|
||||
return pods_ary
|
||||
end
|
||||
|
||||
target 'Runner' do
|
||||
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
|
||||
# referring to absolute paths on developers' machines.
|
||||
system('rm -rf .symlinks')
|
||||
system('mkdir -p .symlinks/plugins')
|
||||
|
||||
# Flutter Pods
|
||||
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
|
||||
if generated_xcode_build_settings.empty?
|
||||
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
|
||||
end
|
||||
generated_xcode_build_settings.map { |p|
|
||||
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
|
||||
symlink = File.join('.symlinks', 'flutter')
|
||||
File.symlink(File.dirname(p[:path]), symlink)
|
||||
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
|
||||
end
|
||||
}
|
||||
|
||||
# Plugin Pods
|
||||
plugin_pods = parse_KV_file('../.flutter-plugins')
|
||||
plugin_pods.map { |p|
|
||||
symlink = File.join('.symlinks', 'plugins', p[:name])
|
||||
File.symlink(p[:path], symlink)
|
||||
pod p[:name], :path => File.join(symlink, 'ios')
|
||||
}
|
||||
end
|
||||
|
||||
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
|
||||
install! 'cocoapods', :disable_input_output_paths => true
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,500 +0,0 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
5C6F5A711EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */; };
|
||||
7A1ECC911E8EDB6900309407 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A1ECC901E8EDB6900309407 /* GoogleService-Info.plist */; };
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
|
||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
CE57DC9C9240FBD15E358E24 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E13AAF33B0B411D7B2D38642 /* libPods-Runner.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
|
||||
5C6F5A6F1EC3CCCC008D64B5 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
7A1ECC901E8EDB6900309407 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E13AAF33B0B411D7B2D38642 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
|
||||
CE57DC9C9240FBD15E358E24 /* libPods-Runner.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
840012C8B5EDBCF56B0E4AC1 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B80C3931E831B6300D905FE /* App.framework */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
840012C8B5EDBCF56B0E4AC1 /* Pods */,
|
||||
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5C6F5A6F1EC3CCCC008D64B5 /* GeneratedPluginRegistrant.h */,
|
||||
5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */,
|
||||
7A1ECC901E8EDB6900309407 /* GoogleService-Info.plist */,
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
97C146F11CF9000F007C117D /* Supporting Files */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F11CF9000F007C117D /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146F21CF9000F007C117D /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E13AAF33B0B411D7B2D38642 /* libPods-Runner.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */,
|
||||
532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0830;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7A1ECC911E8EDB6900309407 /* GoogleService-Info.plist in Resources */,
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
|
||||
};
|
||||
532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */,
|
||||
5C6F5A711EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = arm64;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firestoreExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = arm64;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firestoreExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -1,91 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,10 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : FlutterAppDelegate
|
||||
|
||||
@end
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "AppDelegate.h"
|
||||
#include "GeneratedPluginRegistrant.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[GeneratedPluginRegistrant registerWithRegistry:self];
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,116 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 564 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.5 KiB |
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Flutter View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#ifndef GeneratedPluginRegistrant_h
|
||||
#define GeneratedPluginRegistrant_h
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface GeneratedPluginRegistrant : NSObject
|
||||
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
|
||||
@end
|
||||
|
||||
#endif /* GeneratedPluginRegistrant_h */
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#import "GeneratedPluginRegistrant.h"
|
||||
#import <cloud_firestore/CloudFirestorePlugin.h>
|
||||
#import <firebase_core/FirebaseCorePlugin.h>
|
||||
|
||||
@implementation GeneratedPluginRegistrant
|
||||
|
||||
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
|
||||
[FLTCloudFirestorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTCloudFirestorePlugin"]];
|
||||
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AD_UNIT_ID_FOR_BANNER_TEST</key>
|
||||
<string>ca-app-pub-3940256099942544/2934735716</string>
|
||||
<key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key>
|
||||
<string>ca-app-pub-3940256099942544/4411468910</string>
|
||||
<key>CLIENT_ID</key>
|
||||
<string>159623150305-1iiqqggbff817a8bpnalo64nuc3qobid.apps.googleusercontent.com</string>
|
||||
<key>REVERSED_CLIENT_ID</key>
|
||||
<string>com.googleusercontent.apps.159623150305-1iiqqggbff817a8bpnalo64nuc3qobid</string>
|
||||
<key>API_KEY</key>
|
||||
<string>AIzaSyDyzecVw1zXTpBKwfFHxpl7QyYBhimNhUk</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>159623150305</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>io.flutter.plugins.firestoreExample</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>flutter-firebase-plugins</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>flutter-firebase-plugins.appspot.com</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:159623150305:ios:7e8aafdf0bd8d289</string>
|
||||
<key>DATABASE_URL</key>
|
||||
<string>https://flutter-firebase-plugins.firebaseio.com</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,49 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>firestore_example</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
final FirebaseApp app = await FirebaseApp.configure(
|
||||
name: 'test',
|
||||
options: const FirebaseOptions(
|
||||
googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd',
|
||||
gcmSenderID: '79601577497',
|
||||
apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU',
|
||||
projectID: 'flutter-firestore',
|
||||
),
|
||||
);
|
||||
final Firestore firestore = Firestore(app: app);
|
||||
await firestore.settings(timestampsInSnapshotsEnabled: true);
|
||||
|
||||
runApp(MaterialApp(
|
||||
title: 'Firestore Example', home: MyHomePage(firestore: firestore)));
|
||||
}
|
||||
|
||||
class MessageList extends StatelessWidget {
|
||||
MessageList({this.firestore});
|
||||
|
||||
final Firestore firestore;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<QuerySnapshot>(
|
||||
stream: firestore.collection('messages').snapshots(),
|
||||
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
|
||||
if (!snapshot.hasData) return const Text('Loading...');
|
||||
final int messageCount = snapshot.data.documents.length;
|
||||
return ListView.builder(
|
||||
itemCount: messageCount,
|
||||
itemBuilder: (_, int index) {
|
||||
final DocumentSnapshot document = snapshot.data.documents[index];
|
||||
return ListTile(
|
||||
title: Text(document['message'] ?? '<No message retrieved>'),
|
||||
subtitle: Text('Message ${index + 1} of $messageCount'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatelessWidget {
|
||||
MyHomePage({this.firestore});
|
||||
final Firestore firestore;
|
||||
CollectionReference get messages => firestore.collection('messages');
|
||||
|
||||
Future<void> _addMessage() async {
|
||||
await messages.add(<String, dynamic>{
|
||||
'message': 'Hello world!',
|
||||
'created_at': FieldValue.serverTimestamp(),
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Firestore Example'),
|
||||
),
|
||||
body: MessageList(firestore: firestore),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _addMessage,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,430 +0,0 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.36.3"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
cloud_firestore:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.12.5"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.14.11"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.8"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0+3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_driver:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
front_end:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: front_end
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.18"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.7"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.0+2"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.0+2"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.15.8"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.3"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.1+1"
|
||||
json_rpc_2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_rpc_2
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
kernel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: kernel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.18"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.5"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.6"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.6+3"
|
||||
multi_server_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: multi_server_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.4"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
package_resolver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_resolver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.10"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.2"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.5"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.8"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.8"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.5"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.3"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.3"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.5"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.5"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.6"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
vm_service_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service_client
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.6+2"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.7+10"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.13"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.15"
|
||||
sdks:
|
||||
dart: ">=2.2.0 <3.0.0"
|
||||
flutter: ">=1.5.0 <2.0.0"
|
|
@ -1,17 +0,0 @@
|
|||
name: firestore_example
|
||||
description: Demonstrates how to use the firestore plugin.
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cloud_firestore:
|
||||
path: ../
|
||||
firebase_core: "^0.4.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
test: any
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
|
@ -1,192 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter_driver/driver_extension.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
|
||||
void main() {
|
||||
final Completer<String> completer = Completer<String>();
|
||||
enableFlutterDriverExtension(handler: (_) => completer.future);
|
||||
tearDownAll(() => completer.complete(null));
|
||||
|
||||
group('$Firestore', () {
|
||||
Firestore firestore;
|
||||
Firestore firestoreWithSettings;
|
||||
|
||||
setUp(() async {
|
||||
final FirebaseOptions firebaseOptions = const FirebaseOptions(
|
||||
googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd',
|
||||
gcmSenderID: '79601577497',
|
||||
apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU',
|
||||
projectID: 'flutter-firestore',
|
||||
);
|
||||
final FirebaseApp app = await FirebaseApp.configure(
|
||||
name: 'test',
|
||||
options: firebaseOptions,
|
||||
);
|
||||
final FirebaseApp app2 = await FirebaseApp.configure(
|
||||
name: 'test2',
|
||||
options: firebaseOptions,
|
||||
);
|
||||
firestore = Firestore(app: app);
|
||||
firestoreWithSettings = Firestore(app: app2);
|
||||
await firestoreWithSettings.settings(
|
||||
persistenceEnabled: true,
|
||||
host: null,
|
||||
sslEnabled: true,
|
||||
timestampsInSnapshotsEnabled: true,
|
||||
cacheSizeBytes: 1048576,
|
||||
);
|
||||
});
|
||||
|
||||
test('getDocumentsWithFirestoreSettings', () async {
|
||||
final Query query = firestoreWithSettings.collection('messages').limit(1);
|
||||
final QuerySnapshot querySnapshot = await query.getDocuments();
|
||||
expect(querySnapshot.documents.length, 1);
|
||||
});
|
||||
|
||||
test('getDocumentsFromCollection', () async {
|
||||
final Query query = firestore
|
||||
.collection('messages')
|
||||
.where('message', isEqualTo: 'Hello world!')
|
||||
.limit(1);
|
||||
final QuerySnapshot querySnapshot = await query.getDocuments();
|
||||
expect(querySnapshot.documents.first['message'], 'Hello world!');
|
||||
final DocumentReference firstDoc =
|
||||
querySnapshot.documents.first.reference;
|
||||
final DocumentSnapshot documentSnapshot = await firstDoc.get();
|
||||
expect(documentSnapshot.data['message'], 'Hello world!');
|
||||
final DocumentSnapshot cachedSnapshot =
|
||||
await firstDoc.get(source: Source.cache);
|
||||
expect(cachedSnapshot.data['message'], 'Hello world!');
|
||||
final DocumentSnapshot snapshot = await firstDoc.snapshots().first;
|
||||
expect(snapshot.data['message'], 'Hello world!');
|
||||
});
|
||||
|
||||
test('getDocumentsFromCollectionGroup', () async {
|
||||
final Query query = firestore
|
||||
.collectionGroup('reviews')
|
||||
.where('stars', isEqualTo: 5)
|
||||
.limit(1);
|
||||
final QuerySnapshot querySnapshot = await query.getDocuments();
|
||||
expect(querySnapshot.documents.first['stars'], 5);
|
||||
});
|
||||
|
||||
test('increment', () async {
|
||||
final DocumentReference ref = firestore.collection('messages').document();
|
||||
await ref.setData(<String, dynamic>{
|
||||
'message': 1,
|
||||
'created_at': FieldValue.serverTimestamp(),
|
||||
});
|
||||
DocumentSnapshot snapshot = await ref.get();
|
||||
expect(snapshot.data['message'], 1);
|
||||
await ref.updateData(<String, dynamic>{
|
||||
'message': FieldValue.increment(1),
|
||||
});
|
||||
snapshot = await ref.get();
|
||||
expect(snapshot.data['message'], 2);
|
||||
await ref.updateData(<String, dynamic>{
|
||||
'message': FieldValue.increment(40.1),
|
||||
});
|
||||
snapshot = await ref.get();
|
||||
expect(snapshot.data['message'], 42.1);
|
||||
await ref.delete();
|
||||
});
|
||||
|
||||
test('runTransaction', () async {
|
||||
final DocumentReference ref = firestore.collection('messages').document();
|
||||
await ref.setData(<String, dynamic>{
|
||||
'message': 'testing',
|
||||
'created_at': FieldValue.serverTimestamp(),
|
||||
});
|
||||
final DocumentSnapshot initialSnapshot = await ref.get();
|
||||
expect(initialSnapshot.data['message'], 'testing');
|
||||
final dynamic result = await firestore.runTransaction(
|
||||
(Transaction tx) async {
|
||||
final DocumentSnapshot snapshot = await tx.get(ref);
|
||||
final Map<String, dynamic> updatedData =
|
||||
Map<String, dynamic>.from(snapshot.data);
|
||||
updatedData['message'] = 'testing2';
|
||||
await tx.update(ref, updatedData);
|
||||
return updatedData;
|
||||
},
|
||||
);
|
||||
expect(result['message'], 'testing2');
|
||||
await ref.delete();
|
||||
final DocumentSnapshot nonexistentSnapshot = await ref.get();
|
||||
expect(nonexistentSnapshot.data, null);
|
||||
expect(nonexistentSnapshot.exists, false);
|
||||
});
|
||||
|
||||
test('pagination', () async {
|
||||
// Populate the database with two test documents
|
||||
final CollectionReference messages = firestore.collection('messages');
|
||||
final DocumentReference doc1 = messages.document();
|
||||
// Use document ID as a unique identifier to ensure that we don't
|
||||
// collide with other tests running against this database.
|
||||
final String testRun = doc1.documentID;
|
||||
await doc1.setData(<String, dynamic>{
|
||||
'message': 'pagination testing1',
|
||||
'test_run': testRun,
|
||||
'created_at': FieldValue.serverTimestamp(),
|
||||
});
|
||||
final DocumentSnapshot snapshot1 = await doc1.get();
|
||||
final DocumentReference doc2 = messages.document();
|
||||
await doc2.setData(<String, dynamic>{
|
||||
'message': 'pagination testing2',
|
||||
'test_run': testRun,
|
||||
'created_at': FieldValue.serverTimestamp(),
|
||||
});
|
||||
final DocumentSnapshot snapshot2 = await doc2.get();
|
||||
|
||||
QuerySnapshot snapshot;
|
||||
List<DocumentSnapshot> results;
|
||||
|
||||
// startAtDocument
|
||||
snapshot = await messages
|
||||
.orderBy('created_at')
|
||||
.where('test_run', isEqualTo: testRun)
|
||||
.startAtDocument(snapshot1)
|
||||
.getDocuments();
|
||||
results = snapshot.documents;
|
||||
expect(results.length, 2);
|
||||
expect(results[0].data['message'], 'pagination testing1');
|
||||
expect(results[1].data['message'], 'pagination testing2');
|
||||
|
||||
// startAfterDocument
|
||||
snapshot = await messages
|
||||
.orderBy('created_at')
|
||||
.where('test_run', isEqualTo: testRun)
|
||||
.startAfterDocument(snapshot1)
|
||||
.getDocuments();
|
||||
results = snapshot.documents;
|
||||
expect(results.length, 1);
|
||||
expect(results[0].data['message'], 'pagination testing2');
|
||||
|
||||
// endAtDocument
|
||||
snapshot = await messages
|
||||
.orderBy('created_at')
|
||||
.where('test_run', isEqualTo: testRun)
|
||||
.endAtDocument(snapshot2)
|
||||
.getDocuments();
|
||||
results = snapshot.documents;
|
||||
expect(results.length, 2);
|
||||
expect(results[0].data['message'], 'pagination testing1');
|
||||
expect(results[1].data['message'], 'pagination testing2');
|
||||
|
||||
// endBeforeDocument
|
||||
snapshot = await messages
|
||||
.orderBy('created_at')
|
||||
.where('test_run', isEqualTo: testRun)
|
||||
.endBeforeDocument(snapshot2)
|
||||
.getDocuments();
|
||||
results = snapshot.documents;
|
||||
expect(results.length, 1);
|
||||
expect(results[0].data['message'], 'pagination testing1');
|
||||
|
||||
// Clean up
|
||||
await doc1.delete();
|
||||
await doc2.delete();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
|
||||
void main() async {
|
||||
final FlutterDriver driver = await FlutterDriver.connect();
|
||||
await driver.requestData(null, timeout: const Duration(minutes: 1));
|
||||
driver.close();
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface FLTCloudFirestorePlugin : NSObject <FlutterPlugin>
|
||||
@end
|
|
@ -1,653 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "CloudFirestorePlugin.h"
|
||||
|
||||
#import <Firebase/Firebase.h>
|
||||
|
||||
#define LIBRARY_NAME @"flutter-firebase_cloud_firestore"
|
||||
#define LIBRARY_VERSION @"0.12.5"
|
||||
|
||||
static FlutterError *getFlutterError(NSError *error) {
|
||||
if (error == nil) return nil;
|
||||
|
||||
return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code]
|
||||
message:error.domain
|
||||
details:error.localizedDescription];
|
||||
}
|
||||
|
||||
static FIRFirestore *getFirestore(NSDictionary *arguments) {
|
||||
FIRApp *app = [FIRApp appNamed:arguments[@"app"]];
|
||||
return [FIRFirestore firestoreForApp:app];
|
||||
}
|
||||
|
||||
static FIRDocumentReference *getDocumentReference(NSDictionary *arguments) {
|
||||
return [getFirestore(arguments) documentWithPath:arguments[@"path"]];
|
||||
}
|
||||
|
||||
static NSArray *getDocumentValues(NSDictionary *document, NSArray *orderBy,
|
||||
BOOL *isCollectionGroup) {
|
||||
NSMutableArray *values = [[NSMutableArray alloc] init];
|
||||
NSDictionary *documentData = document[@"data"];
|
||||
if (orderBy) {
|
||||
for (id item in orderBy) {
|
||||
NSArray *orderByParameters = item;
|
||||
NSString *fieldName = orderByParameters[0];
|
||||
[values addObject:[documentData objectForKey:fieldName]];
|
||||
}
|
||||
}
|
||||
if (isCollectionGroup) {
|
||||
NSString *path = document[@"path"];
|
||||
[values addObject:path];
|
||||
} else {
|
||||
NSString *documentId = document[@"id"];
|
||||
[values addObject:documentId];
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
static FIRQuery *getQuery(NSDictionary *arguments) {
|
||||
NSNumber *data = arguments[@"isCollectionGroup"];
|
||||
BOOL isCollectionGroup = data.boolValue;
|
||||
FIRQuery *query;
|
||||
if (isCollectionGroup) {
|
||||
query = [getFirestore(arguments) collectionGroupWithID:arguments[@"path"]];
|
||||
} else {
|
||||
query = [getFirestore(arguments) collectionWithPath:arguments[@"path"]];
|
||||
}
|
||||
NSDictionary *parameters = arguments[@"parameters"];
|
||||
NSArray *whereConditions = parameters[@"where"];
|
||||
for (id item in whereConditions) {
|
||||
NSArray *condition = item;
|
||||
NSString *fieldName = condition[0];
|
||||
NSString *op = condition[1];
|
||||
id value = condition[2];
|
||||
if ([op isEqualToString:@"=="]) {
|
||||
query = [query queryWhereField:fieldName isEqualTo:value];
|
||||
} else if ([op isEqualToString:@"<"]) {
|
||||
query = [query queryWhereField:fieldName isLessThan:value];
|
||||
} else if ([op isEqualToString:@"<="]) {
|
||||
query = [query queryWhereField:fieldName isLessThanOrEqualTo:value];
|
||||
} else if ([op isEqualToString:@">"]) {
|
||||
query = [query queryWhereField:fieldName isGreaterThan:value];
|
||||
} else if ([op isEqualToString:@">="]) {
|
||||
query = [query queryWhereField:fieldName isGreaterThanOrEqualTo:value];
|
||||
} else if ([op isEqualToString:@"array-contains"]) {
|
||||
query = [query queryWhereField:fieldName arrayContains:value];
|
||||
} else {
|
||||
// Unsupported operator
|
||||
}
|
||||
}
|
||||
id limit = parameters[@"limit"];
|
||||
if (limit) {
|
||||
NSNumber *length = limit;
|
||||
query = [query queryLimitedTo:[length intValue]];
|
||||
}
|
||||
NSArray *orderBy = parameters[@"orderBy"];
|
||||
if (orderBy) {
|
||||
for (NSArray *orderByParameters in orderBy) {
|
||||
NSString *fieldName = orderByParameters[0];
|
||||
NSNumber *descending = orderByParameters[1];
|
||||
query = [query queryOrderedByField:fieldName descending:[descending boolValue]];
|
||||
}
|
||||
}
|
||||
id startAt = parameters[@"startAt"];
|
||||
if (startAt) {
|
||||
NSArray *startAtValues = startAt;
|
||||
query = [query queryStartingAtValues:startAtValues];
|
||||
}
|
||||
id startAtDocument = parameters[@"startAtDocument"];
|
||||
if (startAtDocument) {
|
||||
NSArray *orderByParameters = [orderBy lastObject];
|
||||
NSNumber *descending = orderByParameters[1];
|
||||
query = [query queryOrderedByFieldPath:FIRFieldPath.documentID
|
||||
descending:[descending boolValue]];
|
||||
query = [query
|
||||
queryStartingAtValues:getDocumentValues(startAtDocument, orderBy, isCollectionGroup)];
|
||||
}
|
||||
id startAfter = parameters[@"startAfter"];
|
||||
if (startAfter) {
|
||||
NSArray *startAfterValues = startAfter;
|
||||
query = [query queryStartingAfterValues:startAfterValues];
|
||||
}
|
||||
id startAfterDocument = parameters[@"startAfterDocument"];
|
||||
if (startAfterDocument) {
|
||||
NSArray *orderByParameters = [orderBy lastObject];
|
||||
NSNumber *descending = orderByParameters[1];
|
||||
query = [query queryOrderedByFieldPath:FIRFieldPath.documentID
|
||||
descending:[descending boolValue]];
|
||||
query = [query
|
||||
queryStartingAfterValues:getDocumentValues(startAfterDocument, orderBy, isCollectionGroup)];
|
||||
}
|
||||
id endAt = parameters[@"endAt"];
|
||||
if (endAt) {
|
||||
NSArray *endAtValues = endAt;
|
||||
query = [query queryEndingAtValues:endAtValues];
|
||||
}
|
||||
id endAtDocument = parameters[@"endAtDocument"];
|
||||
if (endAtDocument) {
|
||||
NSArray *orderByParameters = [orderBy lastObject];
|
||||
NSNumber *descending = orderByParameters[1];
|
||||
query = [query queryOrderedByFieldPath:FIRFieldPath.documentID
|
||||
descending:[descending boolValue]];
|
||||
query =
|
||||
[query queryEndingAtValues:getDocumentValues(endAtDocument, orderBy, isCollectionGroup)];
|
||||
}
|
||||
id endBefore = parameters[@"endBefore"];
|
||||
if (endBefore) {
|
||||
NSArray *endBeforeValues = endBefore;
|
||||
query = [query queryEndingBeforeValues:endBeforeValues];
|
||||
}
|
||||
id endBeforeDocument = parameters[@"endBeforeDocument"];
|
||||
if (endBeforeDocument) {
|
||||
NSArray *orderByParameters = [orderBy lastObject];
|
||||
NSNumber *descending = orderByParameters[1];
|
||||
query = [query queryOrderedByFieldPath:FIRFieldPath.documentID
|
||||
descending:[descending boolValue]];
|
||||
query = [query
|
||||
queryEndingBeforeValues:getDocumentValues(endBeforeDocument, orderBy, isCollectionGroup)];
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
static FIRFirestoreSource getSource(NSDictionary *arguments) {
|
||||
NSString *source = arguments[@"source"];
|
||||
if ([@"server" isEqualToString:source]) {
|
||||
return FIRFirestoreSourceServer;
|
||||
}
|
||||
if ([@"cache" isEqualToString:source]) {
|
||||
return FIRFirestoreSourceCache;
|
||||
}
|
||||
return FIRFirestoreSourceDefault;
|
||||
}
|
||||
|
||||
static NSDictionary *parseQuerySnapshot(FIRQuerySnapshot *snapshot) {
|
||||
NSMutableArray *paths = [NSMutableArray array];
|
||||
NSMutableArray *documents = [NSMutableArray array];
|
||||
NSMutableArray *metadatas = [NSMutableArray array];
|
||||
for (FIRDocumentSnapshot *document in snapshot.documents) {
|
||||
[paths addObject:document.reference.path];
|
||||
[documents addObject:document.data];
|
||||
[metadatas addObject:@{
|
||||
@"hasPendingWrites" : @(document.metadata.hasPendingWrites),
|
||||
@"isFromCache" : @(document.metadata.isFromCache),
|
||||
}];
|
||||
}
|
||||
NSMutableArray *documentChanges = [NSMutableArray array];
|
||||
for (FIRDocumentChange *documentChange in snapshot.documentChanges) {
|
||||
NSString *type;
|
||||
switch (documentChange.type) {
|
||||
case FIRDocumentChangeTypeAdded:
|
||||
type = @"DocumentChangeType.added";
|
||||
break;
|
||||
case FIRDocumentChangeTypeModified:
|
||||
type = @"DocumentChangeType.modified";
|
||||
break;
|
||||
case FIRDocumentChangeTypeRemoved:
|
||||
type = @"DocumentChangeType.removed";
|
||||
break;
|
||||
}
|
||||
[documentChanges addObject:@{
|
||||
@"type" : type,
|
||||
@"document" : documentChange.document.data,
|
||||
@"path" : documentChange.document.reference.path,
|
||||
@"oldIndex" : [NSNumber numberWithUnsignedInteger:documentChange.oldIndex],
|
||||
@"newIndex" : [NSNumber numberWithUnsignedInteger:documentChange.newIndex],
|
||||
@"metadata" : @{
|
||||
@"hasPendingWrites" : @(documentChange.document.metadata.hasPendingWrites),
|
||||
@"isFromCache" : @(documentChange.document.metadata.isFromCache),
|
||||
},
|
||||
}];
|
||||
}
|
||||
return @{
|
||||
@"paths" : paths,
|
||||
@"documentChanges" : documentChanges,
|
||||
@"documents" : documents,
|
||||
@"metadatas" : metadatas,
|
||||
};
|
||||
}
|
||||
|
||||
const UInt8 DATE_TIME = 128;
|
||||
const UInt8 GEO_POINT = 129;
|
||||
const UInt8 DOCUMENT_REFERENCE = 130;
|
||||
const UInt8 BLOB = 131;
|
||||
const UInt8 ARRAY_UNION = 132;
|
||||
const UInt8 ARRAY_REMOVE = 133;
|
||||
const UInt8 DELETE = 134;
|
||||
const UInt8 SERVER_TIMESTAMP = 135;
|
||||
const UInt8 TIMESTAMP = 136;
|
||||
const UInt8 INCREMENT_DOUBLE = 137;
|
||||
const UInt8 INCREMENT_INTEGER = 138;
|
||||
|
||||
@interface FirestoreWriter : FlutterStandardWriter
|
||||
- (void)writeValue:(id)value;
|
||||
@end
|
||||
|
||||
@implementation FirestoreWriter : FlutterStandardWriter
|
||||
- (void)writeValue:(id)value {
|
||||
if ([value isKindOfClass:[NSDate class]]) {
|
||||
[self writeByte:DATE_TIME];
|
||||
NSDate *date = value;
|
||||
NSTimeInterval time = date.timeIntervalSince1970;
|
||||
SInt64 ms = (SInt64)(time * 1000.0);
|
||||
[self writeBytes:&ms length:8];
|
||||
} else if ([value isKindOfClass:[FIRTimestamp class]]) {
|
||||
FIRTimestamp *timestamp = value;
|
||||
SInt64 seconds = timestamp.seconds;
|
||||
int nanoseconds = timestamp.nanoseconds;
|
||||
[self writeByte:TIMESTAMP];
|
||||
[self writeBytes:(UInt8 *)&seconds length:8];
|
||||
[self writeBytes:(UInt8 *)&nanoseconds length:4];
|
||||
} else if ([value isKindOfClass:[FIRGeoPoint class]]) {
|
||||
FIRGeoPoint *geoPoint = value;
|
||||
Float64 latitude = geoPoint.latitude;
|
||||
Float64 longitude = geoPoint.longitude;
|
||||
[self writeByte:GEO_POINT];
|
||||
[self writeAlignment:8];
|
||||
[self writeBytes:(UInt8 *)&latitude length:8];
|
||||
[self writeBytes:(UInt8 *)&longitude length:8];
|
||||
} else if ([value isKindOfClass:[FIRDocumentReference class]]) {
|
||||
FIRDocumentReference *document = value;
|
||||
NSString *documentPath = [document path];
|
||||
[self writeByte:DOCUMENT_REFERENCE];
|
||||
[self writeUTF8:document.firestore.app.name];
|
||||
[self writeUTF8:documentPath];
|
||||
} else if ([value isKindOfClass:[NSData class]]) {
|
||||
NSData *blob = value;
|
||||
[self writeByte:BLOB];
|
||||
[self writeSize:(UInt32)blob.length];
|
||||
[self writeData:blob];
|
||||
} else {
|
||||
[super writeValue:value];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@interface FirestoreReader : FlutterStandardReader
|
||||
- (id)readValueOfType:(UInt8)type;
|
||||
@end
|
||||
|
||||
@implementation FirestoreReader
|
||||
- (id)readValueOfType:(UInt8)type {
|
||||
switch (type) {
|
||||
case DATE_TIME: {
|
||||
SInt64 value;
|
||||
[self readBytes:&value length:8];
|
||||
return [NSDate dateWithTimeIntervalSince1970:(value / 1000.0)];
|
||||
}
|
||||
case TIMESTAMP: {
|
||||
SInt64 seconds;
|
||||
int nanoseconds;
|
||||
[self readBytes:&seconds length:8];
|
||||
[self readBytes:&nanoseconds length:4];
|
||||
return [[FIRTimestamp alloc] initWithSeconds:seconds nanoseconds:nanoseconds];
|
||||
}
|
||||
case GEO_POINT: {
|
||||
Float64 latitude;
|
||||
Float64 longitude;
|
||||
[self readAlignment:8];
|
||||
[self readBytes:&latitude length:8];
|
||||
[self readBytes:&longitude length:8];
|
||||
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 [firestore documentWithPath:documentPath];
|
||||
}
|
||||
case BLOB: {
|
||||
UInt32 elementCount = [self readSize];
|
||||
return [self readData:elementCount];
|
||||
}
|
||||
case ARRAY_UNION: {
|
||||
return [FIRFieldValue fieldValueForArrayUnion:[self readValue]];
|
||||
}
|
||||
case ARRAY_REMOVE: {
|
||||
return [FIRFieldValue fieldValueForArrayRemove:[self readValue]];
|
||||
}
|
||||
case DELETE: {
|
||||
return [FIRFieldValue fieldValueForDelete];
|
||||
}
|
||||
case SERVER_TIMESTAMP: {
|
||||
return [FIRFieldValue fieldValueForServerTimestamp];
|
||||
}
|
||||
case INCREMENT_DOUBLE: {
|
||||
NSNumber *value = [self readValue];
|
||||
return [FIRFieldValue fieldValueForDoubleIncrement:value.doubleValue];
|
||||
}
|
||||
case INCREMENT_INTEGER: {
|
||||
NSNumber *value = [self readValue];
|
||||
return [FIRFieldValue fieldValueForIntegerIncrement:value.intValue];
|
||||
}
|
||||
default:
|
||||
return [super readValueOfType:type];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@interface FirestoreReaderWriter : FlutterStandardReaderWriter
|
||||
- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data;
|
||||
- (FlutterStandardReader *)readerWithData:(NSData *)data;
|
||||
@end
|
||||
|
||||
@implementation FirestoreReaderWriter
|
||||
- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data {
|
||||
return [[FirestoreWriter alloc] initWithData:data];
|
||||
}
|
||||
- (FlutterStandardReader *)readerWithData:(NSData *)data {
|
||||
return [[FirestoreReader alloc] initWithData:data];
|
||||
}
|
||||
@end
|
||||
|
||||
@interface FLTCloudFirestorePlugin ()
|
||||
@property(nonatomic, retain) FlutterMethodChannel *channel;
|
||||
@end
|
||||
|
||||
@implementation FLTCloudFirestorePlugin {
|
||||
NSMutableDictionary<NSNumber *, id<FIRListenerRegistration>> *_listeners;
|
||||
int _nextListenerHandle;
|
||||
NSMutableDictionary *transactions;
|
||||
NSMutableDictionary *transactionResults;
|
||||
NSMutableDictionary<NSNumber *, FIRWriteBatch *> *_batches;
|
||||
int _nextBatchHandle;
|
||||
}
|
||||
|
||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
|
||||
FirestoreReaderWriter *firestoreReaderWriter = [FirestoreReaderWriter new];
|
||||
FlutterMethodChannel *channel =
|
||||
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/cloud_firestore"
|
||||
binaryMessenger:[registrar messenger]
|
||||
codec:[FlutterStandardMethodCodec
|
||||
codecWithReaderWriter:firestoreReaderWriter]];
|
||||
FLTCloudFirestorePlugin *instance = [[FLTCloudFirestorePlugin alloc] init];
|
||||
instance.channel = channel;
|
||||
[registrar addMethodCallDelegate:instance channel:channel];
|
||||
|
||||
SEL sel = NSSelectorFromString(@"registerLibrary:withVersion:");
|
||||
if ([FIRApp respondsToSelector:sel]) {
|
||||
[FIRApp performSelector:sel withObject:LIBRARY_NAME withObject:LIBRARY_VERSION];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) {
|
||||
NSLog(@"Configuring the default Firebase app...");
|
||||
[FIRApp configure];
|
||||
NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name);
|
||||
}
|
||||
_listeners = [NSMutableDictionary<NSNumber *, id<FIRListenerRegistration>> dictionary];
|
||||
_batches = [NSMutableDictionary<NSNumber *, FIRWriteBatch *> dictionary];
|
||||
_nextListenerHandle = 0;
|
||||
_nextBatchHandle = 0;
|
||||
transactions = [NSMutableDictionary<NSNumber *, FIRTransaction *> dictionary];
|
||||
transactionResults = [NSMutableDictionary<NSNumber *, id> dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
void (^defaultCompletionBlock)(NSError *) = ^(NSError *error) {
|
||||
result(getFlutterError(error));
|
||||
};
|
||||
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"];
|
||||
|
||||
self->transactions[transactionId] = transaction;
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
[weakSelf.channel invokeMethod:@"DoTransaction"
|
||||
arguments:call.arguments
|
||||
result:^(id doTransactionResult) {
|
||||
FLTCloudFirestorePlugin *currentSelf = weakSelf;
|
||||
currentSelf->transactionResults[transactionId] =
|
||||
doTransactionResult;
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
|
||||
dispatch_semaphore_wait(
|
||||
semaphore,
|
||||
dispatch_time(DISPATCH_TIME_NOW, [transactionTimeout integerValue] * 1000000));
|
||||
|
||||
return self->transactionResults[transactionId];
|
||||
}
|
||||
completion:^(id transactionResult, NSError *error) {
|
||||
if (error != nil) {
|
||||
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%ld", error.code]
|
||||
message:error.localizedDescription
|
||||
details:nil]);
|
||||
}
|
||||
result(transactionResult);
|
||||
}];
|
||||
} else if ([@"Transaction#get" isEqualToString:call.method]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSNumber *transactionId = call.arguments[@"transactionId"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRTransaction *transaction = self->transactions[transactionId];
|
||||
NSError *error = [[NSError alloc] init];
|
||||
|
||||
FIRDocumentSnapshot *snapshot = [transaction getDocument:document error:&error];
|
||||
|
||||
if (error != nil) {
|
||||
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%tu", [error code]]
|
||||
message:[error localizedDescription]
|
||||
details:nil]);
|
||||
} else if (snapshot != nil) {
|
||||
result(@{
|
||||
@"path" : snapshot.reference.path,
|
||||
@"data" : snapshot.exists ? snapshot.data : [NSNull null],
|
||||
@"metadata" : @{
|
||||
@"hasPendingWrites" : @(snapshot.metadata.hasPendingWrites),
|
||||
@"isFromCache" : @(snapshot.metadata.isFromCache),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
result(nil);
|
||||
}
|
||||
});
|
||||
} else if ([@"Transaction#update" isEqualToString:call.method]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSNumber *transactionId = call.arguments[@"transactionId"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRTransaction *transaction = self->transactions[transactionId];
|
||||
|
||||
[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"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRTransaction *transaction = self->transactions[transactionId];
|
||||
|
||||
[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"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRTransaction *transaction = self->transactions[transactionId];
|
||||
|
||||
[transaction deleteDocument:document];
|
||||
result(nil);
|
||||
});
|
||||
} else if ([@"DocumentReference#setData" isEqualToString:call.method]) {
|
||||
NSDictionary *options = call.arguments[@"options"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
if (![options isEqual:[NSNull null]] &&
|
||||
[options[@"merge"] isEqual:[NSNumber numberWithBool:YES]]) {
|
||||
[document setData:call.arguments[@"data"] merge:YES completion:defaultCompletionBlock];
|
||||
} else {
|
||||
[document setData:call.arguments[@"data"] completion:defaultCompletionBlock];
|
||||
}
|
||||
} else if ([@"DocumentReference#updateData" isEqualToString:call.method]) {
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
[document updateData:call.arguments[@"data"] completion:defaultCompletionBlock];
|
||||
} else if ([@"DocumentReference#delete" isEqualToString:call.method]) {
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
[document deleteDocumentWithCompletion:defaultCompletionBlock];
|
||||
} else if ([@"DocumentReference#get" isEqualToString:call.method]) {
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRFirestoreSource source = getSource(call.arguments);
|
||||
[document
|
||||
getDocumentWithSource:source
|
||||
completion:^(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error) {
|
||||
if (snapshot == nil) {
|
||||
result(getFlutterError(error));
|
||||
} else {
|
||||
result(@{
|
||||
@"path" : snapshot.reference.path,
|
||||
@"data" : snapshot.exists ? snapshot.data : [NSNull null],
|
||||
@"metadata" : @{
|
||||
@"hasPendingWrites" : @(snapshot.metadata.hasPendingWrites),
|
||||
@"isFromCache" : @(snapshot.metadata.isFromCache),
|
||||
},
|
||||
});
|
||||
}
|
||||
}];
|
||||
} else if ([@"Query#addSnapshotListener" isEqualToString:call.method]) {
|
||||
__block NSNumber *handle = [NSNumber numberWithInt:_nextListenerHandle++];
|
||||
FIRQuery *query;
|
||||
@try {
|
||||
query = getQuery(call.arguments);
|
||||
} @catch (NSException *exception) {
|
||||
result([FlutterError errorWithCode:@"invalid_query"
|
||||
message:[exception name]
|
||||
details:[exception reason]]);
|
||||
}
|
||||
id<FIRListenerRegistration> listener = [query
|
||||
addSnapshotListener:^(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error) {
|
||||
if (snapshot == nil) {
|
||||
result(getFlutterError(error));
|
||||
return;
|
||||
}
|
||||
NSMutableDictionary *arguments = [parseQuerySnapshot(snapshot) mutableCopy];
|
||||
[arguments setObject:handle forKey:@"handle"];
|
||||
[weakSelf.channel invokeMethod:@"QuerySnapshot" arguments:arguments];
|
||||
}];
|
||||
_listeners[handle] = listener;
|
||||
result(handle);
|
||||
} else if ([@"Query#addDocumentListener" isEqualToString:call.method]) {
|
||||
__block NSNumber *handle = [NSNumber numberWithInt:_nextListenerHandle++];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
id<FIRListenerRegistration> listener =
|
||||
[document addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) {
|
||||
if (snapshot == nil) {
|
||||
result(getFlutterError(error));
|
||||
return;
|
||||
}
|
||||
[weakSelf.channel invokeMethod:@"DocumentSnapshot"
|
||||
arguments:@{
|
||||
@"handle" : handle,
|
||||
@"path" : snapshot ? snapshot.reference.path : [NSNull null],
|
||||
@"data" : snapshot.exists ? snapshot.data : [NSNull null],
|
||||
@"metadata" : snapshot ? @{
|
||||
@"hasPendingWrites" : @(snapshot.metadata.hasPendingWrites),
|
||||
@"isFromCache" : @(snapshot.metadata.isFromCache),
|
||||
}
|
||||
: [NSNull null],
|
||||
}];
|
||||
}];
|
||||
_listeners[handle] = listener;
|
||||
result(handle);
|
||||
} else if ([@"Query#getDocuments" isEqualToString:call.method]) {
|
||||
FIRQuery *query;
|
||||
FIRFirestoreSource source = getSource(call.arguments);
|
||||
@try {
|
||||
query = getQuery(call.arguments);
|
||||
} @catch (NSException *exception) {
|
||||
result([FlutterError errorWithCode:@"invalid_query"
|
||||
message:[exception name]
|
||||
details:[exception reason]]);
|
||||
}
|
||||
|
||||
[query
|
||||
getDocumentsWithSource:source
|
||||
completion:^(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error) {
|
||||
if (snapshot == nil) {
|
||||
result(getFlutterError(error));
|
||||
return;
|
||||
}
|
||||
result(parseQuerySnapshot(snapshot));
|
||||
}];
|
||||
} else if ([@"Query#removeListener" isEqualToString:call.method]) {
|
||||
NSNumber *handle = call.arguments[@"handle"];
|
||||
[[_listeners objectForKey:handle] remove];
|
||||
[_listeners removeObjectForKey:handle];
|
||||
result(nil);
|
||||
} else if ([@"WriteBatch#create" isEqualToString:call.method]) {
|
||||
__block NSNumber *handle = [NSNumber numberWithInt:_nextBatchHandle++];
|
||||
FIRWriteBatch *batch = [getFirestore(call.arguments) batch];
|
||||
_batches[handle] = batch;
|
||||
result(handle);
|
||||
} else if ([@"WriteBatch#setData" isEqualToString:call.method]) {
|
||||
NSNumber *handle = call.arguments[@"handle"];
|
||||
NSDictionary *options = call.arguments[@"options"];
|
||||
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:document merge:YES];
|
||||
} else {
|
||||
[batch setData:call.arguments[@"data"] forDocument:document];
|
||||
}
|
||||
result(nil);
|
||||
} else if ([@"WriteBatch#updateData" isEqualToString:call.method]) {
|
||||
NSNumber *handle = call.arguments[@"handle"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRWriteBatch *batch = [_batches objectForKey:handle];
|
||||
[batch updateData:call.arguments[@"data"] forDocument:document];
|
||||
result(nil);
|
||||
} else if ([@"WriteBatch#delete" isEqualToString:call.method]) {
|
||||
NSNumber *handle = call.arguments[@"handle"];
|
||||
FIRDocumentReference *document = getDocumentReference(call.arguments);
|
||||
FIRWriteBatch *batch = [_batches objectForKey:handle];
|
||||
[batch deleteDocument:document];
|
||||
result(nil);
|
||||
} else if ([@"WriteBatch#commit" isEqualToString:call.method]) {
|
||||
NSNumber *handle = call.arguments[@"handle"];
|
||||
FIRWriteBatch *batch = [_batches objectForKey:handle];
|
||||
[batch commitWithCompletion:defaultCompletionBlock];
|
||||
[_batches removeObjectForKey:handle];
|
||||
} else if ([@"Firestore#enablePersistence" isEqualToString:call.method]) {
|
||||
bool enable = (bool)call.arguments[@"enable"];
|
||||
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];
|
||||
settings.persistenceEnabled = enable;
|
||||
FIRFirestore *db = getFirestore(call.arguments);
|
||||
db.settings = settings;
|
||||
result(nil);
|
||||
} else if ([@"Firestore#settings" isEqualToString:call.method]) {
|
||||
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];
|
||||
if (![call.arguments[@"persistenceEnabled"] isEqual:[NSNull null]]) {
|
||||
settings.persistenceEnabled = (bool)call.arguments[@"persistenceEnabled"];
|
||||
}
|
||||
if (![call.arguments[@"host"] isEqual:[NSNull null]]) {
|
||||
settings.host = (NSString *)call.arguments[@"host"];
|
||||
}
|
||||
if (![call.arguments[@"sslEnabled"] isEqual:[NSNull null]]) {
|
||||
settings.sslEnabled = (bool)call.arguments[@"sslEnabled"];
|
||||
}
|
||||
if (![call.arguments[@"timestampsInSnapshotsEnabled"] isEqual:[NSNull null]]) {
|
||||
settings.timestampsInSnapshotsEnabled = (bool)call.arguments[@"timestampsInSnapshotsEnabled"];
|
||||
}
|
||||
if (![call.arguments[@"cacheSizeBytes"] isEqual:[NSNull null]]) {
|
||||
settings.cacheSizeBytes = ((NSNumber *)call.arguments[@"cacheSizeBytes"]).intValue;
|
||||
}
|
||||
FIRFirestore *db = getFirestore(call.arguments);
|
||||
db.settings = settings;
|
||||
result(nil);
|
||||
} else {
|
||||
result(FlutterMethodNotImplemented);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'cloud_firestore'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'Firestore plugin for Flutter.'
|
||||
s.description = <<-DESC
|
||||
Firestore plugin for Flutter.
|
||||
DESC
|
||||
s.homepage = 'https://github.com/flutter/firestore'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.public_header_files = 'Classes/**/*.h'
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.dependency 'Flutter'
|
||||
s.dependency 'Firebase/Core'
|
||||
s.dependency 'Firebase/Firestore', '~> 6.0'
|
||||
s.static_framework = true
|
||||
end
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
library cloud_firestore;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' show hashValues, hashList;
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter_web/foundation.dart' show ReadBuffer, WriteBuffer;
|
||||
import 'package:flutter_web/services.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'src/utils/push_id_generator.dart';
|
||||
|
||||
part 'src/blob.dart';
|
||||
part 'src/collection_reference.dart';
|
||||
part 'src/document_change.dart';
|
||||
part 'src/document_reference.dart';
|
||||
part 'src/document_snapshot.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/snapshot_metadata.dart';
|
||||
part 'src/timestamp.dart';
|
||||
part 'src/transaction.dart';
|
||||
part 'src/write_batch.dart';
|
||||
part 'src/source.dart';
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2018, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
class Blob {
|
||||
const Blob(this.bytes);
|
||||
|
||||
final Uint8List bytes;
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) =>
|
||||
other is Blob &&
|
||||
const DeepCollectionEquality().equals(other.bytes, bytes);
|
||||
|
||||
@override
|
||||
int get hashCode => hashList(bytes);
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// A CollectionReference object can be used for adding documents, getting
|
||||
/// 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);
|
||||
|
||||
/// ID of the referenced collection.
|
||||
String get id => _pathComponents.isEmpty ? null : _pathComponents.last;
|
||||
|
||||
/// For subcollections, parent returns the containing [DocumentReference].
|
||||
///
|
||||
/// For root collections, null is returned.
|
||||
DocumentReference parent() {
|
||||
if (_pathComponents.length < 2) {
|
||||
return null;
|
||||
}
|
||||
return DocumentReference._(
|
||||
firestore,
|
||||
(List<String>.from(_pathComponents)..removeLast()),
|
||||
);
|
||||
}
|
||||
|
||||
/// A string containing the slash-separated path to this CollectionReference
|
||||
/// (relative to the root of the database).
|
||||
String get path => _path;
|
||||
|
||||
/// Returns a `DocumentReference` with the provided path.
|
||||
///
|
||||
/// If no [path] is provided, an auto-generated ID is used.
|
||||
///
|
||||
/// 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 = PushIdGenerator.generatePushChildName();
|
||||
childPath = List<String>.from(_pathComponents)..add(key);
|
||||
} else {
|
||||
childPath = List<String>.from(_pathComponents)..addAll(path.split(('/')));
|
||||
}
|
||||
return DocumentReference._(firestore, childPath);
|
||||
}
|
||||
|
||||
/// Returns a `DocumentReference` with an auto-generated ID, after
|
||||
/// populating it with provided [data].
|
||||
///
|
||||
/// The unique key generated is prefixed with a client-generated timestamp
|
||||
/// so that the resulting list will be chronologically-sorted.
|
||||
Future<DocumentReference> add(Map<String, dynamic> data) async {
|
||||
final DocumentReference newDocument = document();
|
||||
await newDocument.setData(data);
|
||||
return newDocument;
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
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, this._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 Firestore _firestore;
|
||||
|
||||
/// The type of change that occurred (added, modified, or removed).
|
||||
final DocumentChangeType 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;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// The document affected by this change.
|
||||
final DocumentSnapshot document;
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// A [DocumentReference] refers to a document location in a Firestore database
|
||||
/// and can be used to write, read, or listen to the location.
|
||||
///
|
||||
/// The document at the referenced location may or may not exist.
|
||||
/// A [DocumentReference] can also be used to create a [CollectionReference]
|
||||
/// to a subcollection.
|
||||
class DocumentReference {
|
||||
DocumentReference._(this.firestore, List<String> pathComponents)
|
||||
: _pathComponents = pathComponents,
|
||||
assert(firestore != null);
|
||||
|
||||
/// The Firestore instance associated with this document reference
|
||||
final Firestore firestore;
|
||||
|
||||
final List<String> _pathComponents;
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic o) =>
|
||||
o is DocumentReference && o.firestore == firestore && o.path == path;
|
||||
|
||||
@override
|
||||
int get hashCode => hashList(_pathComponents);
|
||||
|
||||
/// Parent returns the containing [CollectionReference].
|
||||
CollectionReference parent() {
|
||||
return CollectionReference._(
|
||||
firestore,
|
||||
(List<String>.from(_pathComponents)..removeLast()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Slash-delimited path representing the database location of this query.
|
||||
String get path => _pathComponents.join('/');
|
||||
|
||||
/// This document's given or generated ID in the collection.
|
||||
String get documentID => _pathComponents.last;
|
||||
|
||||
/// Writes to the document referred to by this [DocumentReference].
|
||||
///
|
||||
/// If the document does not yet exist, it will be created.
|
||||
///
|
||||
/// 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},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates fields in the document referred to by this [DocumentReference].
|
||||
///
|
||||
/// Values in [data] may be of any supported Firestore type as well as
|
||||
/// special sentinel [FieldValue] type.
|
||||
///
|
||||
/// 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,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Reads the document referenced by this [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),
|
||||
},
|
||||
);
|
||||
return DocumentSnapshot._(
|
||||
data['path'],
|
||||
_asStringKeyedMap(data['data']),
|
||||
SnapshotMetadata._(data['metadata']['hasPendingWrites'],
|
||||
data['metadata']['isFromCache']),
|
||||
firestore,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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},
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the reference of a collection contained inside of this
|
||||
/// document.
|
||||
CollectionReference collection(String collectionPath) {
|
||||
return firestore.collection(
|
||||
<String>[path, collectionPath].join('/'),
|
||||
);
|
||||
}
|
||||
|
||||
/// Notifies of documents at this location
|
||||
// TODO(jackson): Reduce code duplication with [Query]
|
||||
Stream<DocumentSnapshot> snapshots() {
|
||||
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>(
|
||||
'Query#addDocumentListener',
|
||||
<String, dynamic>{
|
||||
'app': firestore.app.name,
|
||||
'path': path,
|
||||
},
|
||||
).then<int>((dynamic result) => result);
|
||||
_handle.then((int handle) {
|
||||
Firestore._documentObservers[handle] = controller;
|
||||
});
|
||||
},
|
||||
onCancel: () {
|
||||
_handle.then((int handle) async {
|
||||
await Firestore.channel.invokeMethod<void>(
|
||||
'Query#removeListener',
|
||||
<String, dynamic>{'handle': handle},
|
||||
);
|
||||
Firestore._documentObservers.remove(handle);
|
||||
});
|
||||
},
|
||||
);
|
||||
return controller.stream;
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// A DocumentSnapshot contains data read from a document in your Firestore
|
||||
/// database.
|
||||
///
|
||||
/// The data can be extracted with the data property or by using subscript
|
||||
/// syntax to access a specific field.
|
||||
class DocumentSnapshot {
|
||||
DocumentSnapshot._(this._path, this.data, this.metadata, this._firestore);
|
||||
|
||||
final String _path;
|
||||
final Firestore _firestore;
|
||||
|
||||
/// The reference that produced this snapshot
|
||||
DocumentReference get reference => _firestore.document(_path);
|
||||
|
||||
/// Contains all the data of this snapshot
|
||||
final Map<String, dynamic> data;
|
||||
|
||||
/// Metadata about this snapshot concerning its source and if it has local
|
||||
/// modifications.
|
||||
final SnapshotMetadata metadata;
|
||||
|
||||
/// Reads individual values from the snapshot
|
||||
dynamic operator [](String key) => data[key];
|
||||
|
||||
/// Returns the ID of the snapshot's document
|
||||
String get documentID => _path.split('/').last;
|
||||
|
||||
/// Returns `true` if the document exists.
|
||||
bool get exists => data != null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _asStringKeyedMap(Map<dynamic, dynamic> map) {
|
||||
if (map == null) return null;
|
||||
if (map is Map<String, dynamic>) {
|
||||
return map;
|
||||
} else {
|
||||
return Map<String, dynamic>.from(map);
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
@visibleForTesting
|
||||
enum FieldValueType {
|
||||
arrayUnion,
|
||||
arrayRemove,
|
||||
delete,
|
||||
serverTimestamp,
|
||||
incrementDouble,
|
||||
incrementInteger,
|
||||
}
|
||||
|
||||
/// Sentinel values that can be used when writing document fields with set() or
|
||||
/// update().
|
||||
class FieldValue {
|
||||
FieldValue._(this.type, this.value);
|
||||
|
||||
@visibleForTesting
|
||||
final FieldValueType type;
|
||||
|
||||
@visibleForTesting
|
||||
final dynamic value;
|
||||
|
||||
/// Returns a special value that tells the server to union the given elements
|
||||
/// with any array value that already exists on the server.
|
||||
///
|
||||
/// Each specified element that doesn't already exist in the array will be
|
||||
/// added to the end. If the field being modified is not already an array it
|
||||
/// will be overwritten with an array containing exactly the specified
|
||||
/// elements.
|
||||
static FieldValue arrayUnion(List<dynamic> elements) =>
|
||||
FieldValue._(FieldValueType.arrayUnion, elements);
|
||||
|
||||
/// Returns a special value that tells the server to remove the given
|
||||
/// elements from any array value that already exists on the server.
|
||||
///
|
||||
/// All instances of each element specified will be removed from the array.
|
||||
/// If the field being modified is not already an array it will be overwritten
|
||||
/// with an empty array.
|
||||
static FieldValue arrayRemove(List<dynamic> elements) =>
|
||||
FieldValue._(FieldValueType.arrayRemove, elements);
|
||||
|
||||
/// Returns a sentinel for use with update() to mark a field for deletion.
|
||||
static FieldValue delete() => FieldValue._(FieldValueType.delete, null);
|
||||
|
||||
/// Returns a sentinel for use with set() or update() to include a
|
||||
/// server-generated timestamp in the written data.
|
||||
static FieldValue serverTimestamp() =>
|
||||
FieldValue._(FieldValueType.serverTimestamp, null);
|
||||
|
||||
/// Returns a special value for use with set() or update() that tells the
|
||||
/// server to increment the field’s current value by the given value.
|
||||
static FieldValue increment(num value) {
|
||||
// It is a compile-time error for any type other than int or double to
|
||||
// attempt to extend or implement num.
|
||||
assert(value is int || value is double);
|
||||
if (value is double) {
|
||||
return FieldValue._(FieldValueType.incrementDouble, value);
|
||||
} else if (value is int) {
|
||||
return FieldValue._(FieldValueType.incrementInteger, value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// The entry point for accessing a Firestore.
|
||||
///
|
||||
/// You can get an instance by calling [Firestore.instance].
|
||||
class Firestore {
|
||||
Firestore({FirebaseApp app}) : app = app ?? FirebaseApp.instance {
|
||||
if (_initialized) return;
|
||||
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'];
|
||||
return _transactionHandlers[transactionId](
|
||||
Transaction(transactionId, this),
|
||||
);
|
||||
}
|
||||
});
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/// Gets the instance of Firestore for the default Firebase app.
|
||||
static final Firestore instance = Firestore();
|
||||
|
||||
/// The [FirebaseApp] instance to which this [FirebaseDatabase] belongs.
|
||||
///
|
||||
/// If null, the default [FirebaseApp] is used.
|
||||
final FirebaseApp app;
|
||||
|
||||
static bool _initialized = false;
|
||||
|
||||
@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;
|
||||
|
||||
@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) {
|
||||
assert(path != null);
|
||||
return CollectionReference._(this, path.split('/'));
|
||||
}
|
||||
|
||||
/// Gets a [Query] for the specified collection group.
|
||||
Query collectionGroup(String path) {
|
||||
assert(path != null);
|
||||
assert(!path.contains("/"), "Collection IDs must not contain '/'.");
|
||||
return Query._(
|
||||
firestore: this,
|
||||
isCollectionGroup: true,
|
||||
pathComponents: path.split('/'),
|
||||
);
|
||||
}
|
||||
|
||||
/// Gets a [DocumentReference] for the specified Firestore path.
|
||||
DocumentReference document(String path) {
|
||||
assert(path != null);
|
||||
return DocumentReference._(this, path.split('/'));
|
||||
}
|
||||
|
||||
/// Creates a write batch, used for performing multiple writes as a single
|
||||
/// atomic operation.
|
||||
///
|
||||
/// 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() => WriteBatch._(this);
|
||||
|
||||
/// Executes the given TransactionHandler and then attempts to commit the
|
||||
/// changes applied within an atomic transaction.
|
||||
///
|
||||
/// In the TransactionHandler, a set of reads and writes can be performed
|
||||
/// atomically using the Transaction object passed to the TransactionHandler.
|
||||
/// After the TransactionHandler is run, Firestore will attempt to apply the
|
||||
/// changes to the server. If any of the data read has been modified outside
|
||||
/// of this transaction since being read, then the transaction will be
|
||||
/// retried by executing the updateBlock again. If the transaction still
|
||||
/// fails after 5 retries, then the transaction will fail.
|
||||
///
|
||||
/// The TransactionHandler may be executed multiple times, it should be able
|
||||
/// to handle multiple executions.
|
||||
///
|
||||
/// Data accessed with the transaction will not reflect local changes that
|
||||
/// have not been committed. For this reason, it is required that all
|
||||
/// reads are performed before any writes. Transactions must be performed
|
||||
/// while online. Otherwise, reads will fail, and the final commit will fail.
|
||||
///
|
||||
/// By default transactions are limited to 5 seconds of execution time. This
|
||||
/// timeout can be adjusted by setting the timeout parameter.
|
||||
Future<Map<String, dynamic>> runTransaction(
|
||||
TransactionHandler transactionHandler,
|
||||
{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
|
||||
});
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> settings(
|
||||
{bool persistenceEnabled,
|
||||
String host,
|
||||
bool sslEnabled,
|
||||
bool timestampsInSnapshotsEnabled,
|
||||
int cacheSizeBytes}) async {
|
||||
await channel.invokeMethod<void>('Firestore#settings', <String, dynamic>{
|
||||
'app': app.name,
|
||||
'persistenceEnabled': persistenceEnabled,
|
||||
'host': host,
|
||||
'sslEnabled': sslEnabled,
|
||||
'timestampsInSnapshotsEnabled': timestampsInSnapshotsEnabled,
|
||||
'cacheSizeBytes': cacheSizeBytes,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
@visibleForTesting
|
||||
class FirestoreMessageCodec extends StandardMessageCodec {
|
||||
const FirestoreMessageCodec();
|
||||
|
||||
static const int _kDateTime = 128;
|
||||
static const int _kGeoPoint = 129;
|
||||
static const int _kDocumentReference = 130;
|
||||
static const int _kBlob = 131;
|
||||
static const int _kArrayUnion = 132;
|
||||
static const int _kArrayRemove = 133;
|
||||
static const int _kDelete = 134;
|
||||
static const int _kServerTimestamp = 135;
|
||||
static const int _kTimestamp = 136;
|
||||
static const int _kIncrementDouble = 137;
|
||||
static const int _kIncrementInteger = 138;
|
||||
|
||||
static const Map<FieldValueType, int> _kFieldValueCodes =
|
||||
<FieldValueType, int>{
|
||||
FieldValueType.arrayUnion: _kArrayUnion,
|
||||
FieldValueType.arrayRemove: _kArrayRemove,
|
||||
FieldValueType.delete: _kDelete,
|
||||
FieldValueType.serverTimestamp: _kServerTimestamp,
|
||||
FieldValueType.incrementDouble: _kIncrementDouble,
|
||||
FieldValueType.incrementInteger: _kIncrementInteger,
|
||||
};
|
||||
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, dynamic value) {
|
||||
if (value is DateTime) {
|
||||
buffer.putUint8(_kDateTime);
|
||||
buffer.putInt64(value.millisecondsSinceEpoch);
|
||||
} else if (value is Timestamp) {
|
||||
buffer.putUint8(_kTimestamp);
|
||||
buffer.putInt64(value.seconds);
|
||||
buffer.putInt32(value.nanoseconds);
|
||||
} else if (value is GeoPoint) {
|
||||
buffer.putUint8(_kGeoPoint);
|
||||
buffer.putFloat64(value.latitude);
|
||||
buffer.putFloat64(value.longitude);
|
||||
} else if (value is DocumentReference) {
|
||||
buffer.putUint8(_kDocumentReference);
|
||||
final List<int> appName = utf8.encoder.convert(value.firestore.app.name);
|
||||
writeSize(buffer, appName.length);
|
||||
buffer.putUint8List(appName);
|
||||
final List<int> bytes = utf8.encoder.convert(value.path);
|
||||
writeSize(buffer, bytes.length);
|
||||
buffer.putUint8List(bytes);
|
||||
} else if (value is Blob) {
|
||||
buffer.putUint8(_kBlob);
|
||||
writeSize(buffer, value.bytes.length);
|
||||
buffer.putUint8List(value.bytes);
|
||||
} else if (value is FieldValue) {
|
||||
final int code = _kFieldValueCodes[value.type];
|
||||
assert(code != null);
|
||||
buffer.putUint8(code);
|
||||
if (value.value != null) writeValue(buffer, value.value);
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case _kDateTime:
|
||||
return DateTime.fromMillisecondsSinceEpoch(buffer.getInt64());
|
||||
case _kTimestamp:
|
||||
return Timestamp(buffer.getInt64(), buffer.getInt32());
|
||||
case _kGeoPoint:
|
||||
return GeoPoint(buffer.getFloat64(), buffer.getFloat64());
|
||||
case _kDocumentReference:
|
||||
final int appNameLength = readSize(buffer);
|
||||
final String appName =
|
||||
utf8.decoder.convert(buffer.getUint8List(appNameLength));
|
||||
final FirebaseApp app = FirebaseApp(name: appName);
|
||||
final Firestore firestore = Firestore(app: app);
|
||||
final int pathLength = readSize(buffer);
|
||||
final String path =
|
||||
utf8.decoder.convert(buffer.getUint8List(pathLength));
|
||||
return firestore.document(path);
|
||||
case _kBlob:
|
||||
final int length = readSize(buffer);
|
||||
final List<int> bytes = buffer.getUint8List(length);
|
||||
return Blob(bytes);
|
||||
case _kArrayUnion:
|
||||
final List<dynamic> value = readValue(buffer);
|
||||
return FieldValue.arrayUnion(value);
|
||||
case _kArrayRemove:
|
||||
final List<dynamic> value = readValue(buffer);
|
||||
return FieldValue.arrayRemove(value);
|
||||
case _kDelete:
|
||||
return FieldValue.delete();
|
||||
case _kServerTimestamp:
|
||||
return FieldValue.serverTimestamp();
|
||||
case _kIncrementDouble:
|
||||
final double value = readValue(buffer);
|
||||
return FieldValue.increment(value);
|
||||
case _kIncrementInteger:
|
||||
final int value = readValue(buffer);
|
||||
return FieldValue.increment(value);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
class GeoPoint {
|
||||
const GeoPoint(this.latitude, this.longitude);
|
||||
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic o) =>
|
||||
o is GeoPoint && o.latitude == latitude && o.longitude == longitude;
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(latitude, longitude);
|
||||
}
|
|
@ -1,352 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// Represents a query over the data at a particular location.
|
||||
class Query {
|
||||
Query._(
|
||||
{@required this.firestore,
|
||||
@required List<String> pathComponents,
|
||||
bool isCollectionGroup = false,
|
||||
Map<String, dynamic> parameters})
|
||||
: _pathComponents = pathComponents,
|
||||
_isCollectionGroup = isCollectionGroup,
|
||||
_parameters = parameters ??
|
||||
Map<String, dynamic>.unmodifiable(<String, dynamic>{
|
||||
'where': List<List<dynamic>>.unmodifiable(<List<dynamic>>[]),
|
||||
'orderBy': List<List<dynamic>>.unmodifiable(<List<dynamic>>[]),
|
||||
}),
|
||||
assert(firestore != null),
|
||||
assert(pathComponents != null);
|
||||
|
||||
/// The Firestore instance associated with this query
|
||||
final Firestore firestore;
|
||||
|
||||
final List<String> _pathComponents;
|
||||
final Map<String, dynamic> _parameters;
|
||||
final bool _isCollectionGroup;
|
||||
|
||||
String get _path => _pathComponents.join('/');
|
||||
|
||||
Query _copyWithParameters(Map<String, dynamic> parameters) {
|
||||
return Query._(
|
||||
firestore: firestore,
|
||||
isCollectionGroup: _isCollectionGroup,
|
||||
pathComponents: _pathComponents,
|
||||
parameters: Map<String, dynamic>.unmodifiable(
|
||||
Map<String, dynamic>.from(_parameters)..addAll(parameters),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> buildArguments() {
|
||||
return Map<String, dynamic>.from(_parameters)
|
||||
..addAll(<String, dynamic>{
|
||||
'path': _path,
|
||||
});
|
||||
}
|
||||
|
||||
/// Notifies of query results at this location
|
||||
// TODO(jackson): Reduce code duplication with [DocumentReference]
|
||||
Stream<QuerySnapshot> snapshots() {
|
||||
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,
|
||||
},
|
||||
).then<int>((dynamic result) => result);
|
||||
_handle.then((int handle) {
|
||||
Firestore._queryObservers[handle] = controller;
|
||||
});
|
||||
},
|
||||
onCancel: () {
|
||||
_handle.then((int handle) async {
|
||||
await Firestore.channel.invokeMethod<void>(
|
||||
'Query#removeListener',
|
||||
<String, dynamic>{'handle': handle},
|
||||
);
|
||||
Firestore._queryObservers.remove(handle);
|
||||
});
|
||||
},
|
||||
);
|
||||
return controller.stream;
|
||||
}
|
||||
|
||||
/// 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),
|
||||
},
|
||||
);
|
||||
return QuerySnapshot._(data, firestore);
|
||||
}
|
||||
|
||||
/// Obtains a CollectionReference corresponding to this query's location.
|
||||
CollectionReference reference() =>
|
||||
CollectionReference._(firestore, _pathComponents);
|
||||
|
||||
/// Creates and returns a new [Query] with additional filter on specified
|
||||
/// [field]. [field] refers to a field in a document.
|
||||
///
|
||||
/// The [field] may consist of a single field name (referring to a top level
|
||||
/// field in the document), or a series of field names seperated by dots '.'
|
||||
/// (referring to a nested field in the document).
|
||||
///
|
||||
/// Only documents satisfying provided condition are included in the result
|
||||
/// set.
|
||||
Query where(
|
||||
String field, {
|
||||
dynamic isEqualTo,
|
||||
dynamic isLessThan,
|
||||
dynamic isLessThanOrEqualTo,
|
||||
dynamic isGreaterThan,
|
||||
dynamic isGreaterThanOrEqualTo,
|
||||
dynamic arrayContains,
|
||||
bool isNull,
|
||||
}) {
|
||||
final ListEquality<dynamic> equality = const ListEquality<dynamic>();
|
||||
final List<List<dynamic>> conditions =
|
||||
List<List<dynamic>>.from(_parameters['where']);
|
||||
|
||||
void addCondition(String field, String operator, dynamic value) {
|
||||
final List<dynamic> condition = <dynamic>[field, operator, value];
|
||||
assert(
|
||||
conditions
|
||||
.where((List<dynamic> item) => equality.equals(condition, item))
|
||||
.isEmpty,
|
||||
'Condition $condition already exists in this query.');
|
||||
conditions.add(condition);
|
||||
}
|
||||
|
||||
if (isEqualTo != null) addCondition(field, '==', isEqualTo);
|
||||
if (isLessThan != null) addCondition(field, '<', isLessThan);
|
||||
if (isLessThanOrEqualTo != null)
|
||||
addCondition(field, '<=', isLessThanOrEqualTo);
|
||||
if (isGreaterThan != null) addCondition(field, '>', isGreaterThan);
|
||||
if (isGreaterThanOrEqualTo != null)
|
||||
addCondition(field, '>=', isGreaterThanOrEqualTo);
|
||||
if (arrayContains != null)
|
||||
addCondition(field, 'array-contains', arrayContains);
|
||||
if (isNull != null) {
|
||||
assert(
|
||||
isNull,
|
||||
'isNull can only be set to true. '
|
||||
'Use isEqualTo to filter on non-null values.');
|
||||
addCondition(field, '==', null);
|
||||
}
|
||||
|
||||
return _copyWithParameters(<String, dynamic>{'where': conditions});
|
||||
}
|
||||
|
||||
/// Creates and returns a new [Query] that's additionally sorted by the specified
|
||||
/// [field].
|
||||
Query orderBy(String field, {bool descending = false}) {
|
||||
final List<List<dynamic>> orders =
|
||||
List<List<dynamic>>.from(_parameters['orderBy']);
|
||||
|
||||
final List<dynamic> order = <dynamic>[field, descending];
|
||||
assert(orders.where((List<dynamic> item) => field == item[0]).isEmpty,
|
||||
'OrderBy $field already exists in this query');
|
||||
orders.add(order);
|
||||
return _copyWithParameters(<String, dynamic>{'orderBy': orders});
|
||||
}
|
||||
|
||||
/// Creates and returns a new [Query] that starts after the provided document
|
||||
/// (exclusive). The starting position is relative to the order of the query.
|
||||
/// The document must contain all of the fields provided in the orderBy of
|
||||
/// this query.
|
||||
///
|
||||
/// Cannot be used in combination with [startAtDocument], [startAt], or
|
||||
/// [startAfter].
|
||||
///
|
||||
/// See also:
|
||||
/// * [endAfterDocument] for a query that ends after a document.
|
||||
/// * [startAtDocument] for a query that starts at a document.
|
||||
/// * [endAtDocument] for a query that ends at a document.
|
||||
Query startAfterDocument(DocumentSnapshot documentSnapshot) {
|
||||
assert(documentSnapshot != null);
|
||||
assert(!_parameters.containsKey('startAfter'));
|
||||
assert(!_parameters.containsKey('startAt'));
|
||||
assert(!_parameters.containsKey('startAfterDocument'));
|
||||
assert(!_parameters.containsKey('startAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{
|
||||
'startAfterDocument': <String, dynamic>{
|
||||
'id': documentSnapshot.documentID,
|
||||
'path': documentSnapshot.reference.path,
|
||||
'data': documentSnapshot.data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Creates and returns a new [Query] that starts at the provided document
|
||||
/// (inclusive). The starting position is relative to the order of the query.
|
||||
/// The document must contain all of the fields provided in the orderBy of
|
||||
/// this query.
|
||||
///
|
||||
/// Cannot be used in combination with [startAfterDocument], [startAfter], or
|
||||
/// [startAt].
|
||||
///
|
||||
/// See also:
|
||||
/// * [startAfterDocument] for a query that starts after a document.
|
||||
/// * [endAtDocument] for a query that ends at a document.
|
||||
/// * [endBeforeDocument] for a query that ends before a document.
|
||||
Query startAtDocument(DocumentSnapshot documentSnapshot) {
|
||||
assert(documentSnapshot != null);
|
||||
assert(!_parameters.containsKey('startAfter'));
|
||||
assert(!_parameters.containsKey('startAt'));
|
||||
assert(!_parameters.containsKey('startAfterDocument'));
|
||||
assert(!_parameters.containsKey('startAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{
|
||||
'startAtDocument': <String, dynamic>{
|
||||
'id': documentSnapshot.documentID,
|
||||
'path': documentSnapshot.reference.path,
|
||||
'data': documentSnapshot.data
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Takes a list of [values], creates and returns a new [Query] that starts
|
||||
/// after the provided fields relative to the order of the query.
|
||||
///
|
||||
/// The [values] must be in order of [orderBy] filters.
|
||||
///
|
||||
/// Cannot be used in combination with [startAt], [startAfterDocument], or
|
||||
/// [startAtDocument].
|
||||
Query startAfter(List<dynamic> values) {
|
||||
assert(values != null);
|
||||
assert(!_parameters.containsKey('startAfter'));
|
||||
assert(!_parameters.containsKey('startAt'));
|
||||
assert(!_parameters.containsKey('startAfterDocument'));
|
||||
assert(!_parameters.containsKey('startAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{'startAfter': values});
|
||||
}
|
||||
|
||||
/// Takes a list of [values], creates and returns a new [Query] that starts at
|
||||
/// the provided fields relative to the order of the query.
|
||||
///
|
||||
/// The [values] must be in order of [orderBy] filters.
|
||||
///
|
||||
/// Cannot be used in combination with [startAfter], [startAfterDocument],
|
||||
/// or [startAtDocument].
|
||||
Query startAt(List<dynamic> values) {
|
||||
assert(values != null);
|
||||
assert(!_parameters.containsKey('startAfter'));
|
||||
assert(!_parameters.containsKey('startAt'));
|
||||
assert(!_parameters.containsKey('startAfterDocument'));
|
||||
assert(!_parameters.containsKey('startAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{'startAt': values});
|
||||
}
|
||||
|
||||
/// Creates and returns a new [Query] that ends at the provided document
|
||||
/// (inclusive). The end position is relative to the order of the query.
|
||||
/// The document must contain all of the fields provided in the orderBy of
|
||||
/// this query.
|
||||
///
|
||||
/// Cannot be used in combination with [endBefore], [endBeforeDocument], or
|
||||
/// [endAt].
|
||||
///
|
||||
/// See also:
|
||||
/// * [startAfterDocument] for a query that starts after a document.
|
||||
/// * [startAtDocument] for a query that starts at a document.
|
||||
/// * [endBeforeDocument] for a query that ends before a document.
|
||||
Query endAtDocument(DocumentSnapshot documentSnapshot) {
|
||||
assert(documentSnapshot != null);
|
||||
assert(!_parameters.containsKey('endBefore'));
|
||||
assert(!_parameters.containsKey('endAt'));
|
||||
assert(!_parameters.containsKey('endBeforeDocument'));
|
||||
assert(!_parameters.containsKey('endAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{
|
||||
'endAtDocument': <String, dynamic>{
|
||||
'id': documentSnapshot.documentID,
|
||||
'path': documentSnapshot.reference.path,
|
||||
'data': documentSnapshot.data
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Takes a list of [values], creates and returns a new [Query] that ends at the
|
||||
/// provided fields relative to the order of the query.
|
||||
///
|
||||
/// The [values] must be in order of [orderBy] filters.
|
||||
///
|
||||
/// Cannot be used in combination with [endBefore], [endBeforeDocument], or
|
||||
/// [endAtDocument].
|
||||
Query endAt(List<dynamic> values) {
|
||||
assert(values != null);
|
||||
assert(!_parameters.containsKey('endBefore'));
|
||||
assert(!_parameters.containsKey('endAt'));
|
||||
assert(!_parameters.containsKey('endBeforeDocument'));
|
||||
assert(!_parameters.containsKey('endAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{'endAt': values});
|
||||
}
|
||||
|
||||
/// Creates and returns a new [Query] that ends before the provided document
|
||||
/// (exclusive). The end position is relative to the order of the query.
|
||||
/// The document must contain all of the fields provided in the orderBy of
|
||||
/// this query.
|
||||
///
|
||||
/// Cannot be used in combination with [endAt], [endBefore], or
|
||||
/// [endAtDocument].
|
||||
///
|
||||
/// See also:
|
||||
/// * [startAfterDocument] for a query that starts after document.
|
||||
/// * [startAtDocument] for a query that starts at a document.
|
||||
/// * [endAtDocument] for a query that ends at a document.
|
||||
Query endBeforeDocument(DocumentSnapshot documentSnapshot) {
|
||||
assert(documentSnapshot != null);
|
||||
assert(!_parameters.containsKey('endBefore'));
|
||||
assert(!_parameters.containsKey('endAt'));
|
||||
assert(!_parameters.containsKey('endBeforeDocument'));
|
||||
assert(!_parameters.containsKey('endAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{
|
||||
'endBeforeDocument': <String, dynamic>{
|
||||
'id': documentSnapshot.documentID,
|
||||
'path': documentSnapshot.reference.path,
|
||||
'data': documentSnapshot.data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Takes a list of [values], creates and returns a new [Query] that ends before
|
||||
/// the provided fields relative to the order of the query.
|
||||
///
|
||||
/// The [values] must be in order of [orderBy] filters.
|
||||
///
|
||||
/// Cannot be used in combination with [endAt], [endBeforeDocument], or
|
||||
/// [endBeforeDocument]
|
||||
Query endBefore(List<dynamic> values) {
|
||||
assert(values != null);
|
||||
assert(!_parameters.containsKey('endBefore'));
|
||||
assert(!_parameters.containsKey('endAt'));
|
||||
assert(!_parameters.containsKey('endBeforeDocument'));
|
||||
assert(!_parameters.containsKey('endAtDocument'));
|
||||
return _copyWithParameters(<String, dynamic>{'endBefore': values});
|
||||
}
|
||||
|
||||
/// Creates and returns a new Query that's additionally limited to only return up
|
||||
/// to the specified number of documents.
|
||||
Query limit(int length) {
|
||||
assert(!_parameters.containsKey('limit'));
|
||||
return _copyWithParameters(<String, dynamic>{'limit': length});
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// A QuerySnapshot contains zero or more DocumentSnapshot objects.
|
||||
class QuerySnapshot {
|
||||
QuerySnapshot._(Map<dynamic, dynamic> data, this._firestore)
|
||||
: documents = List<DocumentSnapshot>.generate(data['documents'].length,
|
||||
(int index) {
|
||||
return DocumentSnapshot._(
|
||||
data['paths'][index],
|
||||
_asStringKeyedMap(data['documents'][index]),
|
||||
SnapshotMetadata._(
|
||||
data['metadatas'][index]['hasPendingWrites'],
|
||||
data['metadatas'][index]['isFromCache'],
|
||||
),
|
||||
_firestore,
|
||||
);
|
||||
}),
|
||||
documentChanges = List<DocumentChange>.generate(
|
||||
data['documentChanges'].length, (int index) {
|
||||
return DocumentChange._(
|
||||
data['documentChanges'][index],
|
||||
_firestore,
|
||||
);
|
||||
});
|
||||
|
||||
/// Gets a list of all the documents included in this snapshot
|
||||
final List<DocumentSnapshot> documents;
|
||||
|
||||
/// An array of the documents that changed since the last snapshot. If this
|
||||
/// is the first snapshot, all documents will be in the list as Added changes.
|
||||
final List<DocumentChange> documentChanges;
|
||||
|
||||
final Firestore _firestore;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// Metadata about a snapshot, describing the state of the snapshot.
|
||||
class SnapshotMetadata {
|
||||
SnapshotMetadata._(this.hasPendingWrites, this.isFromCache);
|
||||
|
||||
/// Whether the snapshot contains the result of local writes that have not yet
|
||||
/// been committed to the backend.
|
||||
///
|
||||
/// If your listener has opted into metadata updates (via
|
||||
/// [DocumentListenOptions] or [QueryListenOptions]) you will receive another
|
||||
/// snapshot with `hasPendingWrites` equal to `false` once the writes have been
|
||||
/// committed to the backend.
|
||||
final bool hasPendingWrites;
|
||||
|
||||
/// Whether the snapshot was created from cached data rather than guaranteed
|
||||
/// up-to-date server data.
|
||||
///
|
||||
/// If your listener has opted into metadata updates (via
|
||||
/// [DocumentListenOptions] or [QueryListenOptions]) you will receive another
|
||||
/// snapshot with `isFomCache` equal to `false` once the client has received
|
||||
/// up-to-date data from the backend.
|
||||
final bool isFromCache;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// An enumeration of firestore source types.
|
||||
enum Source {
|
||||
/// Causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back to
|
||||
/// returning cached data if the server can't be reached.
|
||||
serverAndCache,
|
||||
|
||||
/// Causes Firestore to avoid the cache, generating an error if the server cannot be reached. Note
|
||||
/// that the cache will still be updated if the server request succeeds. Also note that
|
||||
/// latency-compensation still takes effect, so any pending write operations will be visible in the
|
||||
/// returned data (merged into the server-provided data).
|
||||
server,
|
||||
|
||||
/// Causes Firestore to immediately return a value from the cache, ignoring the server completely
|
||||
/// (implying that the returned value may be stale with respect to the value on the server). If
|
||||
/// there is no data in the cache to satisfy the [get()] or [getDocuments()] call,
|
||||
/// [DocumentReference.get()] will return an error and [Query.getDocuments()] will return an empty
|
||||
/// [QuerySnapshot] with no documents.
|
||||
cache,
|
||||
}
|
||||
|
||||
/// Converts [Source] to [String]
|
||||
String _getSourceString(Source source) {
|
||||
assert(source != null);
|
||||
if (source == Source.server) {
|
||||
return 'server';
|
||||
}
|
||||
if (source == Source.cache) {
|
||||
return 'cache';
|
||||
}
|
||||
return 'default';
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
// Copyright 2018, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
const int _kThousand = 1000;
|
||||
const int _kMillion = 1000000;
|
||||
const int _kBillion = 1000000000;
|
||||
|
||||
void _check(bool expr, String name, int value) {
|
||||
if (!expr) {
|
||||
throw ArgumentError("Timestamp $name out of range: $value");
|
||||
}
|
||||
}
|
||||
|
||||
/// A Timestamp represents a point in time independent of any time zone or calendar,
|
||||
/// represented as seconds and fractions of seconds at nanosecond resolution in UTC
|
||||
/// Epoch time. It is encoded using the Proleptic Gregorian Calendar which extends
|
||||
/// the Gregorian calendar backwards to year one. It is encoded assuming all minutes
|
||||
/// are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table
|
||||
/// is needed for interpretation. Range is from 0001-01-01T00:00:00Z to
|
||||
/// 9999-12-31T23:59:59.999999999Z. By restricting to that range, we ensure that we
|
||||
/// can convert to and from RFC 3339 date strings.
|
||||
///
|
||||
/// For more information, see [the reference timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto)
|
||||
class Timestamp implements Comparable<Timestamp> {
|
||||
Timestamp(this._seconds, this._nanoseconds) {
|
||||
_validateRange(_seconds, _nanoseconds);
|
||||
}
|
||||
|
||||
factory Timestamp.fromMillisecondsSinceEpoch(int milliseconds) {
|
||||
final int seconds = (milliseconds / _kThousand).floor();
|
||||
final int nanoseconds = (milliseconds - seconds * _kThousand) * _kMillion;
|
||||
return Timestamp(seconds, nanoseconds);
|
||||
}
|
||||
|
||||
factory Timestamp.fromMicrosecondsSinceEpoch(int microseconds) {
|
||||
final int seconds = (microseconds / _kMillion).floor();
|
||||
final int nanoseconds = (microseconds - seconds * _kMillion) * _kThousand;
|
||||
return Timestamp(seconds, nanoseconds);
|
||||
}
|
||||
|
||||
factory Timestamp.fromDate(DateTime date) {
|
||||
return Timestamp.fromMicrosecondsSinceEpoch(date.microsecondsSinceEpoch);
|
||||
}
|
||||
|
||||
factory Timestamp.now() {
|
||||
return Timestamp.fromMicrosecondsSinceEpoch(
|
||||
DateTime.now().microsecondsSinceEpoch);
|
||||
}
|
||||
|
||||
final int _seconds;
|
||||
final int _nanoseconds;
|
||||
|
||||
static const int _kStartOfTime = -62135596800;
|
||||
static const int _kEndOfTime = 253402300800;
|
||||
|
||||
int get seconds => _seconds;
|
||||
|
||||
int get nanoseconds => _nanoseconds;
|
||||
|
||||
int get millisecondsSinceEpoch =>
|
||||
(seconds * _kThousand + nanoseconds / _kMillion).floor();
|
||||
|
||||
int get microsecondsSinceEpoch =>
|
||||
(seconds * _kMillion + nanoseconds / _kThousand).floor();
|
||||
|
||||
DateTime toDate() {
|
||||
return DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(seconds, nanoseconds);
|
||||
@override
|
||||
bool operator ==(dynamic o) =>
|
||||
o is Timestamp && o.seconds == seconds && o.nanoseconds == nanoseconds;
|
||||
@override
|
||||
int compareTo(Timestamp other) {
|
||||
if (seconds == other.seconds) {
|
||||
return nanoseconds.compareTo(other.nanoseconds);
|
||||
}
|
||||
|
||||
return seconds.compareTo(other.seconds);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "Timestamp(seconds=$seconds, nanoseconds=$nanoseconds)";
|
||||
}
|
||||
|
||||
static void _validateRange(int seconds, int nanoseconds) {
|
||||
_check(nanoseconds >= 0, 'nanoseconds', nanoseconds);
|
||||
_check(nanoseconds < _kBillion, 'nanoseconds', nanoseconds);
|
||||
_check(seconds >= _kStartOfTime, 'seconds', seconds);
|
||||
_check(seconds < _kEndOfTime, 'seconds', seconds);
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
typedef Future<dynamic> TransactionHandler(Transaction transaction);
|
||||
|
||||
class Transaction {
|
||||
@visibleForTesting
|
||||
Transaction(this._transactionId, this._firestore);
|
||||
|
||||
int _transactionId;
|
||||
Firestore _firestore;
|
||||
|
||||
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,
|
||||
});
|
||||
if (result != null) {
|
||||
return DocumentSnapshot._(
|
||||
documentReference.path,
|
||||
result['data']?.cast<String, dynamic>(),
|
||||
SnapshotMetadata._(result['metadata']['hasPendingWrites'],
|
||||
result['metadata']['isFromCache']),
|
||||
_firestore);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> delete(DocumentReference documentReference) async {
|
||||
return Firestore.channel
|
||||
.invokeMethod<void>('Transaction#delete', <String, dynamic>{
|
||||
'app': _firestore.app.name,
|
||||
'transactionId': _transactionId,
|
||||
'path': documentReference.path,
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2017, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
/// Utility class for generating Firebase child node keys.
|
||||
///
|
||||
/// Since the Flutter plugin API is asynchronous, there's no way for us
|
||||
/// to use the native SDK to generate the node key synchronously and we
|
||||
/// have to do it ourselves if we want to be able to reference the
|
||||
/// newly-created node synchronously.
|
||||
///
|
||||
/// This code is based on a Firebase blog post and ported to Dart.
|
||||
/// https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html
|
||||
class PushIdGenerator {
|
||||
static const String PUSH_CHARS =
|
||||
'-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
static final Random _random = Random();
|
||||
|
||||
static int _lastPushTime;
|
||||
|
||||
static final List<int> _lastRandChars = List<int>(12);
|
||||
|
||||
static String generatePushChildName() {
|
||||
int now = DateTime.now().millisecondsSinceEpoch;
|
||||
final bool duplicateTime = (now == _lastPushTime);
|
||||
_lastPushTime = now;
|
||||
|
||||
final List<String> timeStampChars = List<String>(8);
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
timeStampChars[i] = PUSH_CHARS[now % 64];
|
||||
now = (now / 64).floor();
|
||||
}
|
||||
assert(now == 0);
|
||||
|
||||
final StringBuffer result = StringBuffer(timeStampChars.join());
|
||||
|
||||
if (!duplicateTime) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
_lastRandChars[i] = _random.nextInt(64);
|
||||
}
|
||||
} else {
|
||||
_incrementArray();
|
||||
}
|
||||
for (int i = 0; i < 12; i++) {
|
||||
result.write(PUSH_CHARS[_lastRandChars[i]]);
|
||||
}
|
||||
assert(result.length == 20);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static void _incrementArray() {
|
||||
for (int i = 11; i >= 0; i--) {
|
||||
if (_lastRandChars[i] != 63) {
|
||||
_lastRandChars[i] = _lastRandChars[i] + 1;
|
||||
return;
|
||||
}
|
||||
_lastRandChars[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
// Copyright 2018, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of cloud_firestore;
|
||||
|
||||
/// A [WriteBatch] is a series of write operations to be performed as one unit.
|
||||
///
|
||||
/// Operations done on a [WriteBatch] do not take effect until you [commit].
|
||||
///
|
||||
/// Once committed, no further operations can be performed on the [WriteBatch],
|
||||
/// nor can it be committed again.
|
||||
class WriteBatch {
|
||||
WriteBatch._(this._firestore)
|
||||
: _handle = Firestore.channel.invokeMethod<dynamic>(
|
||||
'WriteBatch#create', <String, dynamic>{'app': _firestore.app.name});
|
||||
|
||||
final Firestore _firestore;
|
||||
Future<dynamic> _handle;
|
||||
final List<Future<dynamic>> _actions = <Future<dynamic>>[];
|
||||
|
||||
/// Indicator to whether or not this [WriteBatch] has been committed.
|
||||
bool _committed = false;
|
||||
|
||||
/// Commits all of the writes in this write batch as a single atomic unit.
|
||||
///
|
||||
/// Calling this method prevents any future operations from being added.
|
||||
Future<void> commit() async {
|
||||
if (!_committed) {
|
||||
_committed = true;
|
||||
await Future.wait<dynamic>(_actions);
|
||||
await Firestore.channel.invokeMethod<void>(
|
||||
'WriteBatch#commit', <String, dynamic>{'handle': await _handle});
|
||||
} else {
|
||||
throw StateError("This batch has already been committed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes the document referred to by [document].
|
||||
void delete(DocumentReference document) {
|
||||
if (!_committed) {
|
||||
_handle.then((dynamic handle) {
|
||||
_actions.add(
|
||||
Firestore.channel.invokeMethod<void>(
|
||||
'WriteBatch#delete',
|
||||
<String, dynamic>{
|
||||
'app': _firestore.app.name,
|
||||
'handle': handle,
|
||||
'path': document.path,
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
throw StateError(
|
||||
"This batch has been committed and can no longer be changed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes to the document referred to by [document].
|
||||
///
|
||||
/// If the document does not yet exist, it will be created.
|
||||
///
|
||||
/// If [merge] is true, the provided data will be merged into an
|
||||
/// existing document instead of overwriting.
|
||||
void setData(DocumentReference document, Map<String, dynamic> data,
|
||||
{bool merge = false}) {
|
||||
if (!_committed) {
|
||||
_handle.then((dynamic handle) {
|
||||
_actions.add(
|
||||
Firestore.channel.invokeMethod<void>(
|
||||
'WriteBatch#setData',
|
||||
<String, dynamic>{
|
||||
'app': _firestore.app.name,
|
||||
'handle': handle,
|
||||
'path': document.path,
|
||||
'data': data,
|
||||
'options': <String, bool>{'merge': merge},
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
throw StateError(
|
||||
"This batch has been committed and can no longer be changed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates fields in the document referred to by [document].
|
||||
///
|
||||
/// If the document does not exist, the operation will fail.
|
||||
void updateData(DocumentReference document, Map<String, dynamic> data) {
|
||||
if (!_committed) {
|
||||
_handle.then((dynamic handle) {
|
||||
_actions.add(
|
||||
Firestore.channel.invokeMethod<void>(
|
||||
'WriteBatch#updateData',
|
||||
<String, dynamic>{
|
||||
'app': _firestore.app.name,
|
||||
'handle': handle,
|
||||
'path': document.path,
|
||||
'data': data,
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
throw StateError(
|
||||
"This batch has been committed and can no longer be changed.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
name: cloud_firestore
|
||||
description: Flutter plugin for Cloud Firestore, a cloud-hosted, noSQL database with
|
||||
live synchronization and offline support on Android and iOS.
|
||||
author: Flutter Team <flutter-dev@googlegroups.com>
|
||||
homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore
|
||||
version: 0.12.5
|
||||
|
||||
environment:
|
||||
# You must be using Flutter >=1.5.0 or Dart >=2.3.0
|
||||
sdk: '>=2.3.0-dev.0.1 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter_web: any
|
||||
flutter_web_ui: any
|
||||
firebase_core: any
|
||||
meta: "^1.0.5"
|
||||
collection: "^1.14.3"
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^1.4.0
|
||||
build_web_compilers: ^2.0.0
|
||||
pedantic: ^1.0.0
|
||||
|
||||
dependency_overrides:
|
||||
flutter_web:
|
||||
git:
|
||||
url: https://github.com/flutter/flutter_web
|
||||
path: packages/flutter_web
|
||||
flutter_web_ui:
|
||||
git:
|
||||
url: https://github.com/flutter/flutter_web
|
||||
path: packages/flutter_web_ui
|
||||
firebase_core:
|
||||
git:
|
||||
url: https://github.com/j3g/flutter_web_plugins.git
|
||||
path: packages/firebase_core
|
|
@ -1,133 +0,0 @@
|
|||
## 0.4.0+3
|
||||
|
||||
* Add missing template type parameter to `invokeMethod` calls.
|
||||
* Bump minimum Flutter version to 1.5.0.
|
||||
* Replace invokeMethod with invokeMapMethod wherever necessary.
|
||||
|
||||
## 0.4.0+2
|
||||
|
||||
* Update user agent name. Set to `flutter-fire-core` for consistency with other
|
||||
libraries.
|
||||
|
||||
## 0.4.0+1
|
||||
|
||||
* Send user agent to Firebase.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
* Update Android dependencies to latest.
|
||||
|
||||
## 0.3.4
|
||||
|
||||
* Updates Android firebase-core dependency to a version that is compatible with other Flutterfire plugins.
|
||||
|
||||
## 0.3.3
|
||||
|
||||
* Remove Gradle BoM to avoid Gradle version issues.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
* Move Android dependency to Gradle BoM to help maintain compatability
|
||||
with other FlutterFire plugins.
|
||||
|
||||
## 0.3.1+1
|
||||
|
||||
* Add nil check on static functions to prevent crashes or unwanted behaviors.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
* Remove an assertion that can interfere with hot-restart.
|
||||
|
||||
## 0.3.0+2
|
||||
|
||||
* Remove categories.
|
||||
|
||||
## 0.3.0+1
|
||||
|
||||
* Log a more detailed warning at build time about the previous AndroidX
|
||||
migration.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
* **Breaking change**. Migrate from the deprecated original Android Support
|
||||
Library to AndroidX. This shouldn't result in any functional changes, but it
|
||||
requires any Android apps using this plugin to [also
|
||||
migrate](https://developer.android.com/jetpack/androidx/migrate) if they're
|
||||
using the original support library.
|
||||
|
||||
## 0.2.5+1
|
||||
|
||||
* Bump Android dependencies to latest.
|
||||
|
||||
## 0.2.5
|
||||
|
||||
* Bump Android and Firebase dependency versions.
|
||||
|
||||
## 0.2.4
|
||||
|
||||
* Updated Gradle tooling to match Android Studio 3.1.2.
|
||||
|
||||
## 0.2.3
|
||||
|
||||
* Updated Google Play Services dependencies to version 15.0.0.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
* Simplified podspec for Cocoapods 1.5.0, avoiding link issues in app archives.
|
||||
|
||||
## 0.2.1
|
||||
|
||||
* Fix setting project ID on Android.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
* **Breaking change**. Options API is now async to interoperate with native code that configures Firebase apps.
|
||||
* Provide a getter for the default app
|
||||
* Fix setting of GCM sender ID on iOS
|
||||
|
||||
## 0.1.2
|
||||
|
||||
* Fix projectID on iOS
|
||||
|
||||
## 0.1.1
|
||||
|
||||
* Fix behavior of constructor for named Firebase apps.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
* **Breaking change**. Set SDK constraints to match the Flutter beta release.
|
||||
|
||||
## 0.0.7
|
||||
|
||||
* Fixed Dart 2 type errors.
|
||||
|
||||
## 0.0.6
|
||||
|
||||
* Enabled use in Swift projects.
|
||||
|
||||
## 0.0.5
|
||||
|
||||
* Moved to the io.flutter.plugins org.
|
||||
|
||||
## 0.0.4
|
||||
|
||||
* Fixed warnings from the Dart 2.0 analyzer.
|
||||
* Simplified and upgraded Android project template to Android SDK 27.
|
||||
* Updated package description.
|
||||
|
||||
# 0.0.3
|
||||
|
||||
* **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin
|
||||
3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in
|
||||
order to use this version of the plugin. Instructions can be found
|
||||
[here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1).
|
||||
|
||||
## 0.0.2
|
||||
|
||||
* Fixes for database URL on Android
|
||||
* Make GCM sender id optional on Android
|
||||
* Relax GMS dependency to 11.+
|
||||
|
||||
## 0.0.1
|
||||
|
||||
* Initial Release
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,16 +0,0 @@
|
|||
# Firebase Core for Flutter
|
||||
|
||||
[](https://pub.dartlang.org/packages/firebase_core)
|
||||
|
||||
A Flutter plugin to use the Firebase Core API, which enables connecting to multiple Firebase apps.
|
||||
|
||||
For Flutter plugins for other Firebase products, see [FlutterFire.md](https://github.com/flutter/plugins/blob/master/FlutterFire.md).
|
||||
|
||||
*Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/flutter/flutter/issues) and [Pull Requests](https://github.com/flutter/plugins/pulls) are most welcome!
|
||||
|
||||
## Usage
|
||||
To use this plugin, add `firebase_core` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).
|
||||
|
||||
## Getting Started
|
||||
|
||||
See the `example` directory for a complete sample app using Firebase Core.
|
|
@ -1,51 +0,0 @@
|
|||
def PLUGIN = "firebase_core";
|
||||
def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning";
|
||||
gradle.buildFinished { buildResult ->
|
||||
if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) {
|
||||
println ' *********************************************************'
|
||||
println 'WARNING: This version of ' + PLUGIN + ' will break your Android build if it or its dependencies aren\'t compatible with AndroidX.'
|
||||
println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.'
|
||||
println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.'
|
||||
println ' *********************************************************'
|
||||
rootProject.ext.set(ANDROIDX_WARNING, true);
|
||||
}
|
||||
}
|
||||
|
||||
group 'io.flutter.plugins.firebase.core'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
dependencies {
|
||||
api 'com.google.firebase:firebase-core:16.0.9'
|
||||
implementation 'com.google.firebase:firebase-common:16.1.0'
|
||||
}
|
||||
}
|