├── README.md ├── android ├── android.iml ├── app │ ├── app.iml │ ├── build.gradle │ ├── google-services.json │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ ├── com │ │ │ └── github │ │ │ │ └── putraxor │ │ │ │ └── firestore │ │ │ │ └── MainActivity.java │ │ └── io │ │ │ └── flutter │ │ │ └── plugins │ │ │ └── GeneratedPluginRegistrant.java │ │ └── res │ │ ├── drawable │ │ └── launch_background.xml │ │ ├── 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 │ │ └── values │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle ├── firestore_example.iml ├── lib ├── expense_form.dart ├── expense_list.dart ├── flutter_crud.dart └── main.dart ├── pubspec.lock ├── pubspec.yaml └── test └── widget_test.dart /README.md: -------------------------------------------------------------------------------- 1 | # firestore 2 | 3 | Simple Firestore with Flutter. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](http://flutter.io/). 9 | -------------------------------------------------------------------------------- /android/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withInputStream { stream -> 5 | localProperties.load(stream) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 25 19 | buildToolsVersion '25.0.3' 20 | 21 | lintOptions { 22 | disable 'InvalidPackage' 23 | } 24 | 25 | defaultConfig { 26 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 27 | applicationId "com.github.putraxor.firestore" 28 | minSdkVersion 16 29 | targetSdkVersion 25 30 | versionCode 1 31 | versionName "1.0" 32 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 33 | } 34 | 35 | buildTypes { 36 | release { 37 | // TODO: Add your own signing config for the release build. 38 | // Signing with the debug keys for now, so `flutter run --release` works. 39 | signingConfig signingConfigs.debug 40 | } 41 | } 42 | } 43 | 44 | flutter { 45 | source '../..' 46 | } 47 | 48 | dependencies { 49 | androidTestCompile 'com.android.support:support-annotations:25.2.0' 50 | androidTestCompile 'com.android.support.test:runner:0.5' 51 | androidTestCompile 'com.android.support.test:rules:0.5' 52 | } 53 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "10838166660", 4 | "firebase_url": "https://budget-8b9cb.firebaseio.com", 5 | "project_id": "budget-8b9cb", 6 | "storage_bucket": "budget-8b9cb.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:10838166660:android:7ad4850918c71fdc", 12 | "android_client_info": { 13 | "package_name": "com.github.putraxor.firestore" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "10838166660-0ufi41rg0i6c24t86njueifsii7isvrp.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.github.putraxor.firestore", 22 | "certificate_hash": "089461174c59e9b972867d06f01d383e79d9dc0d" 23 | } 24 | }, 25 | { 26 | "client_id": "10838166660-uil6j7jtmnknmnpme5fpehm7s3jgia3q.apps.googleusercontent.com", 27 | "client_type": 3 28 | } 29 | ], 30 | "api_key": [ 31 | { 32 | "current_key": "AIzaSyB_OShgJAMavP0GY4BGCQ2XpCnHp0Zst1o" 33 | } 34 | ], 35 | "services": { 36 | "analytics_service": { 37 | "status": 1 38 | }, 39 | "appinvite_service": { 40 | "status": 2, 41 | "other_platform_oauth_client": [ 42 | { 43 | "client_id": "10838166660-uil6j7jtmnknmnpme5fpehm7s3jgia3q.apps.googleusercontent.com", 44 | "client_type": 3 45 | } 46 | ] 47 | }, 48 | "ads_service": { 49 | "status": 2 50 | } 51 | } 52 | } 53 | ], 54 | "configuration_version": "1" 55 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/github/putraxor/firestore/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.putraxor.firestore; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | 6 | import com.google.firebase.FirebaseApp; 7 | 8 | import io.flutter.app.FlutterActivity; 9 | import io.flutter.plugins.GeneratedPluginRegistrant; 10 | 11 | public class MainActivity extends FlutterActivity { 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | FirebaseApp.initializeApp(this); 16 | Log.wtf("Main", "Why flutter stupid?"); 17 | GeneratedPluginRegistrant.registerWith(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java: -------------------------------------------------------------------------------- 1 | package io.flutter.plugins; 2 | 3 | import io.flutter.plugin.common.PluginRegistry; 4 | import io.flutter.plugins.firebase.firestore.FirestorePlugin; 5 | 6 | /** 7 | * Generated file. Do not edit. 8 | */ 9 | public final class GeneratedPluginRegistrant { 10 | public static void registerWith(PluginRegistry registry) { 11 | FirestorePlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebase.firestore.FirestorePlugin")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | maven { 5 | url "https://maven.google.com" 6 | } 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:2.3.3' 11 | classpath 'com.google.gms:google-services:3.1.1' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | maven { 19 | url "https://maven.google.com" 20 | } 21 | } 22 | } 23 | 24 | rootProject.buildDir = '../build' 25 | subprojects { 26 | project.buildDir = "${rootProject.buildDir}/${project.name}" 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/putraxor/firestore-flutter/100d591275575e36579ebd9d2da353aa4f12602a/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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-3.3-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | sdk.dir=/home/putraxor/android_sdk_linux/ 2 | flutter.sdk=/home/putraxor/flutter 3 | flutter.buildMode=debug -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withInputStream { stream -> plugins.load(stream) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /firestore_example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib/expense_form.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class ExpenseForm { 6 | 7 | final BuildContext context; 8 | 9 | ExpenseForm(this.context); 10 | 11 | Future show() async { 12 | return showDialog( 13 | context: context, 14 | barrierDismissible: false, // user must tap button! 15 | child: new AlertDialog( 16 | title: new Text('Expense Form'), 17 | content: new SingleChildScrollView( 18 | child: new ListBody( 19 | children: [ 20 | new Text('You will never be satisfied.'), 21 | new Text('You\’re like me. I’m never satisfied.'), 22 | ], 23 | ), 24 | ), 25 | actions: [ 26 | new FlatButton( 27 | child: new Text('Regret'), 28 | onPressed: () { 29 | Navigator.of(context).pop(); 30 | }, 31 | ), 32 | ], 33 | ), 34 | ); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /lib/expense_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:firebase_firestore/firebase_firestore.dart'; 3 | 4 | class ExpenseList extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | 8 | return new StreamBuilder( 9 | stream: Firestore.instance.collection("expenses").snapshots, 10 | builder: (BuildContext context, AsyncSnapshot snapshot) { 11 | if (!snapshot.hasData) return new Text("There is no expense"); 12 | return new ListView(children: getExpenseItems(snapshot)); 13 | }); 14 | } 15 | 16 | getExpenseItems(AsyncSnapshot snapshot) { 17 | return snapshot.data.documents 18 | .map((doc) => new ListTile(title: new Text(doc["name"]), subtitle: new Text(doc["amount"].toString()))) 19 | .toList(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/flutter_crud.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | void main() => runApp(new App()); 5 | 6 | ///APP 7 | class App extends StatelessWidget { 8 | 9 | var _routes = { 10 | ListScreen.routeName: (BuildContext context) => new ListScreen(), 11 | }; 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return new MaterialApp( 16 | title: 'Flutter CRUD', 17 | theme: new ThemeData(primarySwatch: Colors.blue, accentColor: Colors.lightBlue), 18 | home: new ListScreen(), 19 | routes: _routes, 20 | onGenerateRoute: (settings) { 21 | var path = settings.name.split('/'); 22 | final param = path.length > 1 ? path[1] : null; 23 | return new MaterialPageRoute( 24 | builder: (context) => new FormScreen(id: param), 25 | settings: settings, 26 | ); 27 | }, 28 | ); 29 | } 30 | } 31 | 32 | 33 | ///DTO 34 | class User { 35 | String name = ""; 36 | } 37 | 38 | 39 | ///LIST SCREEN 40 | class ListScreen extends StatefulWidget { 41 | static String routeName = "list-screen"; 42 | 43 | @override 44 | _ListScreenState createState() => new _ListScreenState(); 45 | } 46 | 47 | class _ListScreenState extends State { 48 | @override 49 | Widget build(BuildContext context) { 50 | return new Scaffold( 51 | appBar: new AppBar(title: new Text("User List")), 52 | body: new StreamBuilder( 53 | stream: Firestore.instance 54 | .collection("user") 55 | .snapshots, 56 | builder: (context, snapshot) { 57 | if (!snapshot.hasData) return new Center(child: new Text("Loading")); 58 | return new ListView( 59 | children: snapshot.data.documents.map((data) { 60 | return new ListTile( 61 | title: new Text(data['name']), 62 | onTap: () => Navigator.pushNamed(context, "${FormScreen.routeName}/${data.documentID}"), 63 | ); 64 | }).toList() 65 | ); 66 | }), 67 | floatingActionButton: new FloatingActionButton( 68 | child: new Icon(Icons.add), 69 | onPressed: () => Navigator.pushNamed(context, FormScreen.routeName)), 70 | ); 71 | } 72 | } 73 | 74 | ///FORM SCREEN 75 | class FormScreen extends StatefulWidget { 76 | String id; 77 | static String routeName = "form-screen"; 78 | 79 | 80 | FormScreen({this.id}); 81 | 82 | @override 83 | _FormScreenState createState() => new _FormScreenState(id: id); 84 | } 85 | 86 | class _FormScreenState extends State { 87 | String id; 88 | User user = new User(); 89 | final formKey = new GlobalKey(); 90 | 91 | _FormScreenState({this.id}); 92 | 93 | ///On save action 94 | _onSave() { 95 | var form = formKey.currentState; 96 | if (form.validate()) { 97 | form.save(); 98 | Firestore.instance 99 | .collection("user") 100 | .document(id).setData({'name': user.name}); 101 | Navigator.pop(context); 102 | } 103 | } 104 | 105 | @override 106 | Widget build(BuildContext context) { 107 | return new Scaffold( 108 | appBar: new AppBar(title: new Text("Form"), actions: [new FlatButton(onPressed: () => _onSave(), child: new Text("Save"))]), 109 | body: new StreamBuilder( 110 | stream: Firestore.instance 111 | .collection("user") 112 | .document(id) 113 | .snapshots, 114 | builder: (context, snapshot) { 115 | if (!snapshot.hasData) return new Center(child: new Text("Loading Form")); 116 | user.name = snapshot.data['name']; 117 | return new Form( 118 | key: formKey, 119 | child: new TextFormField( 120 | initialValue: "${user.name}", 121 | decoration: new InputDecoration(labelText: 'Name', hintText: "Type name", icon: new Icon(Icons.person_outline)), 122 | validator: (val) => val.length == 0 ? 'Define user\'s name.' : null, 123 | onSaved: (val) => user.name = val, 124 | ) 125 | ); 126 | } 127 | ), 128 | ); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_firestore/firebase_firestore.dart'; 2 | import 'package:firestore/expense_list.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | void main() { 6 | runApp(new MyApp()); 7 | } 8 | 9 | class MyApp extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | 13 | return new MaterialApp( 14 | title: 'Budget', 15 | theme: new ThemeData( 16 | primarySwatch: Colors.blueGrey, 17 | ), 18 | home: new MyHomePage(title: 'Expenses'), 19 | ); 20 | } 21 | } 22 | 23 | class MyHomePage extends StatefulWidget { 24 | MyHomePage({Key key, this.title}) : super(key: key); 25 | 26 | final String title; 27 | 28 | @override 29 | _MyHomePageState createState() => new _MyHomePageState(); 30 | } 31 | 32 | class _MyHomePageState extends State { 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return new Scaffold( 37 | appBar: new AppBar( 38 | title: new Text(widget.title), 39 | ), 40 | body: new ExpenseList(), 41 | floatingActionButton: new FloatingActionButton( 42 | onPressed: null, 43 | tooltip: 'Add Expense', 44 | child: new Icon(Icons.add), 45 | ), 46 | ); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See http://pub.dartlang.org/doc/glossary.html#lockfile 3 | packages: 4 | analyzer: 5 | description: 6 | name: analyzer 7 | url: "https://pub.dartlang.org" 8 | source: hosted 9 | version: "0.30.0+4" 10 | args: 11 | description: 12 | name: args 13 | url: "https://pub.dartlang.org" 14 | source: hosted 15 | version: "0.13.7" 16 | async: 17 | description: 18 | name: async 19 | url: "https://pub.dartlang.org" 20 | source: hosted 21 | version: "1.13.3" 22 | barback: 23 | description: 24 | name: barback 25 | url: "https://pub.dartlang.org" 26 | source: hosted 27 | version: "0.15.2+12" 28 | boolean_selector: 29 | description: 30 | name: boolean_selector 31 | url: "https://pub.dartlang.org" 32 | source: hosted 33 | version: "1.0.2" 34 | charcode: 35 | description: 36 | name: charcode 37 | url: "https://pub.dartlang.org" 38 | source: hosted 39 | version: "1.1.1" 40 | cli_util: 41 | description: 42 | name: cli_util 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "0.1.2+1" 46 | collection: 47 | description: 48 | name: collection 49 | url: "https://pub.dartlang.org" 50 | source: hosted 51 | version: "1.14.3" 52 | convert: 53 | description: 54 | name: convert 55 | url: "https://pub.dartlang.org" 56 | source: hosted 57 | version: "2.0.1" 58 | crypto: 59 | description: 60 | name: crypto 61 | url: "https://pub.dartlang.org" 62 | source: hosted 63 | version: "2.0.2+1" 64 | csslib: 65 | description: 66 | name: csslib 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.14.1" 70 | dart_style: 71 | description: 72 | name: dart_style 73 | url: "https://pub.dartlang.org" 74 | source: hosted 75 | version: "1.0.8" 76 | firebase_firestore: 77 | description: 78 | name: firebase_firestore 79 | url: "https://pub.dartlang.org" 80 | source: hosted 81 | version: "0.0.1+1" 82 | flutter: 83 | description: flutter 84 | source: sdk 85 | version: "0.0.37-dev" 86 | flutter_test: 87 | description: flutter 88 | source: sdk 89 | version: "0.0.15-dev" 90 | front_end: 91 | description: 92 | name: front_end 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "0.1.0-alpha.4.1" 96 | glob: 97 | description: 98 | name: glob 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.1.5" 102 | html: 103 | description: 104 | name: html 105 | url: "https://pub.dartlang.org" 106 | source: hosted 107 | version: "0.13.2" 108 | http: 109 | description: 110 | name: http 111 | url: "https://pub.dartlang.org" 112 | source: hosted 113 | version: "0.11.3+14" 114 | http_multi_server: 115 | description: 116 | name: http_multi_server 117 | url: "https://pub.dartlang.org" 118 | source: hosted 119 | version: "2.0.4" 120 | http_parser: 121 | description: 122 | name: http_parser 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "3.1.1" 126 | intl: 127 | description: 128 | name: intl 129 | url: "https://pub.dartlang.org" 130 | source: hosted 131 | version: "0.15.1" 132 | intl_translation: 133 | description: 134 | name: intl_translation 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.15.0" 138 | isolate: 139 | description: 140 | name: isolate 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "1.1.0" 144 | js: 145 | description: 146 | name: js 147 | url: "https://pub.dartlang.org" 148 | source: hosted 149 | version: "0.6.1" 150 | kernel: 151 | description: 152 | name: kernel 153 | url: "https://pub.dartlang.org" 154 | source: hosted 155 | version: "0.3.0-alpha.1.1" 156 | logging: 157 | description: 158 | name: logging 159 | url: "https://pub.dartlang.org" 160 | source: hosted 161 | version: "0.11.3+1" 162 | matcher: 163 | description: 164 | name: matcher 165 | url: "https://pub.dartlang.org" 166 | source: hosted 167 | version: "0.12.1+4" 168 | meta: 169 | description: 170 | name: meta 171 | url: "https://pub.dartlang.org" 172 | source: hosted 173 | version: "1.1.1" 174 | mime: 175 | description: 176 | name: mime 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "0.9.3" 180 | node_preamble: 181 | description: 182 | name: node_preamble 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "1.4.0" 186 | package_config: 187 | description: 188 | name: package_config 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "1.0.3" 192 | package_resolver: 193 | description: 194 | name: package_resolver 195 | url: "https://pub.dartlang.org" 196 | source: hosted 197 | version: "1.0.2" 198 | path: 199 | description: 200 | name: path 201 | url: "https://pub.dartlang.org" 202 | source: hosted 203 | version: "1.4.2" 204 | petitparser: 205 | description: 206 | name: petitparser 207 | url: "https://pub.dartlang.org" 208 | source: hosted 209 | version: "1.6.1" 210 | plugin: 211 | description: 212 | name: plugin 213 | url: "https://pub.dartlang.org" 214 | source: hosted 215 | version: "0.2.0+2" 216 | pool: 217 | description: 218 | name: pool 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "1.3.3" 222 | pub_semver: 223 | description: 224 | name: pub_semver 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "1.3.2" 228 | quiver: 229 | description: 230 | name: quiver 231 | url: "https://pub.dartlang.org" 232 | source: hosted 233 | version: "0.25.0" 234 | shelf: 235 | description: 236 | name: shelf 237 | url: "https://pub.dartlang.org" 238 | source: hosted 239 | version: "0.7.0" 240 | shelf_packages_handler: 241 | description: 242 | name: shelf_packages_handler 243 | url: "https://pub.dartlang.org" 244 | source: hosted 245 | version: "1.0.3" 246 | shelf_static: 247 | description: 248 | name: shelf_static 249 | url: "https://pub.dartlang.org" 250 | source: hosted 251 | version: "0.2.5" 252 | shelf_web_socket: 253 | description: 254 | name: shelf_web_socket 255 | url: "https://pub.dartlang.org" 256 | source: hosted 257 | version: "0.2.2" 258 | sky_engine: 259 | description: 260 | path: "../../../flutter/bin/cache/pkg/sky_engine" 261 | relative: true 262 | source: path 263 | version: "0.0.99" 264 | source_map_stack_trace: 265 | description: 266 | name: source_map_stack_trace 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "1.1.4" 270 | source_maps: 271 | description: 272 | name: source_maps 273 | url: "https://pub.dartlang.org" 274 | source: hosted 275 | version: "0.10.4" 276 | source_span: 277 | description: 278 | name: source_span 279 | url: "https://pub.dartlang.org" 280 | source: hosted 281 | version: "1.4.0" 282 | stack_trace: 283 | description: 284 | name: stack_trace 285 | url: "https://pub.dartlang.org" 286 | source: hosted 287 | version: "1.8.2" 288 | stream_channel: 289 | description: 290 | name: stream_channel 291 | url: "https://pub.dartlang.org" 292 | source: hosted 293 | version: "1.6.2" 294 | string_scanner: 295 | description: 296 | name: string_scanner 297 | url: "https://pub.dartlang.org" 298 | source: hosted 299 | version: "1.0.2" 300 | term_glyph: 301 | description: 302 | name: term_glyph 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "1.0.0" 306 | test: 307 | description: 308 | name: test 309 | url: "https://pub.dartlang.org" 310 | source: hosted 311 | version: "0.12.24+8" 312 | typed_data: 313 | description: 314 | name: typed_data 315 | url: "https://pub.dartlang.org" 316 | source: hosted 317 | version: "1.1.4" 318 | utf: 319 | description: 320 | name: utf 321 | url: "https://pub.dartlang.org" 322 | source: hosted 323 | version: "0.9.0+3" 324 | vector_math: 325 | description: 326 | name: vector_math 327 | url: "https://pub.dartlang.org" 328 | source: hosted 329 | version: "2.0.5" 330 | watcher: 331 | description: 332 | name: watcher 333 | url: "https://pub.dartlang.org" 334 | source: hosted 335 | version: "0.9.7+4" 336 | web_socket_channel: 337 | description: 338 | name: web_socket_channel 339 | url: "https://pub.dartlang.org" 340 | source: hosted 341 | version: "1.0.6" 342 | yaml: 343 | description: 344 | name: yaml 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "2.1.13" 348 | sdks: 349 | dart: ">=1.24.0 <2.0.0-dev.infinity" 350 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: firestore 2 | description: Simple Firestore with Flutter. 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | firebase_firestore: 0.0.1+1 8 | 9 | dev_dependencies: 10 | flutter_test: 11 | sdk: flutter 12 | 13 | 14 | # For information on the generic Dart part of this file, see the 15 | # following page: https://www.dartlang.org/tools/pub/pubspec 16 | 17 | # The following section is specific to Flutter. 18 | flutter: 19 | 20 | # The following line ensures that the Material Icons font is 21 | # included with your application, so that you can use the icons in 22 | # the Icons class. 23 | uses-material-design: true 24 | 25 | # To add assets to your application, add an assets section, like this: 26 | # assets: 27 | # - images/a_dot_burr.jpeg 28 | # - images/a_dot_ham.jpeg 29 | 30 | # An image asset can refer to one or more resolution-specific "variants", see 31 | # https://flutter.io/assets-and-images/#resolution-aware. 32 | 33 | # For details regarding adding assets from package dependencies, see 34 | # https://flutter.io/assets-and-images/#from-packages 35 | 36 | # To add custom fonts to your application, add a fonts section here, 37 | # in this "flutter" section. Each entry in this list should have a 38 | # "family" key with the font family name, and a "fonts" key with a 39 | # list giving the asset and other descriptors for the font. For 40 | # example: 41 | # fonts: 42 | # - family: Schyler 43 | # fonts: 44 | # - asset: fonts/Schyler-Regular.ttf 45 | # - asset: fonts/Schyler-Italic.ttf 46 | # style: italic 47 | # - family: Trajan Pro 48 | # fonts: 49 | # - asset: fonts/TrajanPro.ttf 50 | # - asset: fonts/TrajanPro_Bold.ttf 51 | # weight: 700 52 | # 53 | # For details regarding fonts from package dependencies, 54 | # see https://flutter.io/custom-fonts/#from-packages 55 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import '../lib/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(new MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | --------------------------------------------------------------------------------