├── .github
├── workflows
│ ├── scripts
│ │ ├── remoteconfig.template.json
│ │ ├── firestore.indexes.json
│ │ ├── .firebaserc
│ │ ├── storage.rules
│ │ ├── install-flutter.sh
│ │ ├── database.rules.json
│ │ ├── install-tools.sh
│ │ ├── drive-app.sh
│ │ ├── firestore.rules
│ │ ├── firebase.json
│ │ └── start-firebase-emulator.sh
│ └── ci.yml
└── PULL_REQUEST_TEMPLATE.md
├── packages
└── firebase_snippets_app
│ ├── remoteconfig.template.json
│ ├── firestore.indexes.json
│ ├── .firebaserc
│ ├── android
│ ├── gradle.properties
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values-night
│ │ │ │ │ │ └── styles.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── firebase_snippets_app
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ ├── google-services.json
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── .gitignore
│ ├── settings.gradle
│ └── build.gradle
│ ├── storage.rules
│ ├── database.rules.json
│ ├── .metadata
│ ├── lib
│ ├── snippets
│ │ ├── crashlytics.dart
│ │ ├── firestore_odm
│ │ │ ├── address_model.dart
│ │ │ └── user_model.dart
│ │ ├── snippet_base.dart
│ │ ├── firestore_odm.dart
│ │ ├── cloud_functions.dart
│ │ ├── remote_config.dart
│ │ ├── ml_model_downloader.dart
│ │ ├── cloud_messaging.dart
│ │ ├── firebase_performance.dart
│ │ ├── dynamic_links.dart
│ │ ├── database.dart
│ │ ├── analytics.dart
│ │ ├── cloud_storage.dart
│ │ └── auth.dart
│ ├── model
│ │ ├── restaurant.dart
│ │ └── firestore_add_data_custom_objects_snippet.dart
│ ├── widgets
│ │ ├── user.dart
│ │ ├── users_list.dart
│ │ └── user_info_streambuilder.dart
│ ├── firebase_options.dart
│ ├── main.dart
│ └── app.dart
│ ├── firestore.rules
│ ├── integration_test
│ └── app_test.dart
│ ├── README.md
│ ├── .gitignore
│ ├── firebase.json
│ ├── test
│ └── widget_test.dart
│ ├── pubspec.yaml
│ ├── analysis_options.yaml
│ └── pubspec.lock
├── analysis_options.yml
├── .gitignore
├── CONTRIBUTING.md
├── README.md
└── LICENSE
/.github/workflows/scripts/remoteconfig.template.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/remoteconfig.template.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.github/workflows/scripts/firestore.indexes.json:
--------------------------------------------------------------------------------
1 | {
2 | "indexes": [],
3 | "fieldOverrides": []
4 | }
5 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/firestore.indexes.json:
--------------------------------------------------------------------------------
1 | {
2 | "indexes": [],
3 | "fieldOverrides": []
4 | }
5 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "flutter-fire-snippets"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "flutter-fire-snippets"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 | android.defaults.buildfeatures.buildconfig=true
5 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/storage.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 | service firebase.storage {
3 | match /b/{bucket}/o {
4 | match /{allPaths=**} {
5 | allow read, write: if true;
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/storage.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 | service firebase.storage {
3 | match /b/{bucket}/o {
4 | match /{allPaths=**} {
5 | allow read, write: if true;
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/snippets-flutter/HEAD/packages/firebase_snippets_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/snippets-flutter/HEAD/packages/firebase_snippets_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/snippets-flutter/HEAD/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/snippets-flutter/HEAD/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/snippets-flutter/HEAD/packages/firebase_snippets_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.github/workflows/scripts/install-flutter.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BRANCH=$1
4 | git clone https://github.com/flutter/flutter.git --depth 1 -b $BRANCH "$GITHUB_WORKSPACE/_flutter"
5 | echo "$GITHUB_WORKSPACE/_flutter/bin" >> $GITHUB_PATH
6 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/kotlin/com/example/firebase_snippets_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.firebase_snippets_app
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/database.rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | ".read": "false",
4 | ".write": "false",
5 | "posts": {
6 | ".read": "true",
7 | ".write": "true"
8 | },
9 | "users": {
10 | ".read": "true",
11 | ".write": "true"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/database.rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | ".read": "false",
4 | ".write": "false",
5 | "posts": {
6 | ".read": "true",
7 | ".write": "true"
8 | },
9 | "users": {
10 | ".read": "true",
11 | ".write": "true"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/.github/workflows/scripts/install-tools.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | flutter config --no-analytics
4 | flutter pub global activate melos 1.1.0
5 | echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
6 | echo "$GITHUB_WORKSPACE/_flutter/.pub-cache/bin" >> $GITHUB_PATH
7 | echo "$GITHUB_WORKSPACE/_flutter/bin/cache/dart-sdk/bin" >> $GITHUB_PATH
8 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip
7 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/drive-app.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PROJECT_NAME=$1
4 | TARGET_PATH="packages/$PROJECT_NAME/"
5 |
6 | # The && are necessary for some reason when using the Android Emulator action
7 | pushd "$TARGET_PATH" || exit &&
8 | flutter clean &&
9 | flutter pub get &&
10 | dart format . &&
11 | flutter test integration_test
12 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: db747aa1331bd95bc9b3874c842261ca2d302cd5
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/snippets/crashlytics.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_snippets_app/snippets/snippet_base.dart';
2 |
3 | class CrashlyticsSnippets implements DocSnippet {
4 | @override
5 | void runAll() {
6 | // Crashlytics testing isn't yet supported,
7 | // since it requires crashing the app to set up
8 | // and this will require additional CI work
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/firestore.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 | service cloud.firestore {
3 | match /databases/{database}/documents {
4 | match /{document=**} {
5 | allow read, write: if false;
6 | }
7 |
8 | match /users/{document=**} {
9 | allow read, write;
10 | }
11 |
12 | match /cities/{document=**} {
13 | allow read, write;
14 | }
15 |
16 | match /restaurants/{document=**} {
17 | allow read, write;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/firestore.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 | service cloud.firestore {
3 | match /databases/{database}/documents {
4 | match /{document=**} {
5 | allow read, write: if false;
6 | }
7 |
8 | match /users/{document=**} {
9 | allow read, write;
10 | }
11 |
12 | match /cities/{document=**} {
13 | allow read, write;
14 | }
15 |
16 | match /restaurants/{document=**} {
17 | allow read, write;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | _Description of what this PR is changing or adding:_
2 |
3 | _Issues fixed by this PR (if any):_
4 |
5 | ## Risk Level
6 | - [ ] No risk
7 | - [ ] Somewhat Risky
8 | - [ ] High risk
9 |
10 | ## Pre-submit checklist
11 | - [ ] This PR follows the [Google Developer Documentation Style Guidelines](https://developers.google.com/style)
12 | - [ ] This PR uses [semantic line breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks)
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/snippets/firestore_odm/address_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'address_model.g.dart';
4 |
5 | // [START sub_collections_define]
6 | @JsonSerializable()
7 | class Address {
8 | final String streetName;
9 |
10 | Address({required this.streetName});
11 |
12 | factory Address.fromJson(Map json) =>
13 | _$AddressFromJson(json);
14 |
15 | Map toJson() => _$AddressToJson(this);
16 | }
17 | // [END sub_collections_define]
18 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/integration_test/app_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_snippets_app/main.dart' as app;
2 | import 'package:flutter_test/flutter_test.dart';
3 | import 'package:integration_test/integration_test.dart';
4 |
5 | void main() {
6 | IntegrationTestWidgetsFlutterBinding.ensureInitialized();
7 |
8 | group('end-to-end test', () {
9 | testWidgets(
10 | 'run the app, which calls all firebase snippet functions on start',
11 | (WidgetTester tester) async {
12 | app.main();
13 | await tester.pumpAndSettle();
14 | });
15 | });
16 | }
17 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/README.md:
--------------------------------------------------------------------------------
1 | # firebase_snippets_app
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/analysis_options.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/snippets/snippet_base.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | abstract class DocSnippet {
16 | void runAll();
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 | *.g.dart
34 |
35 | # Web related
36 | lib/generated_plugin_registrant.dart
37 |
38 | # Symbolication related
39 | app.*.symbols
40 |
41 | # Obfuscation related
42 | app.*.map.json
43 |
44 | # Android Studio will place build artifacts here
45 | /android/app/debug
46 | /android/app/profile
47 | /android/app/release
48 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "database": {
3 | "rules": "database.rules.json"
4 | },
5 | "firestore": {
6 | "rules": "firestore.rules",
7 | "indexes": "firestore.indexes.json"
8 | },
9 | "hosting": {
10 | "public": "web",
11 | "ignore": [
12 | "firebase.json",
13 | "**/.*",
14 | "**/node_modules/**"
15 | ]
16 | },
17 | "storage": {
18 | "rules": "storage.rules"
19 | },
20 | "emulators": {
21 | "auth": {
22 | "port": 9099
23 | },
24 | "firestore": {
25 | "port": 8080
26 | },
27 | "database": {
28 | "port": 9000
29 | },
30 | "hosting": {
31 | "port": 3030
32 | },
33 | "pubsub": {
34 | "port": 8085
35 | },
36 | "storage": {
37 | "port": 9199
38 | },
39 | "ui": {
40 | "enabled": true
41 | }
42 | },
43 | "remoteconfig": {
44 | "template": "remoteconfig.template.json"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/model/restaurant.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | class Restaurant {
16 | final String name;
17 | double avgRating;
18 | int numRatings;
19 |
20 | Restaurant(
21 | this.name,
22 | this.avgRating,
23 | this.numRatings,
24 | );
25 |
26 | factory Restaurant.fromFirestore(Object? document) {
27 | return Restaurant("fake data", 3.4, 11);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "database": {
3 | "rules": "database.rules.json"
4 | },
5 | "firestore": {
6 | "rules": "firestore.rules",
7 | "indexes": "firestore.indexes.json"
8 | },
9 | "hosting": {
10 | "public": "web",
11 | "ignore": [
12 | "firebase.json",
13 | "**/.*",
14 | "**/node_modules/**"
15 | ]
16 | },
17 | "storage": {
18 | "rules": "storage.rules"
19 | },
20 | "emulators": {
21 | "auth": {
22 | "port": 9099
23 | },
24 | "firestore": {
25 | "port": 8080
26 | },
27 | "database": {
28 | "port": 9000
29 | },
30 | "hosting": {
31 | "port": 3030
32 | },
33 | "pubsub": {
34 | "port": 8085
35 | },
36 | "storage": {
37 | "port": 9199
38 | },
39 | "ui": {
40 | "enabled": true
41 | },
42 | "functions": {
43 | "port": 5001
44 | }
45 | },
46 | "remoteconfig": {
47 | "template": "remoteconfig.template.json"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/snippets/firestore_odm.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: non_constant_identifier_names
2 |
3 | import 'package:firebase_snippets_app/snippets/firestore_odm/user_model.dart';
4 | import 'package:firebase_snippets_app/snippets/snippet_base.dart';
5 |
6 | class ODMSnippets extends DocSnippet {
7 | @override
8 | void runAll() {
9 | /// testing ODM isn't yet supported.
10 | /// It's still in Alpha, and it will require additional CI work
11 | }
12 |
13 | void references_performQueries() async {
14 | // [START references_perform_queries]
15 | usersRef.whereName(isEqualTo: 'John');
16 | usersRef.whereAge(isGreaterThan: 18);
17 | usersRef.orderByAge();
18 | // ..etc!
19 | // [END references_perform_queries]
20 | }
21 |
22 | void subCollection_accessSubCollection() async {
23 | // [START sub_collection_access_sub_collection]
24 | AddressCollectionReference addressesRef =
25 | usersRef.doc('myDocumentID').addresses;
26 | // [END sub_collection_access_sub_collection]
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/snippets/firestore_odm/user_model.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: non_constant_identifier_names
2 |
3 | import 'package:cloud_firestore/cloud_firestore.dart';
4 | import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
5 | import 'package:firebase_snippets_app/snippets/firestore_odm/address_model.dart';
6 | import 'package:json_annotation/json_annotation.dart';
7 |
8 | part 'user_model.g.dart';
9 |
10 | @JsonSerializable()
11 | class User {
12 | User({
13 | required this.name,
14 | required this.age,
15 | required this.email,
16 | required this.address,
17 | }) {
18 | _$assertUser(this);
19 | }
20 |
21 | factory User.fromJson(Map json) => _$UserFromJson(json);
22 |
23 | final String name;
24 | final String email;
25 | final Address address;
26 |
27 | @Min(0)
28 | final int age;
29 |
30 | Map toJson() => _$UserToJson(this);
31 | }
32 | // [END defining_models]
33 |
34 | // [START references_collection_ref]
35 | @Collection('users')
36 | @Collection('users/*/addresses')
37 | final usersRef = UserCollectionReference();
38 | // [END references_collection_ref]
39 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement (CLA). You (or your employer) retain the copyright to your
10 | contribution; this simply gives us permission to use and redistribute your
11 | contributions as part of the project. Head over to
12 | to see your current agreements on file or
13 | to sign a new one.
14 |
15 | You generally only need to submit a CLA once, so if you've already submitted one
16 | (even if it was for a different project), you probably don't need to do it
17 | again.
18 |
19 | ## Code Reviews
20 |
21 | All submissions, including submissions by project members, require review. We
22 | use GitHub pull requests for this purpose. Consult
23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
24 | information on using pull requests.
25 |
26 | ## Community Guidelines
27 |
28 | This project follows
29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/).
30 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/widgets/user.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: use_key_in_widget_constructors
2 |
3 | import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | import '../snippets/firestore_odm/user_model.dart';
7 |
8 | class UserLabel extends StatelessWidget {
9 | const UserLabel(this.id);
10 |
11 | final String id;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return FirestoreBuilder(
16 | // Access a specific document
17 | ref: usersRef.doc(id),
18 | builder: (context, AsyncSnapshot snapshot,
19 | Widget? child) {
20 | if (snapshot.hasError) return const Text('Something went wrong!');
21 | if (!snapshot.hasData) return const Text('Loading user...');
22 |
23 | // Access the UserDocumentSnapshot
24 | UserDocumentSnapshot documentSnapshot = snapshot.requireData;
25 |
26 | if (!documentSnapshot.exists) {
27 | return const Text('User does not exist.');
28 | }
29 |
30 | User user = documentSnapshot.data!;
31 |
32 | return Text('User name: ${user.name}, age ${user.age}');
33 | });
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.9.0'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:8.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | classpath 'com.google.gms:google-services:4.3.15'
12 | classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
13 |
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 |
23 | subprojects {
24 | afterEvaluate { project ->
25 | if (project.hasProperty('android')) {
26 | project.android {
27 | if (namespace == null) {
28 | namespace project.group
29 | }
30 | }
31 | }
32 | }
33 | }
34 | }
35 |
36 | rootProject.buildDir = '../build'
37 | subprojects {
38 | project.buildDir = "${rootProject.buildDir}/${project.name}"
39 | }
40 | subprojects {
41 | project.evaluationDependsOn(':app')
42 | }
43 |
44 | tasks.register("clean", Delete) {
45 | delete rootProject.buildDir
46 | }
47 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/widgets/users_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | import '../snippets/firestore_odm/user_model.dart';
5 |
6 | // Not currently in the docs, so not currently being tested.
7 | class UsersList extends StatelessWidget {
8 | const UsersList({Key? key}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return FirestoreBuilder(
13 | ref: usersRef,
14 | builder: (context, AsyncSnapshot snapshot,
15 | Widget? child) {
16 | if (snapshot.hasError) return const Text('Something went wrong!');
17 | if (!snapshot.hasData) return const Text('Loading users...');
18 |
19 | // Access the QuerySnapshot
20 | UserQuerySnapshot querySnapshot = snapshot.requireData;
21 |
22 | return ListView.builder(
23 | itemCount: querySnapshot.docs.length,
24 | itemBuilder: (context, index) {
25 | // Access the User instance
26 | User user = querySnapshot.docs[index].data;
27 |
28 | return Text('User name: ${user.name}, age ${user.age}');
29 | },
30 | );
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "220375889386",
4 | "project_id": "flutter-fire-snippets",
5 | "storage_bucket": "flutter-fire-snippets.appspot.com"
6 | },
7 | "client": [
8 | {
9 | "client_info": {
10 | "mobilesdk_app_id": "1:220375889386:android:1a16e85eeab0d5896bae93",
11 | "android_client_info": {
12 | "package_name": "com.example.firebase_snippets_app"
13 | }
14 | },
15 | "oauth_client": [
16 | {
17 | "client_id": "220375889386-2k28ra1b5iq3p2qbh61ag1o4rt24asb6.apps.googleusercontent.com",
18 | "client_type": 3
19 | }
20 | ],
21 | "api_key": [
22 | {
23 | "current_key": "AIzaSyC2bbpFcMWgGpKKEmqNw57Al2vdV4QnNP0"
24 | }
25 | ],
26 | "services": {
27 | "appinvite_service": {
28 | "other_platform_oauth_client": [
29 | {
30 | "client_id": "220375889386-2k28ra1b5iq3p2qbh61ag1o4rt24asb6.apps.googleusercontent.com",
31 | "client_type": 3
32 | },
33 | {
34 | "client_id": "220375889386-8v73sv2lia3e7c12h0btp2tfbj0um4it.apps.googleusercontent.com",
35 | "client_type": 2,
36 | "ios_info": {
37 | "bundle_id": "com.fluttersnippets.app"
38 | }
39 | }
40 | ]
41 | }
42 | }
43 | }
44 | ],
45 | "configuration_version": "1"
46 | }
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/widgets/user_info_streambuilder.dart:
--------------------------------------------------------------------------------
1 | import 'package:cloud_firestore/cloud_firestore.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // [START listen_to_realtime_updates_listen_for_updates2]
5 | class UserInformation extends StatefulWidget {
6 | @override
7 | _UserInformationState createState() => _UserInformationState();
8 | }
9 |
10 | class _UserInformationState extends State {
11 | final Stream _usersStream =
12 | FirebaseFirestore.instance.collection('users').snapshots();
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return StreamBuilder(
17 | stream: _usersStream,
18 | builder: (BuildContext context, AsyncSnapshot snapshot) {
19 | if (snapshot.hasError) {
20 | return const Text('Something went wrong');
21 | }
22 |
23 | if (snapshot.connectionState == ConnectionState.waiting) {
24 | return const Text("Loading");
25 | }
26 |
27 | return ListView(
28 | children: snapshot.data!.docs
29 | .map((DocumentSnapshot document) {
30 | Map data =
31 | document.data()! as Map;
32 | return ListTile(
33 | title: Text(data['full_name']),
34 | subtitle: Text(data['company']),
35 | );
36 | })
37 | .toList()
38 | .cast(),
39 | );
40 | },
41 | );
42 | }
43 | }
44 | // [END listen_to_realtime_updates_listen_for_updates2]
45 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // This is a basic Flutter widget test.
16 | //
17 | // To perform an interaction with a widget in your test, use the WidgetTester
18 | // utility that Flutter provides. For example, you can send tap and scroll
19 | // gestures. You can also use WidgetTester to find child widgets in the widget
20 | // tree, read text, and verify that the values of widget properties are correct.
21 |
22 | import 'package:flutter_test/flutter_test.dart';
23 |
24 | void main() {
25 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
26 | // Build our app and trigger a frame.
27 | // await tester.pumpWidget(const MyApp());
28 |
29 | // Verify that our counter starts at 0.
30 | // expect(find.text('0'), findsOneWidget);
31 | // expect(find.text('1'), findsNothing);
32 | //
33 | // // Tap the '+' icon and trigger a frame.
34 | // await tester.tap(find.byIcon(Icons.add));
35 | // await tester.pump();
36 | //
37 | // // Verify that our counter has incremented.
38 | // expect(find.text('0'), findsNothing);
39 | // expect(find.text('1'), findsOneWidget);
40 | });
41 | }
42 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/start-firebase-emulator.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if ! [ -x "$(command -v firebase)" ]; then
3 | echo "❌ Firebase tools CLI is missing."
4 | exit 1
5 | fi
6 |
7 | if ! [ -x "$(command -v node)" ]; then
8 | echo "❌ Node.js is missing."
9 | exit 1
10 | fi
11 |
12 | if ! [ -x "$(command -v npm)" ]; then
13 | echo "❌ NPM is missing."
14 | exit 1
15 | fi
16 |
17 | export STORAGE_EMULATOR_DEBUG=true
18 | EMU_START_COMMAND="firebase emulators:start --only firestore --project flutter-fire-snippets"
19 |
20 | MAX_RETRIES=3
21 | MAX_CHECKATTEMPTS=60
22 | CHECKATTEMPTS_WAIT=1
23 |
24 | RETRIES=1
25 | while [ $RETRIES -le $MAX_RETRIES ]; do
26 |
27 | if [[ -z "${CI}" ]]; then
28 | echo "Starting Firebase Emulator Suite in foreground."
29 | $EMU_START_COMMAND
30 | exit 0
31 | else
32 | echo "Starting Firebase Emulator Suite in background."
33 | $EMU_START_COMMAND &
34 | CHECKATTEMPTS=1
35 | while [ $CHECKATTEMPTS -le $MAX_CHECKATTEMPTS ]; do
36 | sleep $CHECKATTEMPTS_WAIT
37 | if curl --output /dev/null --silent --fail http://localhost:8080; then
38 | # Check again since it can exit before the emulator is ready.
39 | sleep 15
40 | if curl --output /dev/null --silent --fail http://localhost:8080; then
41 | echo "Firebase Emulator Suite is online!"
42 | exit 0
43 | else
44 | echo "❌ Firebase Emulator exited after startup."
45 | exit 1
46 | fi
47 | fi
48 | echo "Waiting for Firebase Emulator Suite to come online, check $CHECKATTEMPTS of $MAX_CHECKATTEMPTS..."
49 | ((CHECKATTEMPTS = CHECKATTEMPTS + 1))
50 | done
51 | fi
52 |
53 | echo "Firebase Emulator Suite did not come online in $MAX_CHECKATTEMPTS checks. Try $RETRIES of $MAX_RETRIES."
54 | ((RETRIES = RETRIES + 1))
55 |
56 | done
57 | echo "Firebase Emulator Suite did not come online after $MAX_RETRIES attempts."
58 | exit 1
59 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/pubspec.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | name: firebase_snippets_app
16 | description: A new Flutter project.
17 |
18 | publish_to: 'none'
19 | version: 1.0.0+1
20 |
21 | environment:
22 | sdk: ">=2.16.1 <3.0.0"
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 | firebase_core: ^3.10.0
27 | cloud_firestore: ^5.6.1
28 | cloud_firestore_odm: ^1.0.0-dev.11
29 | cloud_functions: ^5.3.0
30 | firebase_remote_config: ^5.3.0
31 | firebase_analytics: ^11.4.0
32 | firebase_storage: ^12.4.0
33 | firebase_messaging: ^15.2.0
34 | firebase_dynamic_links: ^6.1.0
35 | firebase_ml_model_downloader: ^0.3.2
36 | firebase_auth: ^5.4.0
37 | path_provider: ^2.0.9
38 | firebase_database: ^11.3.0
39 | firebase_performance: ^0.10.1
40 | json_annotation: ^4.4.0
41 | google_sign_in: ^6.1.0
42 | flutter_facebook_auth: ^7.0.0
43 | twitter_login: ^4.4.2
44 | sign_in_with_apple: ^6.1.0
45 | crypto: ^3.0.1
46 | firebase_crashlytics: ^4.3.0
47 | firebase_auth_platform_interface: ^7.3.0
48 | http: ^1.2.2
49 | win32: ^5.5.4
50 |
51 | dev_dependencies:
52 | flutter_test:
53 | sdk: flutter
54 | integration_test:
55 | sdk: flutter
56 | flutter_lints: ^5.0.0
57 | build_runner: ^2.1.8
58 | cloud_firestore_odm_generator: ^1.0.0-dev.11
59 | json_serializable: ^6.1.5
60 |
61 | flutter:
62 | uses-material-design: true
63 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Run CI
2 |
3 | on:
4 | workflow_dispatch:
5 | pull_request:
6 | types: [opened, reopened, synchronize]
7 | paths:
8 | - "packages/**"
9 | - ".github/workflows"
10 | push:
11 | paths-ignore:
12 | - "**.md"
13 |
14 | jobs:
15 | android:
16 | runs-on: ubuntu-latest
17 | timeout-minutes: 30
18 | steps:
19 |
20 | - name: "Git Checkout"
21 | uses: actions/checkout@v2
22 |
23 | - name: Enable KVM
24 | run: |
25 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
26 | sudo udevadm control --reload-rules
27 | sudo udevadm trigger --name-match=kvm
28 |
29 | - name: "Install Node"
30 | uses: actions/setup-node@v2
31 | with:
32 | node-version: '20'
33 |
34 | - uses: actions/setup-java@v2
35 | name: "Install Java"
36 | with:
37 | distribution: 'temurin'
38 | java-version: '17'
39 |
40 | - name: "Install Flutter"
41 | run: |
42 | sh .github/workflows/scripts/install-flutter.sh stable
43 |
44 | - name: "Install Tools"
45 | run: |
46 | sh ./.github/workflows/scripts/install-tools.sh
47 | flutter config --no-enable-web --no-enable-ios --no-enable-macos-desktop
48 | sudo npm i -g firebase-tools
49 | #
50 | - name: "Start Firebase Emulator"
51 | run: |
52 | sh ./.github/workflows/scripts/start-firebase-emulator.sh
53 |
54 | - name: "Drive Example"
55 | uses: reactivecircus/android-emulator-runner@v2
56 | with:
57 | api-level: 28
58 | arch: x86_64
59 | disable-animations: true
60 | # Firebase Firestore works without Google Play Services, so we don't use the `googleapis`
61 | # emulator target as it's considerably slower on CI.
62 | target: default
63 | profile: Nexus 5X
64 | script: bash ./.github/workflows/scripts/drive-app.sh firebase_snippets_app
65 |
--------------------------------------------------------------------------------
/packages/firebase_snippets_app/lib/model/firestore_add_data_custom_objects_snippet.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:cloud_firestore/cloud_firestore.dart';
16 |
17 | // [START add_data_custom_objects]
18 | class City {
19 | final String? name;
20 | final String? state;
21 | final String? country;
22 | final bool? capital;
23 | final int? population;
24 | final List? regions;
25 |
26 | City({
27 | this.name,
28 | this.state,
29 | this.country,
30 | this.capital,
31 | this.population,
32 | this.regions,
33 | });
34 |
35 | factory City.fromFirestore(
36 | DocumentSnapshot