├── .gitignore ├── .metadata ├── LICENSE.md ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── dev │ │ ├── google-services.json │ │ └── 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 │ │ │ └── values │ │ │ └── strings.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── venturearkstudio │ │ │ │ └── noteapp │ │ │ │ └── MainActivity.kt │ │ └── 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 │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── prod │ │ ├── google-services.json │ │ └── 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 │ │ │ └── values │ │ │ └── strings.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── fonts │ ├── Product-Sans-Bold-Italic.ttf │ ├── Product-Sans-Bold.ttf │ ├── Product-Sans-Italic.ttf │ └── Product-Sans-Regular.ttf └── lang │ ├── en.json │ └── zh.json ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ └── contents.xcworkspacedata └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app_localizations.dart ├── auth_widget_builder.dart ├── caches │ └── sharedpref │ │ └── shared_preference_helper.dart ├── constants │ ├── app_font_family.dart │ └── app_themes.dart ├── flavor.dart ├── main.dart ├── main_prod.dart ├── models │ ├── todo_model.dart │ └── user_model.dart ├── my_app.dart ├── providers │ ├── auth_provider.dart │ ├── language_provider.dart │ └── theme_provider.dart ├── routes.dart ├── services │ ├── firestore_database.dart │ ├── firestore_path.dart │ └── firestore_service.dart └── ui │ ├── auth │ ├── register_screen.dart │ └── sign_in_screen.dart │ ├── home │ └── home.dart │ ├── setting │ ├── setting_language_actions.dart │ └── setting_screen.dart │ ├── splash │ └── splash_screen.dart │ └── todo │ ├── create_edit_todo_screen.dart │ ├── empty_content.dart │ ├── todos_extra_actions.dart │ └── todos_screen.dart ├── media ├── flavor-step-1.png ├── flavor-step-1b.png ├── flavor-step-2.png ├── flavor-step-3.png ├── flavor-step-4.png ├── flavor-step-4b.png ├── flavor-step-5.png ├── flavor-step-5b.png ├── how-to-use-step2.png ├── how-to-use-step4a.png ├── how-to-use-step4b.png ├── how-to-use-step5.png ├── how-to-use-step6.png ├── how-to-use-step7.png ├── how-to-use-step8.png ├── how-to-use-step9.png ├── language_control.gif └── todo-app-screenshots.png ├── pubspec.lock └── pubspec.yaml /.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 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | /android/app/google-services.json 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Exceptions to above rules. 38 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 39 | -------------------------------------------------------------------------------- /.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: 0b8abb4724aa590dd0f429683339b1e045a1594d 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Ken Lee Chiaw Huat [kenaragorn@gmail.com](mailto:kenaragorn@gmail.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 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 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.create_flutter_provider_app"//com.example.create_flutter_provider_app 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 47 | multiDexEnabled true 48 | } 49 | 50 | buildTypes { 51 | release { 52 | // TODO: Add your own signing config for the release build. 53 | // Signing with the debug keys for now, so `flutter run --release` works. 54 | signingConfig signingConfigs.debug 55 | } 56 | } 57 | 58 | flavorDimensions "flavor-type" 59 | 60 | productFlavors { 61 | dev { 62 | dimension "flavor-type" 63 | applicationId "com.example.create_flutter_provider_app.dev" 64 | versionCode 1 65 | versionName "1.0" 66 | } 67 | prod{ 68 | dimension "flavor-type" 69 | applicationId "com.example.create_flutter_provider_app.prod" 70 | versionCode 1 71 | versionName "1.0" 72 | } 73 | } 74 | } 75 | 76 | flutter { 77 | source '../..' 78 | } 79 | 80 | dependencies { 81 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 82 | implementation 'com.android.support:multidex:1.0.3' 83 | testImplementation 'junit:junit:4.12' 84 | androidTestImplementation 'androidx.test:runner:1.1.1' 85 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 86 | } 87 | 88 | 89 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/dev/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "747799024060", 4 | "firebase_url": "https://note-app-dev.firebaseio.com", 5 | "project_id": "note-app-dev", 6 | "storage_bucket": "note-app-dev.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:747799024060:android:12a44c09b32bf75c3d5bb9", 12 | "android_client_info": { 13 | "package_name": "com.example.create_flutter_provider_app.dev" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "747799024060-0i7261mp5tipeb817cpcr7s0cn29ck0a.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyA_mDikkCUSSDXiwFKly7GlC25LJEJHsFA" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "747799024060-0i7261mp5tipeb817cpcr7s0cn29ck0a.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | ], 39 | "configuration_version": "1" 40 | } -------------------------------------------------------------------------------- /android/app/src/dev/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/dev/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/dev/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/dev/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/dev/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/dev/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/dev/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/dev/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/dev/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/dev/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/dev/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Note-Dev 4 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/venturearkstudio/noteapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.venturearkstudio.noteapp 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 10 | GeneratedPluginRegistrant.registerWith(flutterEngine); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Default App Name 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/prod/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "514413640785", 4 | "firebase_url": "https://note-app-prod-aa3d9.firebaseio.com", 5 | "project_id": "note-app-prod-aa3d9", 6 | "storage_bucket": "note-app-prod-aa3d9.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:514413640785:android:2a7848a3d2174f40098c70", 12 | "android_client_info": { 13 | "package_name": "com.example.create_flutter_provider_app.prod" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "514413640785-pb983pp7c9kdgthvq1vqp6q3fstqnusa.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyB9uzuxTzPD9HeR_h_I7yFoiQ8Nmo7Hirs" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "514413640785-pb983pp7c9kdgthvq1vqp6q3fstqnusa.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | ], 39 | "configuration_version": "1" 40 | } -------------------------------------------------------------------------------- /android/app/src/prod/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/prod/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/prod/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/prod/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/prod/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/prod/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/prod/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/prod/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/prod/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/android/app/src/prod/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/prod/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Note-Prod 4 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.3.3' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 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.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /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-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /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.withReader('UTF-8') { reader -> plugins.load(reader) } 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 | -------------------------------------------------------------------------------- /assets/fonts/Product-Sans-Bold-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/assets/fonts/Product-Sans-Bold-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/Product-Sans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/assets/fonts/Product-Sans-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Product-Sans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/assets/fonts/Product-Sans-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/Product-Sans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/assets/fonts/Product-Sans-Regular.ttf -------------------------------------------------------------------------------- /assets/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "splashTitle": "Welcome to ", 3 | "alertDialogTitle": "Alert", 4 | "alertDialogMessage": "This will logout. Are you sure?", 5 | "alertDialogCancelBtn": "Cancel", 6 | "alertDialogYesBtn": "Yes", 7 | "loginTxtEmail": "Email", 8 | "loginTxtPassword": "Password", 9 | "loginBtnSignIn": "Sign In", 10 | "loginBtnSignUp": "Sign Up", 11 | "loginTxtDontHaveAccount": "Don't have an account?", 12 | "loginTxtHaveAccount": "Already have an account?", 13 | "loginBtnLinkCreateAccount": "Create account", 14 | "loginBtnLinkSignIn": "Sign in", 15 | "loginTxtErrorEmail": "Please enter an email", 16 | "loginTxtErrorPassword": "Please enter a password with 6+ chars long", 17 | "loginTxtErrorSignIn": "Invalid email and/or password", 18 | "homeAppBarTitle": "Todos", 19 | "settingAppTitle": "Setting", 20 | "settingThemeListTitle": "Dark theme", 21 | "settingThemeListSubTitle": "Turn On the Dark Side", 22 | "settingLogoutListTitle": "Logout", 23 | "settingLogoutListSubTitle": "Log me out from here", 24 | "settingLogoutButton": "Logout", 25 | "settingLanguageListTitle": "Language", 26 | "settingLanguageListSubTitle": "Set Your Prefer Language", 27 | "settingPopUpToggleEnglish": "Change to English", 28 | "settingPopUpToggleChinese": "Change to Chinese", 29 | "todosSnackBarContent": "Deleted ", 30 | "todosSnackBarActionLbl": "Undo", 31 | "todosErrorTopMsgTxt": "Something went wrong", 32 | "todosErrorBottomMsgTxt": "Can't load data right now", 33 | "todosDismissibleMsgTxt": "Delete", 34 | "todosPopUpToggleAllComplete": "Mark all complete", 35 | "todosPopUpToggleClearCompleted": "Clear all completed", 36 | "todosCreateEditAppBarTitleNewTxt": "New Todo", 37 | "todosCreateEditAppBarTitleEditTxt": "Edit Todo", 38 | "todosCreateEditTaskNameTxt": "Todo Name", 39 | "todosCreateEditNotesTxt": "Notes", 40 | "todosCreateEditTaskNameValidatorMsg": "Name can't be empty", 41 | "todosCreateEditCompletedTxt": "Completed ?", 42 | "todosEmptyTopMsgDefaultTxt": "Nothing here", 43 | "todosEmptyBottomDefaultMsgTxt": "Add a new item to get started" 44 | } -------------------------------------------------------------------------------- /assets/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "splashTitle": "欢迎来到 ", 3 | "alertDialogTitle": "警报", 4 | "alertDialogMessage": "这将注销。 你确定吗?", 5 | "alertDialogCancelBtn": "取消", 6 | "alertDialogYesBtn": "是", 7 | "loginTxtEmail": "电子邮件", 8 | "loginTxtPassword": "密码", 9 | "loginBtnSignIn": "登入", 10 | "loginBtnSignUp": "注册", 11 | "loginTxtDontHaveAccount": "还没有帐号?", 12 | "loginTxtHaveAccount": "已经有帐号了?", 13 | "loginBtnLinkCreateAccount": "创建帐号", 14 | "loginBtnLinkSignIn": "登入", 15 | "loginTxtErrorEmail": "请输入电子邮件", 16 | "loginTxtErrorPassword": "请输入超过6个字符的密码", 17 | "loginTxtErrorSignIn": "无效的电子邮件和/或密码", 18 | "homeAppBarTitle": "全部", 19 | "settingAppTitle": "设置", 20 | "settingThemeListTitle": "黑暗主题", 21 | "settingThemeListSubTitle": "打开黑暗的一面", 22 | "settingLogoutListTitle": "登出", 23 | "settingLogoutListSubTitle": "从这里注销我", 24 | "settingLogoutButton": "登出", 25 | "settingLanguageListTitle": "语言", 26 | "settingLanguageListSubTitle": "设定您的偏好语言", 27 | "settingPopUpToggleEnglish": "改成英文", 28 | "settingPopUpToggleChinese": "改成中文", 29 | "todosSnackBarContent": "已删除 ", 30 | "todosSnackBarActionLbl": "撤消", 31 | "todosErrorTopMsgTxt": "出问题了", 32 | "todosErrorBottomMsgTxt": "现在无法加载数据", 33 | "todosDismissibleMsgTxt": "删除", 34 | "todosPopUpToggleAllComplete": "标记所有完成", 35 | "todosPopUpToggleClearCompleted": "清除所有已完成", 36 | "todosCreateEditAppBarTitleNewTxt": "新渡渡鸟", 37 | "todosCreateEditAppBarTitleEditTxt": "编辑一切", 38 | "todosCreateEditTaskNameTxt": "待办事项名称", 39 | "todosCreateEditNotesTxt": "笔记", 40 | "todosCreateEditTaskNameValidatorMsg": "名称不能为空", 41 | "todosCreateEditCompletedTxt": "完成了吗 ?", 42 | "todosEmptyTopMsgDefaultTxt": "这里没有什么", 43 | "todosEmptyBottomDefaultMsgTxt": "添加新项目以开始" 44 | } -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 18 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 19 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXCopyFilesBuildPhase section */ 23 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 24 | isa = PBXCopyFilesBuildPhase; 25 | buildActionMask = 2147483647; 26 | dstPath = ""; 27 | dstSubfolderSpec = 10; 28 | files = ( 29 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 30 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 31 | ); 32 | name = "Embed Frameworks"; 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 39 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 40 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 41 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 42 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 43 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 44 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 45 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 46 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 47 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 48 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 61 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 9740EEB11CF90186004384FC /* Flutter */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 3B80C3931E831B6300D905FE /* App.framework */, 72 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 73 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 74 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 75 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 76 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 77 | ); 78 | name = Flutter; 79 | sourceTree = ""; 80 | }; 81 | 97C146E51CF9000F007C117D = { 82 | isa = PBXGroup; 83 | children = ( 84 | 9740EEB11CF90186004384FC /* Flutter */, 85 | 97C146F01CF9000F007C117D /* Runner */, 86 | 97C146EF1CF9000F007C117D /* Products */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 97C146EF1CF9000F007C117D /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 97C146EE1CF9000F007C117D /* Runner.app */, 94 | ); 95 | name = Products; 96 | sourceTree = ""; 97 | }; 98 | 97C146F01CF9000F007C117D /* Runner */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 102 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 103 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 104 | 97C147021CF9000F007C117D /* Info.plist */, 105 | 97C146F11CF9000F007C117D /* Supporting Files */, 106 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 107 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 108 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 109 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 110 | ); 111 | path = Runner; 112 | sourceTree = ""; 113 | }; 114 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 97C146ED1CF9000F007C117D /* Runner */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 127 | buildPhases = ( 128 | 9740EEB61CF901F6004384FC /* Run Script */, 129 | 97C146EA1CF9000F007C117D /* Sources */, 130 | 97C146EB1CF9000F007C117D /* Frameworks */, 131 | 97C146EC1CF9000F007C117D /* Resources */, 132 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 133 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = Runner; 140 | productName = Runner; 141 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 97C146E61CF9000F007C117D /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 1020; 151 | ORGANIZATIONNAME = "The Chromium Authors"; 152 | TargetAttributes = { 153 | 97C146ED1CF9000F007C117D = { 154 | CreatedOnToolsVersion = 7.3.1; 155 | LastSwiftMigration = 1100; 156 | }; 157 | }; 158 | }; 159 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 160 | compatibilityVersion = "Xcode 3.2"; 161 | developmentRegion = en; 162 | hasScannedForEncodings = 0; 163 | knownRegions = ( 164 | en, 165 | Base, 166 | ); 167 | mainGroup = 97C146E51CF9000F007C117D; 168 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 169 | projectDirPath = ""; 170 | projectRoot = ""; 171 | targets = ( 172 | 97C146ED1CF9000F007C117D /* Runner */, 173 | ); 174 | }; 175 | /* End PBXProject section */ 176 | 177 | /* Begin PBXResourcesBuildPhase section */ 178 | 97C146EC1CF9000F007C117D /* Resources */ = { 179 | isa = PBXResourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 183 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 184 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 185 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXResourcesBuildPhase section */ 190 | 191 | /* Begin PBXShellScriptBuildPhase section */ 192 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 193 | isa = PBXShellScriptBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | inputPaths = ( 198 | ); 199 | name = "Thin Binary"; 200 | outputPaths = ( 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | shellPath = /bin/sh; 204 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 205 | }; 206 | 9740EEB61CF901F6004384FC /* Run Script */ = { 207 | isa = PBXShellScriptBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | inputPaths = ( 212 | ); 213 | name = "Run Script"; 214 | outputPaths = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 219 | }; 220 | /* End PBXShellScriptBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | 97C146EA1CF9000F007C117D /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 228 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | /* End PBXSourcesBuildPhase section */ 233 | 234 | /* Begin PBXVariantGroup section */ 235 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 236 | isa = PBXVariantGroup; 237 | children = ( 238 | 97C146FB1CF9000F007C117D /* Base */, 239 | ); 240 | name = Main.storyboard; 241 | sourceTree = ""; 242 | }; 243 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 97C147001CF9000F007C117D /* Base */, 247 | ); 248 | name = LaunchScreen.storyboard; 249 | sourceTree = ""; 250 | }; 251 | /* End PBXVariantGroup section */ 252 | 253 | /* Begin XCBuildConfiguration section */ 254 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 255 | isa = XCBuildConfiguration; 256 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_ANALYZER_NONNULL = YES; 260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_ENABLE_MODULES = YES; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 265 | CLANG_WARN_BOOL_CONVERSION = YES; 266 | CLANG_WARN_COMMA = YES; 267 | CLANG_WARN_CONSTANT_CONVERSION = YES; 268 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 279 | CLANG_WARN_STRICT_PROTOTYPES = YES; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_NS_ASSERTIONS = NO; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | SDKROOT = iphoneos; 299 | SUPPORTED_PLATFORMS = iphoneos; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | VALIDATE_PRODUCT = YES; 302 | }; 303 | name = Profile; 304 | }; 305 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 306 | isa = XCBuildConfiguration; 307 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 308 | buildSettings = { 309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 310 | CLANG_ENABLE_MODULES = YES; 311 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 312 | ENABLE_BITCODE = NO; 313 | FRAMEWORK_SEARCH_PATHS = ( 314 | "$(inherited)", 315 | "$(PROJECT_DIR)/Flutter", 316 | ); 317 | INFOPLIST_FILE = Runner/Info.plist; 318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 319 | LIBRARY_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "$(PROJECT_DIR)/Flutter", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = com.venturearkstudio.noteapp; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 326 | SWIFT_VERSION = 5.0; 327 | VERSIONING_SYSTEM = "apple-generic"; 328 | }; 329 | name = Profile; 330 | }; 331 | 97C147031CF9000F007C117D /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 334 | buildSettings = { 335 | ALWAYS_SEARCH_USER_PATHS = NO; 336 | CLANG_ANALYZER_NONNULL = YES; 337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 338 | CLANG_CXX_LIBRARY = "libc++"; 339 | CLANG_ENABLE_MODULES = YES; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 342 | CLANG_WARN_BOOL_CONVERSION = YES; 343 | CLANG_WARN_COMMA = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 347 | CLANG_WARN_EMPTY_BODY = YES; 348 | CLANG_WARN_ENUM_CONVERSION = YES; 349 | CLANG_WARN_INFINITE_RECURSION = YES; 350 | CLANG_WARN_INT_CONVERSION = YES; 351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 352 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 356 | CLANG_WARN_STRICT_PROTOTYPES = YES; 357 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | DEBUG_INFORMATION_FORMAT = dwarf; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | ENABLE_TESTABILITY = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 375 | GCC_WARN_UNDECLARED_SELECTOR = YES; 376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 377 | GCC_WARN_UNUSED_FUNCTION = YES; 378 | GCC_WARN_UNUSED_VARIABLE = YES; 379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 380 | MTL_ENABLE_DEBUG_INFO = YES; 381 | ONLY_ACTIVE_ARCH = YES; 382 | SDKROOT = iphoneos; 383 | TARGETED_DEVICE_FAMILY = "1,2"; 384 | }; 385 | name = Debug; 386 | }; 387 | 97C147041CF9000F007C117D /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_ANALYZER_NONNULL = YES; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 402 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 409 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 412 | CLANG_WARN_STRICT_PROTOTYPES = YES; 413 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 419 | ENABLE_NS_ASSERTIONS = NO; 420 | ENABLE_STRICT_OBJC_MSGSEND = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu99; 422 | GCC_NO_COMMON_BLOCKS = YES; 423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 425 | GCC_WARN_UNDECLARED_SELECTOR = YES; 426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 427 | GCC_WARN_UNUSED_FUNCTION = YES; 428 | GCC_WARN_UNUSED_VARIABLE = YES; 429 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 430 | MTL_ENABLE_DEBUG_INFO = NO; 431 | SDKROOT = iphoneos; 432 | SUPPORTED_PLATFORMS = iphoneos; 433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 434 | TARGETED_DEVICE_FAMILY = "1,2"; 435 | VALIDATE_PRODUCT = YES; 436 | }; 437 | name = Release; 438 | }; 439 | 97C147061CF9000F007C117D /* Debug */ = { 440 | isa = XCBuildConfiguration; 441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | CLANG_ENABLE_MODULES = YES; 445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 446 | ENABLE_BITCODE = NO; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "$(PROJECT_DIR)/Flutter", 450 | ); 451 | INFOPLIST_FILE = Runner/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | LIBRARY_SEARCH_PATHS = ( 454 | "$(inherited)", 455 | "$(PROJECT_DIR)/Flutter", 456 | ); 457 | PRODUCT_BUNDLE_IDENTIFIER = com.venturearkstudio.noteapp; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 461 | SWIFT_VERSION = 5.0; 462 | VERSIONING_SYSTEM = "apple-generic"; 463 | }; 464 | name = Debug; 465 | }; 466 | 97C147071CF9000F007C117D /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 471 | CLANG_ENABLE_MODULES = YES; 472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 473 | ENABLE_BITCODE = NO; 474 | FRAMEWORK_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | INFOPLIST_FILE = Runner/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 480 | LIBRARY_SEARCH_PATHS = ( 481 | "$(inherited)", 482 | "$(PROJECT_DIR)/Flutter", 483 | ); 484 | PRODUCT_BUNDLE_IDENTIFIER = com.venturearkstudio.noteapp; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 487 | SWIFT_VERSION = 5.0; 488 | VERSIONING_SYSTEM = "apple-generic"; 489 | }; 490 | name = Release; 491 | }; 492 | /* End XCBuildConfiguration section */ 493 | 494 | /* Begin XCConfigurationList section */ 495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 496 | isa = XCConfigurationList; 497 | buildConfigurations = ( 498 | 97C147031CF9000F007C117D /* Debug */, 499 | 97C147041CF9000F007C117D /* Release */, 500 | 249021D3217E4FDB00AE95B9 /* Profile */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 97C147061CF9000F007C117D /* Debug */, 509 | 97C147071CF9000F007C117D /* Release */, 510 | 249021D4217E4FDB00AE95B9 /* Profile */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | /* End XCConfigurationList section */ 516 | }; 517 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 518 | } 519 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | noteapp 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/app_localizations.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | 7 | class AppLocalizations { 8 | final Locale locale; 9 | 10 | AppLocalizations(this.locale); 11 | 12 | // Helper method to keep the code in the widgets concise 13 | // Localizations are accessed using an InheritedWidget "of" syntax 14 | static AppLocalizations of(BuildContext context) { 15 | return Localizations.of(context, AppLocalizations)!; 16 | } 17 | 18 | //This is the static member for allowing simple access to the delegate from the MaterialApp 19 | static const LocalizationsDelegate delegate = 20 | _AppLocalizationsDelegate(); 21 | 22 | Map _localizedStrings = Map(); 23 | 24 | Future load() async { 25 | // Load the language JSON file from the "lang" folder 26 | String jsonString = 27 | await rootBundle.loadString('lang/${locale.languageCode}.json'); 28 | Map jsonMap = json.decode(jsonString); 29 | 30 | _localizedStrings = jsonMap.map((key, value) { 31 | return MapEntry(key, value.toString()); 32 | }); 33 | 34 | return true; 35 | } 36 | 37 | // This method will be called from every widgets which needs a localized text 38 | String translate(String key) { 39 | return _localizedStrings[key] ?? key; 40 | } 41 | } 42 | 43 | // LocalizationsDelegate is a factory for a set of localized resources 44 | // In this case, the localized strings will be gotten in an AppLocalizations object 45 | class _AppLocalizationsDelegate 46 | extends LocalizationsDelegate { 47 | const _AppLocalizationsDelegate(); 48 | 49 | @override 50 | bool isSupported(Locale locale) { 51 | // Include all of your supported language codes here 52 | return ['en', 'zh'].contains(locale.languageCode); 53 | } 54 | 55 | @override 56 | Future load(Locale locale) async { 57 | // AppLocalizations class is where the JSON loading actually runs 58 | AppLocalizations localizations = new AppLocalizations(locale); 59 | await localizations.load(); 60 | return localizations; 61 | } 62 | 63 | @override 64 | bool shouldReload(_AppLocalizationsDelegate old) => false; 65 | } 66 | -------------------------------------------------------------------------------- /lib/auth_widget_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/models/user_model.dart'; 3 | import 'package:noteapp/providers/auth_provider.dart'; 4 | import 'package:noteapp/services/firestore_database.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | /* 8 | * This class is mainly to help with creating user dependent object that 9 | * need to be available by all downstream widgets. 10 | * Thus, this widget builder is a must to live above [MaterialApp]. 11 | * As we rely on uid to decide which main screen to display (eg: Home or Sign In), 12 | * this class will helps to create all providers needed that depends on 13 | * the user logged data uid. 14 | */ 15 | class AuthWidgetBuilder extends StatelessWidget { 16 | const AuthWidgetBuilder( 17 | {required Key key, required this.builder, required this.databaseBuilder}) 18 | : super(key: key); 19 | final Widget Function(BuildContext, AsyncSnapshot) builder; 20 | final FirestoreDatabase Function(BuildContext context, String uid) 21 | databaseBuilder; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | final authService = Provider.of(context, listen: false); 26 | return StreamBuilder( 27 | stream: authService.user, 28 | builder: (BuildContext context, AsyncSnapshot snapshot) { 29 | final UserModel? user = snapshot.data; 30 | if (user != null) { 31 | /* 32 | * For any other Provider services that rely on user data can be 33 | * added to the following MultiProvider list. 34 | * Once a user has been detected, a re-build will be initiated. 35 | */ 36 | return MultiProvider( 37 | providers: [ 38 | Provider.value(value: user), 39 | Provider( 40 | create: (context) => databaseBuilder(context, user.uid), 41 | ), 42 | ], 43 | child: builder(context, snapshot), 44 | ); 45 | } 46 | return builder(context, snapshot); 47 | }, 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/caches/sharedpref/shared_preference_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | 3 | class SharedPreferenceHelper { 4 | Future? _sharedPreference; 5 | static const String is_dark_mode = "is_dark_mode"; 6 | static const String language_code = "language_code"; 7 | 8 | SharedPreferenceHelper() { 9 | _sharedPreference = SharedPreferences.getInstance(); 10 | } 11 | 12 | //Theme module 13 | Future changeTheme(bool value) { 14 | return _sharedPreference!.then((prefs) { 15 | return prefs.setBool(is_dark_mode, value); 16 | }); 17 | } 18 | 19 | Future get isDarkMode { 20 | return _sharedPreference!.then((prefs) { 21 | return prefs.getBool(is_dark_mode) ?? false; 22 | }); 23 | } 24 | 25 | //Locale module 26 | Future? get appLocale { 27 | return _sharedPreference?.then((prefs) { 28 | return prefs.getString(language_code) ?? 'en'; 29 | }); 30 | } 31 | 32 | Future changeLanguage(String value) { 33 | return _sharedPreference!.then((prefs) { 34 | return prefs.setString(language_code, value); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/constants/app_font_family.dart: -------------------------------------------------------------------------------- 1 | class AppFontFamily{ 2 | AppFontFamily._(); 3 | 4 | static String productSans = "ProductSans"; 5 | static String roboto = "Roboto"; 6 | } -------------------------------------------------------------------------------- /lib/constants/app_themes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/constants/app_font_family.dart'; 3 | 4 | class AppThemes { 5 | AppThemes._(); 6 | 7 | //constants color range for light theme 8 | static const Color _lightPrimaryColor = Colors.black; 9 | static const Color _lightPrimaryVariantColor = Colors.white; 10 | static const Color _lightSecondaryColor = Colors.green; 11 | static const Color _lightOnPrimaryColor = Colors.black; 12 | static const Color _lightButtonPrimaryColor = Colors.orangeAccent; 13 | static const Color _lightAppBarColor = Colors.orangeAccent; 14 | static Color _lightIconColor = Colors.orangeAccent; 15 | static Color _lightSnackBarBackgroundErrorColor = Colors.redAccent; 16 | 17 | //text theme for light theme 18 | static final TextStyle _lightScreenHeadingTextStyle = 19 | TextStyle(fontSize: 20.0, color: _lightOnPrimaryColor); 20 | static final TextStyle _lightScreenTaskNameTextStyle = 21 | TextStyle(fontSize: 16.0, color: _lightOnPrimaryColor); 22 | static final TextStyle _lightScreenTaskDurationTextStyle = 23 | TextStyle(fontSize: 14.0, color: Colors.grey); 24 | static final TextStyle _lightScreenButtonTextStyle = TextStyle( 25 | fontSize: 14.0, color: _lightOnPrimaryColor, fontWeight: FontWeight.w500); 26 | static final TextStyle _lightScreenCaptionTextStyle = TextStyle( 27 | fontSize: 12.0, color: _lightAppBarColor, fontWeight: FontWeight.w100); 28 | 29 | static final TextTheme _lightTextTheme = TextTheme( 30 | headline: _lightScreenHeadingTextStyle, 31 | body1: _lightScreenTaskNameTextStyle, 32 | body2: _lightScreenTaskDurationTextStyle, 33 | button: _lightScreenButtonTextStyle, 34 | title: _lightScreenTaskNameTextStyle, 35 | subhead: _lightScreenTaskNameTextStyle, 36 | caption: _lightScreenCaptionTextStyle, 37 | ); 38 | 39 | //constants color range for dark theme 40 | static const Color _darkPrimaryColor = Colors.white; 41 | static const Color _darkPrimaryVariantColor = Colors.black; 42 | static const Color _darkSecondaryColor = Colors.white; 43 | static const Color _darkOnPrimaryColor = Colors.white; 44 | static const Color _darkButtonPrimaryColor = Colors.deepPurpleAccent; 45 | static const Color _darkAppBarColor = Colors.deepPurpleAccent; 46 | static Color _darkIconColor = Colors.deepPurpleAccent; 47 | static Color _darkSnackBarBackgroundErrorColor = Colors.redAccent; 48 | 49 | //text theme for dark theme 50 | static final TextStyle _darkScreenHeadingTextStyle = 51 | _lightScreenHeadingTextStyle.copyWith(color: _darkOnPrimaryColor); 52 | static final TextStyle _darkScreenTaskNameTextStyle = 53 | _lightScreenTaskNameTextStyle.copyWith(color: _darkOnPrimaryColor); 54 | static final TextStyle _darkScreenTaskDurationTextStyle = 55 | _lightScreenTaskDurationTextStyle; 56 | static final TextStyle _darkScreenButtonTextStyle = TextStyle( 57 | fontSize: 14.0, color: _darkOnPrimaryColor, fontWeight: FontWeight.w500); 58 | static final TextStyle _darkScreenCaptionTextStyle = TextStyle( 59 | fontSize: 12.0, color: _darkAppBarColor, fontWeight: FontWeight.w100); 60 | 61 | static final TextTheme _darkTextTheme = TextTheme( 62 | headline: _darkScreenHeadingTextStyle, 63 | body1: _darkScreenTaskNameTextStyle, 64 | body2: _darkScreenTaskDurationTextStyle, 65 | button: _darkScreenButtonTextStyle, 66 | title: _darkScreenTaskNameTextStyle, 67 | subhead: _darkScreenTaskNameTextStyle, 68 | caption: _darkScreenCaptionTextStyle, 69 | ); 70 | 71 | //the light theme 72 | static final ThemeData lightTheme = ThemeData( 73 | fontFamily: AppFontFamily.productSans, 74 | scaffoldBackgroundColor: _lightPrimaryVariantColor, 75 | floatingActionButtonTheme: FloatingActionButtonThemeData( 76 | backgroundColor: _lightButtonPrimaryColor, 77 | ), 78 | appBarTheme: AppBarTheme( 79 | color: _lightAppBarColor, 80 | iconTheme: IconThemeData(color: _lightOnPrimaryColor), 81 | textTheme: _lightTextTheme, 82 | ), 83 | colorScheme: ColorScheme.light( 84 | primary: _lightPrimaryColor, 85 | primaryVariant: _lightPrimaryVariantColor, 86 | secondary: _lightSecondaryColor, 87 | onPrimary: _lightOnPrimaryColor, 88 | ), 89 | snackBarTheme: 90 | SnackBarThemeData(backgroundColor: _lightSnackBarBackgroundErrorColor), 91 | iconTheme: IconThemeData( 92 | color: _lightIconColor, 93 | ), 94 | popupMenuTheme: PopupMenuThemeData(color: _lightAppBarColor), 95 | textTheme: _lightTextTheme, 96 | buttonTheme: ButtonThemeData( 97 | buttonColor: _lightButtonPrimaryColor, 98 | textTheme: ButtonTextTheme.primary), 99 | unselectedWidgetColor: _lightPrimaryColor, 100 | inputDecorationTheme: InputDecorationTheme( 101 | fillColor: _lightPrimaryColor, 102 | labelStyle: TextStyle( 103 | color: _lightPrimaryColor, 104 | )), 105 | ); 106 | 107 | //the dark theme 108 | static final ThemeData darkTheme = ThemeData( 109 | fontFamily: AppFontFamily.productSans, 110 | scaffoldBackgroundColor: _darkPrimaryVariantColor, 111 | floatingActionButtonTheme: FloatingActionButtonThemeData( 112 | backgroundColor: _darkButtonPrimaryColor, 113 | ), 114 | appBarTheme: AppBarTheme( 115 | color: _darkAppBarColor, 116 | iconTheme: IconThemeData(color: _darkOnPrimaryColor), 117 | textTheme: _darkTextTheme, 118 | ), 119 | colorScheme: ColorScheme.light( 120 | primary: _darkPrimaryColor, 121 | primaryVariant: _darkPrimaryVariantColor, 122 | secondary: _darkSecondaryColor, 123 | onPrimary: _darkOnPrimaryColor, 124 | ), 125 | snackBarTheme: 126 | SnackBarThemeData(backgroundColor: _darkSnackBarBackgroundErrorColor), 127 | iconTheme: IconThemeData( 128 | color: _darkIconColor, 129 | ), 130 | popupMenuTheme: PopupMenuThemeData(color: _darkAppBarColor), 131 | textTheme: _darkTextTheme, 132 | buttonTheme: ButtonThemeData( 133 | buttonColor: _darkButtonPrimaryColor, 134 | textTheme: ButtonTextTheme.primary), 135 | unselectedWidgetColor: _darkPrimaryColor, 136 | inputDecorationTheme: InputDecorationTheme( 137 | fillColor: _darkPrimaryColor, 138 | labelStyle: TextStyle( 139 | color: _darkPrimaryColor, 140 | )), 141 | ); 142 | } 143 | -------------------------------------------------------------------------------- /lib/flavor.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Available commands: 3 | 4 | flutter run --flavor dev -t lib/main.dart 5 | flutter run --flavor prod -t lib/main_prod.dart 6 | */ 7 | 8 | enum Flavor {dev, prod} -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:noteapp/flavor.dart'; 4 | import 'package:noteapp/my_app.dart'; 5 | import 'package:noteapp/providers/auth_provider.dart'; 6 | import 'package:noteapp/providers/language_provider.dart'; 7 | import 'package:noteapp/providers/theme_provider.dart'; 8 | import 'package:noteapp/services/firestore_database.dart'; 9 | import 'package:provider/provider.dart'; 10 | 11 | void main() { 12 | WidgetsFlutterBinding.ensureInitialized(); 13 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) 14 | .then((_) async { 15 | runApp( 16 | /* 17 | * MultiProvider for top services that do not depends on any runtime values 18 | * such as user uid/email. 19 | */ 20 | MultiProvider( 21 | providers: [ 22 | Provider.value(value: Flavor.dev), 23 | ChangeNotifierProvider( 24 | create: (context) => ThemeProvider(), 25 | ), 26 | ChangeNotifierProvider( 27 | create: (context) => AuthProvider(), 28 | ), 29 | ChangeNotifierProvider( 30 | create: (context) => LanguageProvider(), 31 | ), 32 | ], 33 | child: MyApp( 34 | databaseBuilder: (_, uid) => FirestoreDatabase(uid: uid), 35 | key: Key('MyApp'), 36 | ), 37 | ), 38 | ); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /lib/main_prod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:noteapp/flavor.dart'; 4 | import 'package:noteapp/my_app.dart'; 5 | import 'package:noteapp/providers/auth_provider.dart'; 6 | import 'package:noteapp/providers/language_provider.dart'; 7 | import 'package:noteapp/providers/theme_provider.dart'; 8 | import 'package:noteapp/services/firestore_database.dart'; 9 | import 'package:provider/provider.dart'; 10 | 11 | void main() { 12 | WidgetsFlutterBinding.ensureInitialized(); 13 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) 14 | .then((_) async { 15 | runApp( 16 | /* 17 | * MultiProvider for top services that do not depends on any runtime values 18 | * such as user uid/email. 19 | */ 20 | MultiProvider( 21 | providers: [ 22 | Provider.value(value: Flavor.prod), 23 | ChangeNotifierProvider( 24 | create: (context) => ThemeProvider(), 25 | ), 26 | ChangeNotifierProvider( 27 | create: (context) => AuthProvider(), 28 | ), 29 | ChangeNotifierProvider( 30 | create: (context) => LanguageProvider(), 31 | ), 32 | ], 33 | child: MyApp( 34 | databaseBuilder: (_, uid) => FirestoreDatabase(uid: uid), 35 | key: Key('SimpleFinance'), 36 | ), 37 | ), 38 | ); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /lib/models/todo_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | class TodoModel { 4 | final String id; 5 | final String task; 6 | final String extraNote; 7 | final bool complete; 8 | 9 | TodoModel( 10 | {required this.id, 11 | required this.task, 12 | required this.extraNote, 13 | required this.complete}); 14 | 15 | factory TodoModel.fromMap(Map data, String documentId) { 16 | String task = data['task']; 17 | String extraNote = data['extraNote']; 18 | bool complete = data['complete']; 19 | 20 | return TodoModel( 21 | id: documentId, task: task, extraNote: extraNote, complete: complete); 22 | } 23 | 24 | Map toMap() { 25 | return { 26 | 'task': task, 27 | 'extraNote': extraNote, 28 | 'complete': complete, 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/models/user_model.dart: -------------------------------------------------------------------------------- 1 | class UserModel { 2 | String uid; 3 | String? email; 4 | String? displayName; 5 | String? phoneNumber; 6 | String? photoUrl; 7 | 8 | UserModel( 9 | {required this.uid, 10 | this.email, 11 | this.displayName, 12 | this.phoneNumber, 13 | this.photoUrl}); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lib/my_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/auth_widget_builder.dart'; 4 | import 'package:noteapp/constants/app_themes.dart'; 5 | import 'package:noteapp/flavor.dart'; 6 | import 'package:noteapp/models/user_model.dart'; 7 | import 'package:noteapp/providers/auth_provider.dart'; 8 | import 'package:noteapp/providers/language_provider.dart'; 9 | import 'package:noteapp/providers/theme_provider.dart'; 10 | import 'package:noteapp/routes.dart'; 11 | import 'package:noteapp/services/firestore_database.dart'; 12 | import 'package:noteapp/ui/auth/sign_in_screen.dart'; 13 | import 'package:noteapp/ui/home/home.dart'; 14 | import 'package:provider/provider.dart'; 15 | import 'package:flutter_localizations/flutter_localizations.dart'; 16 | 17 | class MyApp extends StatelessWidget { 18 | const MyApp({required Key key, required this.databaseBuilder}) 19 | : super(key: key); 20 | 21 | // Expose builders for 3rd party services at the root of the widget tree 22 | // This is useful when mocking services while testing 23 | final FirestoreDatabase Function(BuildContext context, String uid) 24 | databaseBuilder; 25 | 26 | // This widget is the root of your application. 27 | @override 28 | Widget build(BuildContext context) { 29 | return Consumer( 30 | builder: (_, themeProviderRef, __) { 31 | //{context, data, child} 32 | return Consumer( 33 | builder: (_, languageProviderRef, __) { 34 | return AuthWidgetBuilder( 35 | databaseBuilder: databaseBuilder, 36 | builder: (BuildContext context, 37 | AsyncSnapshot userSnapshot) { 38 | return MaterialApp( 39 | debugShowCheckedModeBanner: false, 40 | locale: languageProviderRef.appLocale, 41 | //List of all supported locales 42 | supportedLocales: [ 43 | Locale('en', 'US'), 44 | Locale('zh', 'CN'), 45 | ], 46 | //These delegates make sure that the localization data for the proper language is loaded 47 | localizationsDelegates: [ 48 | //A class which loads the translations from JSON files 49 | AppLocalizations.delegate, 50 | //Built-in localization of basic text for Material widgets (means those default Material widget such as alert dialog icon text) 51 | GlobalMaterialLocalizations.delegate, 52 | //Built-in localization for text direction LTR/RTL 53 | GlobalWidgetsLocalizations.delegate, 54 | ], 55 | //return a locale which will be used by the app 56 | localeResolutionCallback: (locale, supportedLocales) { 57 | //check if the current device locale is supported or not 58 | for (var supportedLocale in supportedLocales) { 59 | if (supportedLocale.languageCode == 60 | locale?.languageCode || 61 | supportedLocale.countryCode == locale?.countryCode) { 62 | return supportedLocale; 63 | } 64 | } 65 | //if the locale from the mobile device is not supported yet, 66 | //user the first one from the list (in our case, that will be English) 67 | return supportedLocales.first; 68 | }, 69 | title: Provider.of(context).toString(), 70 | routes: Routes.routes, 71 | theme: AppThemes.lightTheme, 72 | darkTheme: AppThemes.darkTheme, 73 | themeMode: themeProviderRef.isDarkModeOn 74 | ? ThemeMode.dark 75 | : ThemeMode.light, 76 | home: Consumer( 77 | builder: (_, authProviderRef, __) { 78 | if (userSnapshot.connectionState == 79 | ConnectionState.active) { 80 | return userSnapshot.hasData 81 | ? HomeScreen() 82 | : SignInScreen(); 83 | } 84 | 85 | return Material( 86 | child: CircularProgressIndicator(), 87 | ); 88 | }, 89 | ), 90 | ); 91 | }, 92 | key: Key('AuthWidget'), 93 | ); 94 | }, 95 | ); 96 | }, 97 | ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/providers/auth_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:noteapp/models/user_model.dart'; 4 | 5 | enum Status { 6 | Uninitialized, 7 | Authenticated, 8 | Authenticating, 9 | Unauthenticated, 10 | Registering 11 | } 12 | /* 13 | The UI will depends on the Status to decide which screen/action to be done. 14 | 15 | - Uninitialized - Checking user is logged or not, the Splash Screen will be shown 16 | - Authenticated - User is authenticated successfully, Home Page will be shown 17 | - Authenticating - Sign In button just been pressed, progress bar will be shown 18 | - Unauthenticated - User is not authenticated, login page will be shown 19 | - Registering - User just pressed registering, progress bar will be shown 20 | 21 | Take note, this is just an idea. You can remove or further add more different 22 | status for your UI or widgets to listen. 23 | */ 24 | 25 | class AuthProvider extends ChangeNotifier { 26 | //Firebase Auth object 27 | late FirebaseAuth _auth; 28 | 29 | //Default status 30 | Status _status = Status.Uninitialized; 31 | 32 | Status get status => _status; 33 | 34 | Stream get user => _auth.authStateChanges().map(_userFromFirebase); 35 | 36 | AuthProvider() { 37 | //initialise object 38 | _auth = FirebaseAuth.instance; 39 | 40 | //listener for authentication changes such as user sign in and sign out 41 | _auth.authStateChanges().listen(onAuthStateChanged); 42 | } 43 | 44 | //Create user object based on the given User 45 | UserModel _userFromFirebase(User? user) { 46 | if (user == null) { 47 | return UserModel(displayName: 'Null', uid: 'null'); 48 | } 49 | 50 | return UserModel( 51 | uid: user.uid, 52 | email: user.email, 53 | displayName: user.displayName, 54 | phoneNumber: user.phoneNumber, 55 | photoUrl: user.photoURL); 56 | } 57 | 58 | //Method to detect live auth changes such as user sign in and sign out 59 | Future onAuthStateChanged(User? firebaseUser) async { 60 | if (firebaseUser == null) { 61 | _status = Status.Unauthenticated; 62 | } else { 63 | _userFromFirebase(firebaseUser); 64 | _status = Status.Authenticated; 65 | } 66 | notifyListeners(); 67 | } 68 | 69 | //Method for new user registration using email and password 70 | Future registerWithEmailAndPassword( 71 | String email, String password) async { 72 | try { 73 | _status = Status.Registering; 74 | notifyListeners(); 75 | final UserCredential result = await _auth.createUserWithEmailAndPassword( 76 | email: email, password: password); 77 | 78 | return _userFromFirebase(result.user); 79 | } catch (e) { 80 | print("Error on the new user registration = " + e.toString()); 81 | _status = Status.Unauthenticated; 82 | notifyListeners(); 83 | return UserModel(displayName: 'Null', uid: 'null'); 84 | } 85 | } 86 | 87 | //Method to handle user sign in using email and password 88 | Future signInWithEmailAndPassword(String email, String password) async { 89 | try { 90 | _status = Status.Authenticating; 91 | notifyListeners(); 92 | await _auth.signInWithEmailAndPassword(email: email, password: password); 93 | return true; 94 | } catch (e) { 95 | print("Error on the sign in = " + e.toString()); 96 | _status = Status.Unauthenticated; 97 | notifyListeners(); 98 | return false; 99 | } 100 | } 101 | 102 | //Method to handle password reset email 103 | Future sendPasswordResetEmail(String email) async { 104 | await _auth.sendPasswordResetEmail(email: email); 105 | } 106 | 107 | //Method to handle user signing out 108 | Future signOut() async { 109 | _auth.signOut(); 110 | _status = Status.Unauthenticated; 111 | notifyListeners(); 112 | return Future.delayed(Duration.zero); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/providers/language_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/caches/sharedpref/shared_preference_helper.dart'; 3 | 4 | class LanguageProvider extends ChangeNotifier { 5 | // shared pref object 6 | late SharedPreferenceHelper _sharedPrefsHelper; 7 | 8 | Locale _appLocale = Locale('en'); 9 | 10 | LanguageProvider() { 11 | _sharedPrefsHelper = SharedPreferenceHelper(); 12 | } 13 | 14 | Locale get appLocale { 15 | _sharedPrefsHelper.appLocale?.then((localeValue) { 16 | _appLocale = Locale(localeValue); 17 | }); 18 | 19 | return _appLocale; 20 | } 21 | 22 | void updateLanguage(String languageCode) { 23 | if (languageCode == "zh") { 24 | _appLocale = Locale("zh"); 25 | } else { 26 | _appLocale = Locale("en"); 27 | } 28 | 29 | _sharedPrefsHelper.changeLanguage(languageCode); 30 | notifyListeners(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/providers/theme_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/caches/sharedpref/shared_preference_helper.dart'; 3 | 4 | class ThemeProvider extends ChangeNotifier { 5 | // shared pref object 6 | late SharedPreferenceHelper _sharedPrefsHelper; 7 | 8 | bool _isDarkModeOn = false; 9 | 10 | ThemeProvider() { 11 | _sharedPrefsHelper = SharedPreferenceHelper(); 12 | } 13 | 14 | bool get isDarkModeOn { 15 | _sharedPrefsHelper.isDarkMode.then((statusValue) { 16 | _isDarkModeOn = statusValue; 17 | }); 18 | 19 | return _isDarkModeOn; 20 | } 21 | 22 | void updateTheme(bool isDarkModeOn) { 23 | _sharedPrefsHelper.changeTheme(isDarkModeOn); 24 | _sharedPrefsHelper.isDarkMode.then((darkModeStatus) { 25 | _isDarkModeOn = darkModeStatus; 26 | }); 27 | 28 | notifyListeners(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/routes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/ui/auth/register_screen.dart'; 3 | import 'package:noteapp/ui/auth/sign_in_screen.dart'; 4 | import 'package:noteapp/ui/setting/setting_screen.dart'; 5 | import 'package:noteapp/ui/splash/splash_screen.dart'; 6 | import 'package:noteapp/ui/todo/create_edit_todo_screen.dart'; 7 | import 'package:noteapp/ui/todo/todos_screen.dart'; 8 | 9 | class Routes { 10 | Routes._(); //this is to prevent anyone from instantiate this object 11 | 12 | static const String splash = '/splash'; 13 | static const String login = '/login'; 14 | static const String register = '/register'; 15 | static const String home = '/home'; 16 | static const String setting = '/setting'; 17 | static const String create_edit_todo = '/create_edit_todo'; 18 | 19 | static final routes = { 20 | splash: (BuildContext context) => SplashScreen(), 21 | login: (BuildContext context) => SignInScreen(), 22 | register: (BuildContext context) => RegisterScreen(), 23 | home: (BuildContext context) => TodosScreen(), 24 | setting: (BuildContext context) => SettingScreen(), 25 | create_edit_todo: (BuildContext context) => CreateEditTodoScreen(), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /lib/services/firestore_database.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:noteapp/models/todo_model.dart'; 4 | import 'package:noteapp/services/firestore_path.dart'; 5 | import 'package:cloud_firestore/cloud_firestore.dart'; 6 | 7 | import 'package:noteapp/services/firestore_service.dart'; 8 | 9 | String documentIdFromCurrentDate() => DateTime.now().toIso8601String(); 10 | 11 | /* 12 | This is the main class access/call for any UI widgets that require to perform 13 | any CRUD activities operation in FirebaseFirestore database. 14 | This class work hand-in-hand with FirestoreService and FirestorePath. 15 | 16 | Notes: 17 | For cases where you need to have a special method such as bulk update specifically 18 | on a field, then is ok to use custom code and write it here. For example, 19 | setAllTodoComplete is require to change all todos item to have the complete status 20 | changed to true. 21 | 22 | */ 23 | class FirestoreDatabase { 24 | FirestoreDatabase({required this.uid}) : assert(uid != null); 25 | final String uid; 26 | 27 | final _firestoreService = FirestoreService.instance; 28 | 29 | //Method to create/update todoModel 30 | Future setTodo(TodoModel todo) async => await _firestoreService.set( 31 | path: FirestorePath.todo(uid, todo.id), 32 | data: todo.toMap(), 33 | ); 34 | 35 | //Method to delete todoModel entry 36 | Future deleteTodo(TodoModel todo) async { 37 | await _firestoreService.deleteData(path: FirestorePath.todo(uid, todo.id)); 38 | } 39 | 40 | //Method to retrieve todoModel object based on the given todoId 41 | Stream todoStream({required String todoId}) => 42 | _firestoreService.documentStream( 43 | path: FirestorePath.todo(uid, todoId), 44 | builder: (data, documentId) => TodoModel.fromMap(data, documentId), 45 | ); 46 | 47 | //Method to retrieve all todos item from the same user based on uid 48 | Stream> todosStream() => _firestoreService.collectionStream( 49 | path: FirestorePath.todos(uid), 50 | builder: (data, documentId) => TodoModel.fromMap(data, documentId), 51 | ); 52 | 53 | //Method to mark all todoModel to be complete 54 | Future setAllTodoComplete() async { 55 | final batchUpdate = FirebaseFirestore.instance.batch(); 56 | 57 | final querySnapshot = await FirebaseFirestore.instance 58 | .collection(FirestorePath.todos(uid)) 59 | .get(); 60 | 61 | for (DocumentSnapshot ds in querySnapshot.docs) { 62 | batchUpdate.update(ds.reference, {'complete': true}); 63 | } 64 | await batchUpdate.commit(); 65 | } 66 | 67 | Future deleteAllTodoWithComplete() async { 68 | final batchDelete = FirebaseFirestore.instance.batch(); 69 | 70 | final querySnapshot = await FirebaseFirestore.instance 71 | .collection(FirestorePath.todos(uid)) 72 | .where('complete', isEqualTo: true) 73 | .get(); 74 | 75 | for (DocumentSnapshot ds in querySnapshot.docs) { 76 | batchDelete.delete(ds.reference); 77 | } 78 | await batchDelete.commit(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/services/firestore_path.dart: -------------------------------------------------------------------------------- 1 | /* 2 | This class defines all the possible read/write locations from the FirebaseFirestore database. 3 | In future, any new path can be added here. 4 | This class work together with FirestoreService and FirestoreDatabase. 5 | */ 6 | 7 | class FirestorePath { 8 | static String todo(String uid, String todoId) => 'users/$uid/todos/$todoId'; 9 | static String todos(String uid) => 'users/$uid/todos'; 10 | } 11 | -------------------------------------------------------------------------------- /lib/services/firestore_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | /* 4 | This class represent all possible CRUD operation for FirebaseFirestore. 5 | It contains all generic implementation needed based on the provided document 6 | path and documentID,since most of the time in FirebaseFirestore design, we will have 7 | documentID and path for any document and collections. 8 | */ 9 | class FirestoreService { 10 | FirestoreService._(); 11 | static final instance = FirestoreService._(); 12 | 13 | Future set({ 14 | required String path, 15 | required Map data, 16 | bool merge = false, 17 | }) async { 18 | final reference = FirebaseFirestore.instance.doc(path); 19 | print('$path: $data'); 20 | await reference.set(data); 21 | } 22 | 23 | Future bulkSet({ 24 | required String path, 25 | required List> datas, 26 | bool merge = false, 27 | }) async { 28 | final reference = FirebaseFirestore.instance.doc(path); 29 | final batchSet = FirebaseFirestore.instance.batch(); 30 | 31 | // for() 32 | // batchSet. 33 | 34 | print('$path: $datas'); 35 | } 36 | 37 | Future deleteData({required String path}) async { 38 | final reference = FirebaseFirestore.instance.doc(path); 39 | print('delete: $path'); 40 | await reference.delete(); 41 | } 42 | 43 | Stream> collectionStream({ 44 | required String path, 45 | required T builder(Map data, String documentID), 46 | Query queryBuilder(Query query)?, 47 | int sort(T lhs, T rhs)?, 48 | }) { 49 | Query query = FirebaseFirestore.instance.collection(path); 50 | if (queryBuilder != null) { 51 | query = queryBuilder(query); 52 | } 53 | final Stream snapshots = query.snapshots(); 54 | return snapshots.map((snapshot) { 55 | final result = snapshot.docs 56 | .map((snapshot) => 57 | builder(snapshot.data() as Map, snapshot.id)) 58 | .where((value) => value != null) 59 | .toList(); 60 | if (sort != null) { 61 | result.sort(sort); 62 | } 63 | return result; 64 | }); 65 | } 66 | 67 | Stream documentStream({ 68 | required String path, 69 | required T builder(Map data, String documentID), 70 | }) { 71 | final DocumentReference reference = FirebaseFirestore.instance.doc(path); 72 | final Stream snapshots = reference.snapshots(); 73 | return snapshots.map((snapshot) => 74 | builder(snapshot.data() as Map, snapshot.id)); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/ui/auth/register_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/models/user_model.dart'; 4 | import 'package:noteapp/providers/auth_provider.dart'; 5 | import 'package:noteapp/routes.dart'; 6 | import 'package:provider/provider.dart'; 7 | 8 | class RegisterScreen extends StatefulWidget { 9 | @override 10 | _RegisterScreenState createState() => _RegisterScreenState(); 11 | } 12 | 13 | class _RegisterScreenState extends State { 14 | late TextEditingController _emailController; 15 | late TextEditingController _passwordController; 16 | final _formKey = GlobalKey(); 17 | final _scaffoldKey = GlobalKey(); 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | _emailController = TextEditingController(text: ""); 23 | _passwordController = TextEditingController(text: ""); 24 | } 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | key: _scaffoldKey, 30 | body: Stack( 31 | children: [ 32 | _buildBackground(), 33 | Align( 34 | alignment: Alignment.center, 35 | child: _buildForm(context), 36 | ), 37 | ], 38 | ), 39 | ); 40 | } 41 | 42 | @override 43 | void dispose() { 44 | _emailController.dispose(); 45 | _passwordController.dispose(); 46 | super.dispose(); 47 | } 48 | 49 | Widget _buildForm(BuildContext context) { 50 | final authProvider = Provider.of(context); 51 | 52 | return Form( 53 | key: _formKey, 54 | child: SingleChildScrollView( 55 | child: Padding( 56 | padding: const EdgeInsets.symmetric(horizontal: 24), 57 | child: Column( 58 | mainAxisSize: MainAxisSize.max, 59 | crossAxisAlignment: CrossAxisAlignment.stretch, 60 | mainAxisAlignment: MainAxisAlignment.center, 61 | children: [ 62 | Padding( 63 | padding: const EdgeInsets.all(8.0), 64 | child: FlutterLogo( 65 | size: 128, 66 | ), 67 | ), 68 | TextFormField( 69 | controller: _emailController, 70 | style: Theme.of(context).textTheme.body1, 71 | validator: (value) => value!.isEmpty 72 | ? AppLocalizations.of(context) 73 | .translate("loginTxtErrorEmail") 74 | : null, 75 | decoration: InputDecoration( 76 | prefixIcon: Icon( 77 | Icons.email, 78 | color: Theme.of(context).iconTheme.color, 79 | ), 80 | labelText: AppLocalizations.of(context) 81 | .translate("loginTxtEmail"), 82 | border: OutlineInputBorder()), 83 | ), 84 | Padding( 85 | padding: const EdgeInsets.symmetric(vertical: 16), 86 | child: TextFormField( 87 | obscureText: true, 88 | maxLength: 12, 89 | controller: _passwordController, 90 | style: Theme.of(context).textTheme.body1, 91 | validator: (value) => value!.length < 6 92 | ? AppLocalizations.of(context) 93 | .translate("loginTxtErrorPassword") 94 | : null, 95 | decoration: InputDecoration( 96 | prefixIcon: Icon( 97 | Icons.lock, 98 | color: Theme.of(context).iconTheme.color, 99 | ), 100 | labelText: AppLocalizations.of(context) 101 | .translate("loginTxtPassword"), 102 | border: OutlineInputBorder()), 103 | ), 104 | ), 105 | authProvider.status == Status.Registering 106 | ? Center( 107 | child: CircularProgressIndicator(), 108 | ) 109 | : RaisedButton( 110 | child: Text( 111 | AppLocalizations.of(context) 112 | .translate("loginBtnSignUp"), 113 | style: Theme.of(context).textTheme.button, 114 | ), 115 | onPressed: () async { 116 | if (_formKey.currentState!.validate()) { 117 | FocusScope.of(context) 118 | .unfocus(); //to hide the keyboard - if any 119 | 120 | UserModel userModel = 121 | await authProvider.registerWithEmailAndPassword( 122 | _emailController.text, 123 | _passwordController.text); 124 | 125 | if (userModel == null) { 126 | _scaffoldKey.currentState!.showSnackBar(SnackBar( 127 | content: Text(AppLocalizations.of(context) 128 | .translate("loginTxtErrorSignIn")), 129 | )); 130 | } 131 | } 132 | }), 133 | authProvider.status == Status.Registering 134 | ? Center( 135 | child: null, 136 | ) 137 | : Padding( 138 | padding: const EdgeInsets.only(top: 48), 139 | child: Center( 140 | child: Text( 141 | AppLocalizations.of(context) 142 | .translate("loginTxtHaveAccount"), 143 | style: Theme.of(context).textTheme.button, 144 | )), 145 | ), 146 | authProvider.status == Status.Registering 147 | ? Center( 148 | child: null, 149 | ) 150 | : FlatButton( 151 | child: Text(AppLocalizations.of(context) 152 | .translate("loginBtnLinkSignIn")), 153 | textColor: Theme.of(context).iconTheme.color, 154 | onPressed: () { 155 | Navigator.of(context) 156 | .pushReplacementNamed(Routes.login); 157 | }, 158 | ), 159 | ], 160 | ), 161 | ), 162 | )); 163 | } 164 | 165 | Widget _buildBackground() { 166 | return ClipPath( 167 | clipper: SignInCustomClipper(), 168 | child: Container( 169 | width: MediaQuery.of(context).size.width, 170 | height: MediaQuery.of(context).size.height * 0.5, 171 | color: Theme.of(context).iconTheme.color, 172 | ), 173 | ); 174 | } 175 | } 176 | 177 | class SignInCustomClipper extends CustomClipper { 178 | @override 179 | Path getClip(Size size) { 180 | Path path = Path(); 181 | path.lineTo(0, size.height); 182 | 183 | var firstEndPoint = Offset(size.width / 2, size.height - 95); 184 | var firstControlPoint = Offset(size.width / 6, size.height * 0.45); 185 | 186 | path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy, 187 | firstEndPoint.dx, firstEndPoint.dy); 188 | 189 | var secondEndPoint = Offset(size.width, size.height / 2 - 50); 190 | var secondControlPoint = Offset(size.width, size.height + 15); 191 | 192 | path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy, 193 | secondEndPoint.dx, secondEndPoint.dy); 194 | 195 | path.lineTo(size.width, size.height / 2); 196 | path.lineTo(size.width, 0); 197 | path.close(); 198 | return path; 199 | } 200 | 201 | @override 202 | bool shouldReclip(CustomClipper oldClipper) { 203 | return true; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /lib/ui/auth/sign_in_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/flavor.dart'; 4 | import 'package:noteapp/providers/auth_provider.dart'; 5 | import 'package:noteapp/routes.dart'; 6 | import 'package:provider/provider.dart'; 7 | 8 | class SignInScreen extends StatefulWidget { 9 | @override 10 | _SignInScreenState createState() => _SignInScreenState(); 11 | } 12 | 13 | class _SignInScreenState extends State { 14 | late TextEditingController _emailController; 15 | late TextEditingController _passwordController; 16 | final _formKey = GlobalKey(); 17 | final _scaffoldKey = GlobalKey(); 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | _emailController = TextEditingController(text: ""); 23 | _passwordController = TextEditingController(text: ""); 24 | } 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | key: _scaffoldKey, 30 | body: Stack( 31 | children: [ 32 | _buildBackground(), 33 | Align( 34 | alignment: Alignment.center, 35 | child: _buildForm(context), 36 | ), 37 | ], 38 | ), 39 | ); 40 | } 41 | 42 | @override 43 | void dispose() { 44 | _emailController.dispose(); 45 | _passwordController.dispose(); 46 | super.dispose(); 47 | } 48 | 49 | Widget _buildForm(BuildContext context) { 50 | final authProvider = Provider.of(context); 51 | 52 | return Form( 53 | key: _formKey, 54 | child: SingleChildScrollView( 55 | child: Padding( 56 | padding: const EdgeInsets.symmetric(horizontal: 24), 57 | child: Column( 58 | mainAxisSize: MainAxisSize.max, 59 | crossAxisAlignment: CrossAxisAlignment.stretch, 60 | mainAxisAlignment: MainAxisAlignment.center, 61 | children: [ 62 | Padding( 63 | padding: const EdgeInsets.all(8.0), 64 | child: FlutterLogo( 65 | size: 128, 66 | ), 67 | ), 68 | TextFormField( 69 | controller: _emailController, 70 | style: Theme.of(context).textTheme.body1, 71 | validator: (value) => value!.isEmpty 72 | ? AppLocalizations.of(context) 73 | .translate("loginTxtErrorEmail") 74 | : null, 75 | decoration: InputDecoration( 76 | prefixIcon: Icon( 77 | Icons.email, 78 | color: Theme.of(context).iconTheme.color, 79 | ), 80 | labelText: AppLocalizations.of(context) 81 | .translate("loginTxtEmail"), 82 | border: OutlineInputBorder()), 83 | ), 84 | Padding( 85 | padding: const EdgeInsets.symmetric(vertical: 16), 86 | child: TextFormField( 87 | obscureText: true, 88 | maxLength: 12, 89 | controller: _passwordController, 90 | style: Theme.of(context).textTheme.body1, 91 | validator: (value) => value!.length < 6 92 | ? AppLocalizations.of(context) 93 | .translate("loginTxtErrorPassword") 94 | : null, 95 | decoration: InputDecoration( 96 | prefixIcon: Icon( 97 | Icons.lock, 98 | color: Theme.of(context).iconTheme.color, 99 | ), 100 | labelText: AppLocalizations.of(context) 101 | .translate("loginTxtPassword"), 102 | border: OutlineInputBorder()), 103 | ), 104 | ), 105 | authProvider.status == Status.Authenticating 106 | ? Center( 107 | child: CircularProgressIndicator(), 108 | ) 109 | : RaisedButton( 110 | child: Text( 111 | AppLocalizations.of(context) 112 | .translate("loginBtnSignIn"), 113 | style: Theme.of(context).textTheme.button, 114 | ), 115 | onPressed: () async { 116 | if (_formKey.currentState!.validate()) { 117 | FocusScope.of(context) 118 | .unfocus(); //to hide the keyboard - if any 119 | 120 | bool status = 121 | await authProvider.signInWithEmailAndPassword( 122 | _emailController.text, 123 | _passwordController.text); 124 | 125 | if (!status) { 126 | _scaffoldKey.currentState!.showSnackBar(SnackBar( 127 | content: Text(AppLocalizations.of(context) 128 | .translate("loginTxtErrorSignIn")), 129 | )); 130 | } else { 131 | Navigator.of(context) 132 | .pushReplacementNamed(Routes.home); 133 | } 134 | } 135 | }), 136 | authProvider.status == Status.Authenticating 137 | ? Center( 138 | child: null, 139 | ) 140 | : Padding( 141 | padding: const EdgeInsets.only(top: 48), 142 | child: Center( 143 | child: Text( 144 | AppLocalizations.of(context) 145 | .translate("loginTxtDontHaveAccount"), 146 | style: Theme.of(context).textTheme.button, 147 | )), 148 | ), 149 | authProvider.status == Status.Authenticating 150 | ? Center( 151 | child: null, 152 | ) 153 | : FlatButton( 154 | child: Text(AppLocalizations.of(context) 155 | .translate("loginBtnLinkCreateAccount")), 156 | textColor: Theme.of(context).iconTheme.color, 157 | onPressed: () { 158 | Navigator.of(context) 159 | .pushReplacementNamed(Routes.register); 160 | }, 161 | ), 162 | Center( 163 | child: Column( 164 | mainAxisAlignment: MainAxisAlignment.end, 165 | children: [ 166 | SizedBox( 167 | height: 70, 168 | ), 169 | Text( 170 | Provider.of(context).toString(), 171 | style: Theme.of(context).textTheme.body2, 172 | ), 173 | ], 174 | )), 175 | ], 176 | ), 177 | ), 178 | )); 179 | } 180 | 181 | Widget _buildBackground() { 182 | return ClipPath( 183 | clipper: SignInCustomClipper(), 184 | child: Container( 185 | width: MediaQuery.of(context).size.width, 186 | height: MediaQuery.of(context).size.height * 0.5, 187 | color: Theme.of(context).iconTheme.color, 188 | ), 189 | ); 190 | } 191 | } 192 | 193 | class SignInCustomClipper extends CustomClipper { 194 | @override 195 | Path getClip(Size size) { 196 | Path path = Path(); 197 | path.lineTo(0, size.height); 198 | 199 | var firstEndPoint = Offset(size.width / 2, size.height - 95); 200 | var firstControlPoint = Offset(size.width / 6, size.height * 0.45); 201 | 202 | path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy, 203 | firstEndPoint.dx, firstEndPoint.dy); 204 | 205 | var secondEndPoint = Offset(size.width, size.height / 2 - 50); 206 | var secondControlPoint = Offset(size.width, size.height + 15); 207 | 208 | path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy, 209 | secondEndPoint.dx, secondEndPoint.dy); 210 | 211 | path.lineTo(size.width, size.height / 2); 212 | path.lineTo(size.width, 0); 213 | path.close(); 214 | return path; 215 | } 216 | 217 | @override 218 | bool shouldReclip(CustomClipper oldClipper) { 219 | return true; 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /lib/ui/home/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/ui/splash/splash_screen.dart'; 3 | 4 | class HomeScreen extends StatefulWidget { 5 | @override 6 | _HomeScreenState createState() => _HomeScreenState(); 7 | } 8 | 9 | class _HomeScreenState extends State { 10 | @override 11 | Widget build(BuildContext context) { 12 | return SplashScreen(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/ui/setting/setting_language_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/providers/language_provider.dart'; 4 | import 'package:provider/provider.dart'; 5 | 6 | enum LanguagesActions { english, chinese } 7 | 8 | class SettingLanguageActions extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | LanguageProvider languageProvider = Provider.of(context); 12 | Locale _appCurrentLocale = languageProvider.appLocale; 13 | 14 | return PopupMenuButton( 15 | icon: Icon(Icons.language), 16 | onSelected: (LanguagesActions result) { 17 | switch (result) { 18 | case LanguagesActions.english: 19 | languageProvider.updateLanguage("en"); 20 | break; 21 | case LanguagesActions.chinese: 22 | languageProvider.updateLanguage("zh"); 23 | } 24 | }, 25 | itemBuilder: (BuildContext context) => >[ 26 | PopupMenuItem( 27 | value: LanguagesActions.english, 28 | enabled: _appCurrentLocale == Locale("en") ? false : true, 29 | child: Text(AppLocalizations.of(context) 30 | .translate("settingPopUpToggleEnglish")), 31 | ), 32 | PopupMenuItem( 33 | value: LanguagesActions.chinese, 34 | enabled: _appCurrentLocale == Locale("zh") ? false : true, 35 | child: Text(AppLocalizations.of(context) 36 | .translate("settingPopUpToggleChinese")), 37 | ), 38 | ], 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/ui/setting/setting_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; 3 | import 'package:noteapp/app_localizations.dart'; 4 | import 'package:noteapp/providers/auth_provider.dart'; 5 | import 'package:noteapp/providers/theme_provider.dart'; 6 | import 'package:noteapp/routes.dart'; 7 | import 'package:noteapp/ui/setting/setting_language_actions.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class SettingScreen extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text(AppLocalizations.of(context).translate("settingAppTitle")), 16 | ), 17 | body: _buildLayoutSection(context), 18 | ); 19 | } 20 | 21 | Widget _buildLayoutSection(BuildContext context) { 22 | return ListView( 23 | children: [ 24 | ListTile( 25 | title: Text( 26 | AppLocalizations.of(context).translate("settingThemeListTitle")), 27 | subtitle: Text(AppLocalizations.of(context) 28 | .translate("settingThemeListSubTitle")), 29 | trailing: Switch( 30 | activeColor: Theme.of(context).appBarTheme.color, 31 | activeTrackColor: Theme.of(context).textTheme.title!.color, 32 | value: Provider.of(context).isDarkModeOn, 33 | onChanged: (booleanValue) { 34 | Provider.of(context, listen: false) 35 | .updateTheme(booleanValue); 36 | }, 37 | ), 38 | ), 39 | ListTile( 40 | title: Text(AppLocalizations.of(context) 41 | .translate("settingLanguageListTitle")), 42 | subtitle: Text(AppLocalizations.of(context) 43 | .translate("settingLanguageListSubTitle")), 44 | trailing: SettingLanguageActions(), 45 | ), 46 | ListTile( 47 | title: Text( 48 | AppLocalizations.of(context).translate("settingLogoutListTitle")), 49 | subtitle: Text(AppLocalizations.of(context) 50 | .translate("settingLogoutListSubTitle")), 51 | trailing: RaisedButton( 52 | onPressed: () { 53 | _confirmSignOut(context); 54 | }, 55 | child: Text(AppLocalizations.of(context) 56 | .translate("settingLogoutButton"))), 57 | ) 58 | ], 59 | ); 60 | } 61 | 62 | _confirmSignOut(BuildContext context) { 63 | showPlatformDialog( 64 | context: context, 65 | builder: (_) => PlatformAlertDialog( 66 | material: (_, PlatformTarget target) => MaterialAlertDialogData( 67 | backgroundColor: Theme.of(context).appBarTheme.color), 68 | title: Text( 69 | AppLocalizations.of(context).translate("alertDialogTitle")), 70 | content: Text( 71 | AppLocalizations.of(context).translate("alertDialogMessage")), 72 | actions: [ 73 | PlatformDialogAction( 74 | child: PlatformText(AppLocalizations.of(context) 75 | .translate("alertDialogCancelBtn")), 76 | onPressed: () => Navigator.pop(context), 77 | ), 78 | PlatformDialogAction( 79 | child: PlatformText(AppLocalizations.of(context) 80 | .translate("alertDialogYesBtn")), 81 | onPressed: () { 82 | final authProvider = 83 | Provider.of(context, listen: false); 84 | 85 | authProvider.signOut(); 86 | 87 | Navigator.pop(context); 88 | Navigator.of(context).pushNamedAndRemoveUntil( 89 | Routes.login, ModalRoute.withName(Routes.login)); 90 | }, 91 | ) 92 | ], 93 | )); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/ui/splash/splash_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:noteapp/app_localizations.dart'; 4 | import 'package:noteapp/routes.dart'; 5 | 6 | class SplashScreen extends StatefulWidget { 7 | @override 8 | _SplashScreenState createState() => _SplashScreenState(); 9 | } 10 | 11 | class _SplashScreenState extends State { 12 | @override 13 | void initState() { 14 | super.initState(); 15 | startTimer(); 16 | } 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Scaffold( 21 | body: Center( 22 | child: Column( 23 | mainAxisAlignment: MainAxisAlignment.center, 24 | crossAxisAlignment: CrossAxisAlignment.stretch, 25 | children: [ 26 | Center( 27 | child: Text( 28 | AppLocalizations.of(context).translate("splashTitle"), 29 | style: TextStyle( 30 | fontSize: Theme.of(context).textTheme.headline!.fontSize, 31 | ), 32 | )), 33 | FlutterLogo( 34 | size: 128, 35 | ), 36 | ], 37 | ))); 38 | } 39 | 40 | startTimer() { 41 | var duration = Duration(milliseconds: 3000); 42 | return Timer(duration, redirect); 43 | } 44 | 45 | redirect() async { 46 | Navigator.of(context).pushReplacementNamed(Routes.home); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/ui/todo/create_edit_todo_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/models/todo_model.dart'; 4 | import 'package:noteapp/services/firestore_database.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | class CreateEditTodoScreen extends StatefulWidget { 8 | @override 9 | _CreateEditTodoScreenState createState() => _CreateEditTodoScreenState(); 10 | } 11 | 12 | class _CreateEditTodoScreenState extends State { 13 | late TextEditingController _taskController; 14 | late TextEditingController _extraNoteController; 15 | final _formKey = GlobalKey(); 16 | final _scaffoldKey = GlobalKey(); 17 | TodoModel? _todo; 18 | late bool _checkboxCompleted; 19 | 20 | @override 21 | void initState() { 22 | super.initState(); 23 | } 24 | 25 | @override 26 | void didChangeDependencies() { 27 | super.didChangeDependencies(); 28 | final TodoModel? _todoModel = ModalRoute.of(context)?.settings.arguments as TodoModel?; 29 | if (_todoModel != null) { 30 | _todo = _todoModel; 31 | } 32 | 33 | _taskController = 34 | TextEditingController(text: _todo?.task ?? ""); 35 | _extraNoteController = 36 | TextEditingController(text: _todo?.extraNote ?? ""); 37 | 38 | _checkboxCompleted = _todo?.complete ?? false; 39 | } 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return Scaffold( 44 | key: _scaffoldKey, 45 | appBar: AppBar( 46 | leading: IconButton( 47 | icon: Icon(Icons.cancel), 48 | onPressed: () { 49 | Navigator.of(context).pop(); 50 | }, 51 | ), 52 | title: Text(_todo != null 53 | ? AppLocalizations.of(context) 54 | .translate("todosCreateEditAppBarTitleEditTxt") 55 | : AppLocalizations.of(context) 56 | .translate("todosCreateEditAppBarTitleNewTxt")), 57 | actions: [ 58 | FlatButton( 59 | onPressed: () { 60 | if (_formKey.currentState!.validate()) { 61 | FocusScope.of(context).unfocus(); 62 | 63 | final firestoreDatabase = 64 | Provider.of(context, listen: false); 65 | 66 | firestoreDatabase.setTodo(TodoModel( 67 | id: _todo?.id ?? documentIdFromCurrentDate(), 68 | task: _taskController.text, 69 | extraNote: _extraNoteController.text.length > 0 70 | ? _extraNoteController.text 71 | : "", 72 | complete: _checkboxCompleted)); 73 | 74 | Navigator.of(context).pop(); 75 | } 76 | }, 77 | child: Text("Save")) 78 | ], 79 | ), 80 | body: Center( 81 | child: _buildForm(context), 82 | ), 83 | ); 84 | } 85 | 86 | @override 87 | void dispose() { 88 | _taskController.dispose(); 89 | _extraNoteController.dispose(); 90 | super.dispose(); 91 | } 92 | 93 | Widget _buildForm(BuildContext context) { 94 | return Form( 95 | key: _formKey, 96 | child: SingleChildScrollView( 97 | child: Padding( 98 | padding: const EdgeInsets.all(16), 99 | child: Column( 100 | mainAxisSize: MainAxisSize.max, 101 | crossAxisAlignment: CrossAxisAlignment.stretch, 102 | children: [ 103 | TextFormField( 104 | controller: _taskController, 105 | style: Theme.of(context).textTheme.body1, 106 | validator: (value) => value!.isEmpty 107 | ? AppLocalizations.of(context) 108 | .translate("todosCreateEditTaskNameValidatorMsg") 109 | : null, 110 | decoration: InputDecoration( 111 | enabledBorder: OutlineInputBorder( 112 | borderSide: BorderSide( 113 | color: Theme.of(context).iconTheme.color!, width: 2)), 114 | labelText: AppLocalizations.of(context) 115 | .translate("todosCreateEditTaskNameTxt"), 116 | ), 117 | ), 118 | Padding( 119 | padding: const EdgeInsets.symmetric(vertical: 16), 120 | child: TextFormField( 121 | controller: _extraNoteController, 122 | style: Theme.of(context).textTheme.body1, 123 | maxLines: 15, 124 | decoration: InputDecoration( 125 | enabledBorder: OutlineInputBorder( 126 | borderSide: BorderSide( 127 | color: Theme.of(context).iconTheme.color!, 128 | width: 2)), 129 | labelText: AppLocalizations.of(context) 130 | .translate("todosCreateEditNotesTxt"), 131 | alignLabelWithHint: true, 132 | contentPadding: new EdgeInsets.symmetric( 133 | vertical: 10.0, horizontal: 10.0), 134 | ), 135 | ), 136 | ), 137 | Padding( 138 | padding: const EdgeInsets.only(left: 8), 139 | child: Row( 140 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 141 | children: [ 142 | Text(AppLocalizations.of(context) 143 | .translate("todosCreateEditCompletedTxt")), 144 | Checkbox( 145 | value: _checkboxCompleted, 146 | onChanged: (value) { 147 | setState(() { 148 | _checkboxCompleted = value!; 149 | }); 150 | }) 151 | ], 152 | ), 153 | ) 154 | ], 155 | ), 156 | ), 157 | ), 158 | ); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /lib/ui/todo/empty_content.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class EmptyContentWidget extends StatelessWidget { 4 | final String title; 5 | final String message; 6 | 7 | EmptyContentWidget( 8 | {required Key key, 9 | required this.title, 10 | required this.message}) 11 | : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Center( 16 | child: Column( 17 | mainAxisAlignment: MainAxisAlignment.center, 18 | children: [ 19 | Text(title), 20 | Text(message), 21 | ], 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/ui/todo/todos_extra_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/services/firestore_database.dart'; 4 | import 'package:provider/provider.dart'; 5 | 6 | enum TodosActions { toggleAllComplete, clearCompleted } 7 | 8 | class TodosExtraActions extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | FirestoreDatabase firestoreDatabase = Provider.of(context); 12 | 13 | return PopupMenuButton( 14 | icon: Icon(Icons.more_horiz), 15 | onSelected: (TodosActions result) { 16 | switch (result) { 17 | case TodosActions.toggleAllComplete: 18 | firestoreDatabase.setAllTodoComplete(); 19 | break; 20 | case TodosActions.clearCompleted: 21 | firestoreDatabase.deleteAllTodoWithComplete(); 22 | } 23 | }, 24 | itemBuilder: (BuildContext context) => >[ 25 | PopupMenuItem( 26 | value: TodosActions.toggleAllComplete, 27 | child: Text(AppLocalizations.of(context) 28 | .translate("todosPopUpToggleAllComplete")), 29 | ), 30 | PopupMenuItem( 31 | value: TodosActions.clearCompleted, 32 | child: Text(AppLocalizations.of(context) 33 | .translate("todosPopUpToggleClearCompleted")), 34 | ), 35 | ], 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/ui/todo/todos_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:noteapp/app_localizations.dart'; 3 | import 'package:noteapp/models/todo_model.dart'; 4 | import 'package:noteapp/models/user_model.dart'; 5 | import 'package:noteapp/providers/auth_provider.dart'; 6 | import 'package:noteapp/routes.dart'; 7 | import 'package:noteapp/services/firestore_database.dart'; 8 | import 'package:noteapp/ui/todo/empty_content.dart'; 9 | import 'package:noteapp/ui/todo/todos_extra_actions.dart'; 10 | import 'package:provider/provider.dart'; 11 | 12 | class TodosScreen extends StatelessWidget { 13 | final _scaffoldKey = GlobalKey(); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final authProvider = Provider.of(context); 18 | final firestoreDatabase = 19 | Provider.of(context, listen: false); 20 | 21 | return Scaffold( 22 | key: _scaffoldKey, 23 | appBar: AppBar( 24 | title: StreamBuilder( 25 | stream: authProvider.user, 26 | builder: (context, snapshot) { 27 | final UserModel? user = snapshot.data as UserModel?; 28 | return Text(user != null 29 | ? user.email! + 30 | " - " + 31 | AppLocalizations.of(context).translate("homeAppBarTitle") 32 | : AppLocalizations.of(context).translate("homeAppBarTitle")); 33 | }), 34 | actions: [ 35 | StreamBuilder( 36 | stream: firestoreDatabase.todosStream(), 37 | builder: (context, snapshot) { 38 | if (snapshot.hasData) { 39 | List todos = snapshot.data as List; 40 | return Visibility( 41 | visible: todos.isNotEmpty ? true : false, 42 | child: TodosExtraActions()); 43 | } else { 44 | return Container( 45 | width: 0, 46 | height: 0, 47 | ); 48 | } 49 | }), 50 | IconButton( 51 | icon: Icon(Icons.settings), 52 | onPressed: () { 53 | Navigator.of(context).pushNamed(Routes.setting); 54 | }), 55 | ], 56 | ), 57 | floatingActionButton: FloatingActionButton( 58 | child: Icon(Icons.add), 59 | onPressed: () { 60 | Navigator.of(context).pushNamed( 61 | Routes.create_edit_todo, 62 | ); 63 | }, 64 | ), 65 | body: WillPopScope( 66 | onWillPop: () async => false, child: _buildBodySection(context)), 67 | ); 68 | } 69 | 70 | Widget _buildBodySection(BuildContext context) { 71 | final firestoreDatabase = 72 | Provider.of(context, listen: false); 73 | 74 | return StreamBuilder( 75 | stream: firestoreDatabase.todosStream(), 76 | builder: (context, snapshot) { 77 | if (snapshot.hasData) { 78 | List todos = snapshot.data as List; 79 | if (todos.isNotEmpty) { 80 | return ListView.separated( 81 | itemCount: todos.length, 82 | itemBuilder: (context, index) { 83 | return Dismissible( 84 | background: Container( 85 | color: Colors.red, 86 | child: Center( 87 | child: Text( 88 | AppLocalizations.of(context) 89 | .translate("todosDismissibleMsgTxt"), 90 | style: TextStyle(color: Theme.of(context).canvasColor), 91 | )), 92 | ), 93 | key: Key(todos[index].id), 94 | onDismissed: (direction) { 95 | firestoreDatabase.deleteTodo(todos[index]); 96 | 97 | _scaffoldKey.currentState!.showSnackBar(SnackBar( 98 | backgroundColor: Theme.of(context).appBarTheme.color, 99 | content: Text( 100 | AppLocalizations.of(context) 101 | .translate("todosSnackBarContent") + 102 | todos[index].task, 103 | style: 104 | TextStyle(color: Theme.of(context).canvasColor), 105 | ), 106 | duration: Duration(seconds: 3), 107 | action: SnackBarAction( 108 | label: AppLocalizations.of(context) 109 | .translate("todosSnackBarActionLbl"), 110 | textColor: Theme.of(context).canvasColor, 111 | onPressed: () { 112 | firestoreDatabase.setTodo(todos[index]); 113 | }, 114 | ), 115 | )); 116 | }, 117 | child: ListTile( 118 | leading: Checkbox( 119 | value: todos[index].complete, 120 | onChanged: (value) { 121 | TodoModel todo = TodoModel( 122 | id: todos[index].id, 123 | task: todos[index].task, 124 | extraNote: todos[index].extraNote, 125 | complete: value!); 126 | firestoreDatabase.setTodo(todo); 127 | }), 128 | title: Text(todos[index].task), 129 | onTap: () { 130 | Navigator.of(context).pushNamed(Routes.create_edit_todo, 131 | arguments: todos[index]); 132 | }, 133 | ), 134 | ); 135 | }, 136 | separatorBuilder: (context, index) { 137 | return Divider(height: 0.5); 138 | }, 139 | ); 140 | } else { 141 | return EmptyContentWidget( 142 | title: AppLocalizations.of(context) 143 | .translate("todosEmptyTopMsgDefaultTxt"), 144 | message: AppLocalizations.of(context) 145 | .translate("todosEmptyBottomDefaultMsgTxt"), 146 | key: Key('EmptyContentWidget'), 147 | ); 148 | } 149 | } else if (snapshot.hasError) { 150 | return EmptyContentWidget( 151 | title: 152 | AppLocalizations.of(context).translate("todosErrorTopMsgTxt"), 153 | message: AppLocalizations.of(context) 154 | .translate("todosErrorBottomMsgTxt"), 155 | key: Key('EmptyContentWidget'), 156 | ); 157 | } 158 | return Center(child: CircularProgressIndicator()); 159 | }); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /media/flavor-step-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-1.png -------------------------------------------------------------------------------- /media/flavor-step-1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-1b.png -------------------------------------------------------------------------------- /media/flavor-step-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-2.png -------------------------------------------------------------------------------- /media/flavor-step-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-3.png -------------------------------------------------------------------------------- /media/flavor-step-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-4.png -------------------------------------------------------------------------------- /media/flavor-step-4b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-4b.png -------------------------------------------------------------------------------- /media/flavor-step-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-5.png -------------------------------------------------------------------------------- /media/flavor-step-5b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/flavor-step-5b.png -------------------------------------------------------------------------------- /media/how-to-use-step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step2.png -------------------------------------------------------------------------------- /media/how-to-use-step4a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step4a.png -------------------------------------------------------------------------------- /media/how-to-use-step4b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step4b.png -------------------------------------------------------------------------------- /media/how-to-use-step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step5.png -------------------------------------------------------------------------------- /media/how-to-use-step6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step6.png -------------------------------------------------------------------------------- /media/how-to-use-step7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step7.png -------------------------------------------------------------------------------- /media/how-to-use-step8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step8.png -------------------------------------------------------------------------------- /media/how-to-use-step9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/how-to-use-step9.png -------------------------------------------------------------------------------- /media/language_control.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/language_control.gif -------------------------------------------------------------------------------- /media/todo-app-screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hotcappuccinodev/flutter-firebase-user-auth/ba6df926e5fb0a6f5bc6c4c5831618250184469f/media/todo-app-screenshots.png -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.6.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | cloud_firestore: 40 | dependency: "direct main" 41 | description: 42 | name: cloud_firestore 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "2.5.0" 46 | cloud_firestore_platform_interface: 47 | dependency: transitive 48 | description: 49 | name: cloud_firestore_platform_interface 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "5.4.0" 53 | cloud_firestore_web: 54 | dependency: transitive 55 | description: 56 | name: cloud_firestore_web 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.4.0" 60 | collection: 61 | dependency: transitive 62 | description: 63 | name: collection 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.15.0" 67 | cupertino_icons: 68 | dependency: "direct main" 69 | description: 70 | name: cupertino_icons 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.0.3" 74 | fake_async: 75 | dependency: transitive 76 | description: 77 | name: fake_async 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.2.0" 81 | ffi: 82 | dependency: transitive 83 | description: 84 | name: ffi 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.1.2" 88 | file: 89 | dependency: transitive 90 | description: 91 | name: file 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "6.1.2" 95 | firebase_auth: 96 | dependency: "direct main" 97 | description: 98 | name: firebase_auth 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "3.0.2" 102 | firebase_auth_platform_interface: 103 | dependency: transitive 104 | description: 105 | name: firebase_auth_platform_interface 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "6.0.1" 109 | firebase_auth_web: 110 | dependency: transitive 111 | description: 112 | name: firebase_auth_web 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "3.0.1" 116 | firebase_core: 117 | dependency: transitive 118 | description: 119 | name: firebase_core 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.5.0" 123 | firebase_core_platform_interface: 124 | dependency: transitive 125 | description: 126 | name: firebase_core_platform_interface 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "4.0.1" 130 | firebase_core_web: 131 | dependency: transitive 132 | description: 133 | name: firebase_core_web 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "1.1.0" 137 | flutter: 138 | dependency: "direct main" 139 | description: flutter 140 | source: sdk 141 | version: "0.0.0" 142 | flutter_localizations: 143 | dependency: "direct main" 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | flutter_platform_widgets: 148 | dependency: "direct main" 149 | description: 150 | name: flutter_platform_widgets 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "1.9.5" 154 | flutter_test: 155 | dependency: "direct dev" 156 | description: flutter 157 | source: sdk 158 | version: "0.0.0" 159 | flutter_web_plugins: 160 | dependency: transitive 161 | description: flutter 162 | source: sdk 163 | version: "0.0.0" 164 | http_parser: 165 | dependency: transitive 166 | description: 167 | name: http_parser 168 | url: "https://pub.dartlang.org" 169 | source: hosted 170 | version: "4.0.0" 171 | intl: 172 | dependency: transitive 173 | description: 174 | name: intl 175 | url: "https://pub.dartlang.org" 176 | source: hosted 177 | version: "0.17.0" 178 | js: 179 | dependency: transitive 180 | description: 181 | name: js 182 | url: "https://pub.dartlang.org" 183 | source: hosted 184 | version: "0.6.3" 185 | matcher: 186 | dependency: transitive 187 | description: 188 | name: matcher 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "0.12.10" 192 | meta: 193 | dependency: transitive 194 | description: 195 | name: meta 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "1.3.0" 199 | nested: 200 | dependency: transitive 201 | description: 202 | name: nested 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "1.0.0" 206 | path: 207 | dependency: transitive 208 | description: 209 | name: path 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "1.8.0" 213 | path_provider_linux: 214 | dependency: transitive 215 | description: 216 | name: path_provider_linux 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "2.0.2" 220 | path_provider_platform_interface: 221 | dependency: transitive 222 | description: 223 | name: path_provider_platform_interface 224 | url: "https://pub.dartlang.org" 225 | source: hosted 226 | version: "2.0.1" 227 | path_provider_windows: 228 | dependency: transitive 229 | description: 230 | name: path_provider_windows 231 | url: "https://pub.dartlang.org" 232 | source: hosted 233 | version: "2.0.3" 234 | platform: 235 | dependency: transitive 236 | description: 237 | name: platform 238 | url: "https://pub.dartlang.org" 239 | source: hosted 240 | version: "3.0.2" 241 | plugin_platform_interface: 242 | dependency: transitive 243 | description: 244 | name: plugin_platform_interface 245 | url: "https://pub.dartlang.org" 246 | source: hosted 247 | version: "2.0.1" 248 | process: 249 | dependency: transitive 250 | description: 251 | name: process 252 | url: "https://pub.dartlang.org" 253 | source: hosted 254 | version: "4.2.3" 255 | provider: 256 | dependency: "direct main" 257 | description: 258 | name: provider 259 | url: "https://pub.dartlang.org" 260 | source: hosted 261 | version: "6.0.0" 262 | shared_preferences: 263 | dependency: "direct main" 264 | description: 265 | name: shared_preferences 266 | url: "https://pub.dartlang.org" 267 | source: hosted 268 | version: "2.0.6" 269 | shared_preferences_linux: 270 | dependency: transitive 271 | description: 272 | name: shared_preferences_linux 273 | url: "https://pub.dartlang.org" 274 | source: hosted 275 | version: "2.0.2" 276 | shared_preferences_macos: 277 | dependency: transitive 278 | description: 279 | name: shared_preferences_macos 280 | url: "https://pub.dartlang.org" 281 | source: hosted 282 | version: "2.0.2" 283 | shared_preferences_platform_interface: 284 | dependency: transitive 285 | description: 286 | name: shared_preferences_platform_interface 287 | url: "https://pub.dartlang.org" 288 | source: hosted 289 | version: "2.0.0" 290 | shared_preferences_web: 291 | dependency: transitive 292 | description: 293 | name: shared_preferences_web 294 | url: "https://pub.dartlang.org" 295 | source: hosted 296 | version: "2.0.2" 297 | shared_preferences_windows: 298 | dependency: transitive 299 | description: 300 | name: shared_preferences_windows 301 | url: "https://pub.dartlang.org" 302 | source: hosted 303 | version: "2.0.2" 304 | sky_engine: 305 | dependency: transitive 306 | description: flutter 307 | source: sdk 308 | version: "0.0.99" 309 | source_span: 310 | dependency: transitive 311 | description: 312 | name: source_span 313 | url: "https://pub.dartlang.org" 314 | source: hosted 315 | version: "1.8.1" 316 | stack_trace: 317 | dependency: transitive 318 | description: 319 | name: stack_trace 320 | url: "https://pub.dartlang.org" 321 | source: hosted 322 | version: "1.10.0" 323 | stream_channel: 324 | dependency: transitive 325 | description: 326 | name: stream_channel 327 | url: "https://pub.dartlang.org" 328 | source: hosted 329 | version: "2.1.0" 330 | string_scanner: 331 | dependency: transitive 332 | description: 333 | name: string_scanner 334 | url: "https://pub.dartlang.org" 335 | source: hosted 336 | version: "1.1.0" 337 | term_glyph: 338 | dependency: transitive 339 | description: 340 | name: term_glyph 341 | url: "https://pub.dartlang.org" 342 | source: hosted 343 | version: "1.2.0" 344 | test_api: 345 | dependency: transitive 346 | description: 347 | name: test_api 348 | url: "https://pub.dartlang.org" 349 | source: hosted 350 | version: "0.3.0" 351 | typed_data: 352 | dependency: transitive 353 | description: 354 | name: typed_data 355 | url: "https://pub.dartlang.org" 356 | source: hosted 357 | version: "1.3.0" 358 | vector_math: 359 | dependency: transitive 360 | description: 361 | name: vector_math 362 | url: "https://pub.dartlang.org" 363 | source: hosted 364 | version: "2.1.0" 365 | win32: 366 | dependency: transitive 367 | description: 368 | name: win32 369 | url: "https://pub.dartlang.org" 370 | source: hosted 371 | version: "2.2.5" 372 | xdg_directories: 373 | dependency: transitive 374 | description: 375 | name: xdg_directories 376 | url: "https://pub.dartlang.org" 377 | source: hosted 378 | version: "0.2.0" 379 | sdks: 380 | dart: ">=2.13.0 <3.0.0" 381 | flutter: ">=2.0.0" 382 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: noteapp 2 | description: A new Flutter application. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.12.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | flutter_localizations: 27 | sdk: flutter 28 | 29 | 30 | # The following adds the Cupertino Icons font to your application. 31 | # Use with the CupertinoIcons class for iOS style icons. 32 | cupertino_icons: ^1.0.2 33 | provider: ^6.0.0 34 | shared_preferences: ^2.0.6 35 | firebase_auth: ^3.0.2 36 | cloud_firestore: ^2.5.0 37 | flutter_platform_widgets: ^1.9.5 38 | 39 | dev_dependencies: 40 | flutter_test: 41 | sdk: flutter 42 | 43 | # For information on the generic Dart part of this file, see the 44 | # following page: https://dart.dev/tools/pub/pubspec 45 | 46 | # The following section is specific to Flutter. 47 | flutter: 48 | 49 | # The following line ensures that the Material Icons font is 50 | # included with your application, so that you can use the icons in 51 | # the material Icons class. 52 | uses-material-design: true 53 | 54 | # To add assets to your application, add an assets section, like this: 55 | # assets: 56 | # - images/a_dot_burr.jpeg 57 | # - images/a_dot_ham.jpeg 58 | 59 | # An image asset can refer to one or more resolution-specific "variants", see 60 | # https://flutter.dev/assets-and-images/#resolution-aware. 61 | 62 | # For details regarding adding assets from package dependencies, see 63 | # https://flutter.dev/assets-and-images/#from-packages 64 | 65 | # To add custom fonts to your application, add a fonts section here, 66 | # in this "flutter" section. Each entry in this list should have a 67 | # "family" key with the font family name, and a "fonts" key with a 68 | # list giving the asset and other descriptors for the font. For 69 | # example: 70 | # fonts: 71 | # - family: Schyler 72 | # fonts: 73 | # - asset: fonts/Schyler-Regular.ttf 74 | # - asset: fonts/Schyler-Italic.ttf 75 | # style: italic 76 | # - family: Trajan Pro 77 | # fonts: 78 | # - asset: fonts/TrajanPro.ttf 79 | # - asset: fonts/TrajanPro_Bold.ttf 80 | # weight: 700 81 | # 82 | # For details regarding fonts from package dependencies, 83 | # see https://flutter.dev/custom-fonts/#from-packages 84 | --------------------------------------------------------------------------------