├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ ├── google-services.json
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── images
│ ├── default.png
│ ├── default.svg
│ ├── defaultDark.png
│ └── defaultold.png
├── ios
├── .gitignore
├── Flutter
│ ├── .last_build_id
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Generated 2.xcconfig
│ ├── Release.xcconfig
│ └── flutter_export_environment 2.sh
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── 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
│ ├── GoogleService-Info.plist
│ ├── Info.plist
│ ├── Runner-Bridging-Header.h
│ └── Runner.entitlements
├── lib
├── constants
│ ├── app_routes.dart
│ ├── app_themes.dart
│ ├── constants.dart
│ └── globals.dart
├── controllers
│ ├── auth_controller.dart
│ ├── controllers.dart
│ ├── language_controller.dart
│ └── theme_controller.dart
├── helpers
│ ├── gravatar.dart
│ ├── helpers.dart
│ ├── localization.g.dart
│ ├── update_localizations.dart
│ └── validator.dart
├── main.dart
├── models
│ ├── menu_option_model.dart
│ ├── models.dart
│ └── user_model.dart
└── ui
│ ├── auth
│ ├── auth.dart
│ ├── reset_password_ui.dart
│ ├── sign_in_ui.dart
│ ├── sign_up_ui.dart
│ └── update_profile_ui.dart
│ ├── components
│ ├── avatar.dart
│ ├── components.dart
│ ├── dropdown_picker.dart
│ ├── dropdown_picker_with_icon.dart
│ ├── form_input_field.dart
│ ├── form_input_field_with_icon.dart
│ ├── form_vertical_spacing.dart
│ ├── label_button.dart
│ ├── loading.dart
│ ├── logo_graphic_header.dart
│ ├── primary_button.dart
│ └── segmented_selector.dart
│ ├── home_ui.dart
│ ├── settings_ui.dart
│ ├── splash_ui.dart
│ └── ui.dart
├── pubspec.lock
├── pubspec.yaml
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.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 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Exceptions to above rules.
43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
44 |
45 | # added by delay
46 | /ios/Flutter/
47 | /ios/build/
48 |
--------------------------------------------------------------------------------
/.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: be3a4b37b3e9ab4e80d45b59bed53708b96d211f
8 | channel: dev
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Jeff McMorris
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## GetX Flutter Firebase Auth Example
2 |
3 | 
4 |
5 | UPDATE: Version 2.0.0 Changed to new language options and added null safety.
6 |
7 | GetX is a relatively new package for Flutter that provides the missing link in making Flutter development simpler. I recently converted a [firebase auth project](https://medium.com/@jeffmcmorris/flutter-firebase-auth-starter-project-b0f91a6503b7) I had created which used provider for state management. Switching to GetX simplified many of the pain points I have had with Flutter development. I no longer was having to pass context into functions. I could also better separate my logic from the UI. GetX also greatly simplifies routing, displaying snackbars and dialogs.
8 |
9 | There are some really good projects and tutorials that I made use of in making [this project](https://github.com/delay/flutter_starter). See these links for more help with GetX. [GetX Documentation](https://github.com/jonataslaw/getx), [Todo GetX example](https://medium.com/@loicgeek/flutter-how-to-create-a-todo-app-using-firebase-firestore-and-firebase-authentication-with-getx-89bdaacc6de6), [Amateur Coder GetX Videos](https://www.youtube.com/watch?v=CNpXbeI_slw) and [Loading Overlay](https://medium.com/@fayaz07/dont-kill-app-s-ui-thread-for-showing-loading-indicators-809e5a992230).
10 |
11 | So why would you want to use GetX? Let me give you an example of how it simplified my own code. When I used Provider there was a lot more boilerplate code. It felt much more esoteric to use. GetX made my code easier to understand. Here is my code for main.dart original vs. GetX.
12 |
13 | 
14 |
15 | Once you understand the GetX way it becomes much easier to organize your code and separate your concerns between your UI and functions. For instance when calling a function in the UI I was having to handle the results from the function and display snackbars with the results. With GetX I was able to move the snackbars into the actual function which makes more sense since I no longer have to send success and fail messages in and out of functions. Below I show a button which signs in the user with the old way vs GetX way. I prefer the GetX way even though it isn’t a lot shorter, but I like having my logic all separated from the UI.
16 |
17 | 
18 |
19 | GetX also has a storage package called [get_storage](https://github.com/jonataslaw/get_storage). It can take the place of shared preferences. It simplifies the way to store data on the device. Here is another example of before and after code.
20 |
21 | 
22 |
23 | There are many other features of GetX to make things simpler, such as working with themes, getting various device settings, etc. This package simplifies a lot of the problems developers face daily when building an app.
24 |
25 | When building an auth project there are a lot of the features you need for a production flutter project. I wanted light and dark mode theming but also the ability to detect and switch themes automatically. I needed the ability to switch between languages easily and automatically detect the user’s language. I wanted a simple way to handle translating from english (the only language I know unfortunately). This is accomplished by running a commandline app to generate the GetX Localization class which pulls from a [google sheet](https://docs.google.com/spreadsheets/d/1oS7iJ6ocrZBA53SxRfKF0CG9HAaXeKtzvsTBhgG4Zzk/edit#gid=0) and easily translate into other languages. Also I needed a way to [do simple user roles](https://medium.com/firebase-developers/patterns-for-security-with-firebase-group-based-permissions-for-cloud-firestore-72859cdec8f6) and it needed to be secure. I see a lot of auth packages including roles in the user’s collection in firestore which is usually editable by that same user. This would make it trivial for the user to assign himself admin privileges. I also wanted to show how to put some basic rules in firestore to secure it. Finally I wanted to have a way the user could alter their profile and change their email or password.
26 |
27 | To handle the language translation you need to create a translation for your app in google sheets. Then open /helpers/update_localizations.dart and replace the docID and sheetId with your own documentId and sheetId. After doing that your will need to drop to the command line and go into the helpers directory. Then type: ```dart update_localizations.dart```. This will create or overwrite the localization.g.dart file with your custom translation. There should not be a need to edit this file directly. Every time you make changes to your translation you will need to re-run this generator.
28 |
29 | 
30 |
31 | You can copy my [sheet](https://docs.google.com/spreadsheets/d/1oS7iJ6ocrZBA53SxRfKF0CG9HAaXeKtzvsTBhgG4Zzk/edit#gid=0) as a starting point for your own app. The cool thing about using a google sheet is you can have google translate a field with a simple google formula: =GOOGLETRANSLATE(B4,en,fr) This says translate the phrase in field B4 from english to french.
32 |
33 | To handle user roles I created a separate admin collection and added a document with the same document id as the uid of my user. The reason to do this is to make it secure as explained in this [medium article](https://medium.com/firebase-developers/patterns-for-security-with-firebase-group-based-permissions-for-cloud-firestore-72859cdec8f6). I went with the second method explained in that article. If we had just put the roles as a field in the users collection any user could have upgraded themselves to an admin user. So by moving the admin role to a separate collection we can create some rules in firestore that allow the user to update fields about themselves without giving them access to change the role they were assigned. You can also generate other roles for the user by simply adding additional collections for the other roles..
34 |
35 | The rules I have setup in firestore for this project are fairly simple. Here are the rules I have created.
36 |
37 | 
38 |
39 | The first rule matches any user in the admin collection and allows you to read that document only. No one is allowed to write to this collection. I manually add my admin users through the firebase console. The second rule allows the user to read and write only if the user matches the currently logged in user. So a user can only change information about themselves. Here is how my collections are setup in firestore.
40 |
41 | 
42 |
43 | Finally I wanted to explain a little bit about my ui. I try to control as much as possible with the theme. You can change a lot about the look with the user interface by changing the theme. I am still learning about what all can be changed with just the theme. I also break out small ui components into a separate components folder. Then I make a custom widget instead of using the standard widget directly. This allows me to make changes in one spot if I decide to make ui changes to say a form field in my form_input_field.dart instead of changing a bunch of TextFormField widgets spread through a dozen files.
44 |
45 | ## Overview of project
46 |
47 | **main.dart** — contains info for maintaining the state of the app for the theme, language and user. It initializes language and theme settings. Sets up routing.
48 |
49 |
50 |
51 | ## /constants/
52 |
53 | **app_themes.dart** — contains info related to our light and dark themes.
54 |
55 | **globals.dart** — contains some global app settings
56 |
57 | **app_routes.dart** — contains the app routes.
58 |
59 | ## /controllers/
60 |
61 | **auth_controller.dart** — our user and authentication functions for creating, logging in and out our user and saving our user data.
62 |
63 | **language_controller.dart** — saves and loads our selected language.
64 |
65 | **theme_controller.dart** — saves and loads our selected theme.
66 |
67 | ## /helpers/
68 |
69 | **validator.dart** — contains some validation functions for our form fields.
70 |
71 | **update_localizations.dart** — command line dart app that generates the localization.g.dart file.
72 |
73 | **localizations.g.dart** — this file is generated from our google sheet (do not manually edit this file).
74 |
75 | ## /models/
76 |
77 | **user_model.dart** — contains the model for our user saved in firestore.
78 |
79 | **menu_option_model.dart** — contains our model for our language options and theme options in settings.
80 |
81 | ## /ui/
82 |
83 | **home_ui.dart** — contains the ui for the home which shows info about the user.
84 |
85 | **settings_ui.dart** — contains the settings screen for setting the theme and language and some user settings.
86 |
87 | **splash_ui.dart** — contains the initial loading screen, currently just a circular progress indicator.
88 |
89 | ## /ui/auth/
90 |
91 | **reset_password_ui.dart** — sends a password reset email to the user.
92 |
93 | **sign_in_ui.dart** — allows user to login with email and password.
94 |
95 | **sign_up_ui.dart** — allows user to create a new account.
96 |
97 | **update_profile_ui.dart** — allows user to change his email or name.
98 |
99 | ## /ui/components/
100 |
101 | **avatar.dart** — displays a user avatar on the home_ui.
102 |
103 | **dropdown_picker.dart** — shows a dropdown list.
104 |
105 | **dropdown_picker_with_icon.dart** — shows a dropdown list with icons.
106 |
107 | **form_input_field.dart** — handles our form field elements.
108 |
109 | **form_input_field_with_icon.dart** — handles our form field elements but has an icon too.
110 |
111 | **form_vertical_spacing.dart** — just a space in the ui.
112 |
113 | **label_button.dart** — one type of button in ui.
114 |
115 | **loading.dart** — circular loading indicator overlay.
116 |
117 | **logo_graphic_header.dart** — a graphic displayed in our ui.
118 |
119 | **primary_button.dart** — another button in the ui.
120 |
121 | **segmented_selector.dart** — a control used to select the theme.
122 |
123 | Provider is also a great package and what I was using for Flutter development until I found GetX. Flutter is still new and evolving fast. It is fun to watch it progress so rapidly with the help of the Flutter community!
124 |
125 | Anyway hopefully this project will help someone. Feel free to use any of it, I didn’t create all of this code as parts of it came from watching the tutorials and reviewing the projects mentioned above. Make sure you [setup firebase](https://firebase.google.com/docs/flutter/setup?platform=android) with your project.
126 |
--------------------------------------------------------------------------------
/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: 'com.google.gms.google-services'
26 | apply plugin: 'kotlin-android'
27 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
28 |
29 |
30 | android {
31 | compileSdkVersion 28
32 |
33 | sourceSets {
34 | main.java.srcDirs += 'src/main/kotlin'
35 | }
36 |
37 | lintOptions {
38 | disable 'InvalidPackage'
39 | }
40 |
41 | defaultConfig {
42 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
43 | applicationId "com.tapmode.flutterstarter"
44 | minSdkVersion 16
45 | targetSdkVersion 28
46 | versionCode flutterVersionCode.toInteger()
47 | versionName flutterVersionName
48 | multiDexEnabled true
49 | }
50 |
51 | buildTypes {
52 | release {
53 | // TODO: Add your own signing config for the release build.
54 | // Signing with the debug keys for now, so `flutter run --release` works.
55 | signingConfig signingConfigs.debug
56 | }
57 | }
58 | }
59 |
60 | flutter {
61 | source '../..'
62 | }
63 |
64 | dependencies {
65 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
66 | implementation 'com.google.firebase:firebase-analytics:17.2.2'
67 | implementation 'com.android.support:multidex:1.0.3'
68 | }
69 |
--------------------------------------------------------------------------------
/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "524197078337",
4 | "firebase_url": "https://flutter-starter-delay.firebaseio.com",
5 | "project_id": "flutter-starter-delay",
6 | "storage_bucket": "flutter-starter-delay.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:524197078337:android:dee32de1a467249cfa2dc0",
12 | "android_client_info": {
13 | "package_name": "com.tapmode.flutterstarter"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "524197078337-5gq7dldnk4tt8q4cvtenbn08q5fn4vkj.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyCHe-BxbY8-_CWhZZRC5jqVY4c0ydUGw08"
25 | }
26 | ],
27 | "services": {
28 | "appinvite_service": {
29 | "other_platform_oauth_client": [
30 | {
31 | "client_id": "524197078337-5gq7dldnk4tt8q4cvtenbn08q5fn4vkj.apps.googleusercontent.com",
32 | "client_type": 3
33 | },
34 | {
35 | "client_id": "524197078337-96irqf3smo96s6f48mc1neh2vh7jber5.apps.googleusercontent.com",
36 | "client_type": 2,
37 | "ios_info": {
38 | "bundle_id": "com.tapmode.flutter-starter"
39 | }
40 | }
41 | ]
42 | }
43 | }
44 | }
45 | ],
46 | "configuration_version": "1"
47 | }
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/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/images/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/assets/images/default.png
--------------------------------------------------------------------------------
/assets/images/default.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/images/defaultDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/assets/images/defaultDark.png
--------------------------------------------------------------------------------
/assets/images/defaultold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/assets/images/defaultold.png
--------------------------------------------------------------------------------
/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/.last_build_id:
--------------------------------------------------------------------------------
1 | c3df2818212c7215afb888c221a81ee3
--------------------------------------------------------------------------------
/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? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
3 | #include "Generated.xcconfig"
4 |
--------------------------------------------------------------------------------
/ios/Flutter/Generated 2.xcconfig:
--------------------------------------------------------------------------------
1 | // This is a generated file; do not edit or check into version control.
2 | FLUTTER_ROOT=/Users/delay/development/flutter
3 | FLUTTER_APPLICATION_PATH=/Users/delay/Desktop/Programming/flutter_starter
4 | FLUTTER_TARGET=/Users/delay/Desktop/Programming/flutter_starter/lib/main.dart
5 | FLUTTER_BUILD_DIR=build
6 | SYMROOT=${SOURCE_ROOT}/../build/ios
7 | OTHER_LDFLAGS=$(inherited) -framework Flutter
8 | FLUTTER_FRAMEWORK_DIR=/Users/delay/development/flutter/bin/cache/artifacts/engine/ios
9 | FLUTTER_BUILD_NAME=1.0.0
10 | FLUTTER_BUILD_NUMBER=1
11 | DART_OBFUSCATION=false
12 | TRACK_WIDGET_CREATION=true
13 | TREE_SHAKE_ICONS=false
14 | PACKAGE_CONFIG=.packages
15 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
3 | #include "Generated.xcconfig"
4 |
--------------------------------------------------------------------------------
/ios/Flutter/flutter_export_environment 2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/delay/development/flutter"
4 | export "FLUTTER_APPLICATION_PATH=/Users/delay/Desktop/Programming/flutter_starter"
5 | export "FLUTTER_TARGET=/Users/delay/Desktop/Programming/flutter_starter/lib/main.dart"
6 | export "FLUTTER_BUILD_DIR=build"
7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios"
8 | export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
9 | export "FLUTTER_FRAMEWORK_DIR=/Users/delay/development/flutter/bin/cache/artifacts/engine/ios"
10 | export "FLUTTER_BUILD_NAME=1.0.0"
11 | export "FLUTTER_BUILD_NUMBER=1"
12 | export "DART_OBFUSCATION=false"
13 | export "TRACK_WIDGET_CREATION=true"
14 | export "TREE_SHAKE_ICONS=false"
15 | export "PACKAGE_CONFIG=.packages"
16 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - abseil/algorithm (0.20200225.0):
3 | - abseil/algorithm/algorithm (= 0.20200225.0)
4 | - abseil/algorithm/container (= 0.20200225.0)
5 | - abseil/algorithm/algorithm (0.20200225.0):
6 | - abseil/base/config
7 | - abseil/algorithm/container (0.20200225.0):
8 | - abseil/algorithm/algorithm
9 | - abseil/base/core_headers
10 | - abseil/meta/type_traits
11 | - abseil/base (0.20200225.0):
12 | - abseil/base/atomic_hook (= 0.20200225.0)
13 | - abseil/base/base (= 0.20200225.0)
14 | - abseil/base/base_internal (= 0.20200225.0)
15 | - abseil/base/bits (= 0.20200225.0)
16 | - abseil/base/config (= 0.20200225.0)
17 | - abseil/base/core_headers (= 0.20200225.0)
18 | - abseil/base/dynamic_annotations (= 0.20200225.0)
19 | - abseil/base/endian (= 0.20200225.0)
20 | - abseil/base/errno_saver (= 0.20200225.0)
21 | - abseil/base/exponential_biased (= 0.20200225.0)
22 | - abseil/base/log_severity (= 0.20200225.0)
23 | - abseil/base/malloc_internal (= 0.20200225.0)
24 | - abseil/base/periodic_sampler (= 0.20200225.0)
25 | - abseil/base/pretty_function (= 0.20200225.0)
26 | - abseil/base/raw_logging_internal (= 0.20200225.0)
27 | - abseil/base/spinlock_wait (= 0.20200225.0)
28 | - abseil/base/throw_delegate (= 0.20200225.0)
29 | - abseil/base/atomic_hook (0.20200225.0):
30 | - abseil/base/config
31 | - abseil/base/core_headers
32 | - abseil/base/base (0.20200225.0):
33 | - abseil/base/atomic_hook
34 | - abseil/base/base_internal
35 | - abseil/base/config
36 | - abseil/base/core_headers
37 | - abseil/base/dynamic_annotations
38 | - abseil/base/log_severity
39 | - abseil/base/raw_logging_internal
40 | - abseil/base/spinlock_wait
41 | - abseil/meta/type_traits
42 | - abseil/base/base_internal (0.20200225.0):
43 | - abseil/base/config
44 | - abseil/meta/type_traits
45 | - abseil/base/bits (0.20200225.0):
46 | - abseil/base/config
47 | - abseil/base/core_headers
48 | - abseil/base/config (0.20200225.0)
49 | - abseil/base/core_headers (0.20200225.0):
50 | - abseil/base/config
51 | - abseil/base/dynamic_annotations (0.20200225.0)
52 | - abseil/base/endian (0.20200225.0):
53 | - abseil/base/config
54 | - abseil/base/core_headers
55 | - abseil/base/errno_saver (0.20200225.0):
56 | - abseil/base/config
57 | - abseil/base/exponential_biased (0.20200225.0):
58 | - abseil/base/config
59 | - abseil/base/core_headers
60 | - abseil/base/log_severity (0.20200225.0):
61 | - abseil/base/config
62 | - abseil/base/core_headers
63 | - abseil/base/malloc_internal (0.20200225.0):
64 | - abseil/base/base
65 | - abseil/base/base_internal
66 | - abseil/base/config
67 | - abseil/base/core_headers
68 | - abseil/base/dynamic_annotations
69 | - abseil/base/raw_logging_internal
70 | - abseil/base/periodic_sampler (0.20200225.0):
71 | - abseil/base/core_headers
72 | - abseil/base/exponential_biased
73 | - abseil/base/pretty_function (0.20200225.0)
74 | - abseil/base/raw_logging_internal (0.20200225.0):
75 | - abseil/base/atomic_hook
76 | - abseil/base/config
77 | - abseil/base/core_headers
78 | - abseil/base/log_severity
79 | - abseil/base/spinlock_wait (0.20200225.0):
80 | - abseil/base/base_internal
81 | - abseil/base/core_headers
82 | - abseil/base/errno_saver
83 | - abseil/base/throw_delegate (0.20200225.0):
84 | - abseil/base/config
85 | - abseil/base/raw_logging_internal
86 | - abseil/container/compressed_tuple (0.20200225.0):
87 | - abseil/utility/utility
88 | - abseil/container/inlined_vector (0.20200225.0):
89 | - abseil/algorithm/algorithm
90 | - abseil/base/core_headers
91 | - abseil/base/throw_delegate
92 | - abseil/container/inlined_vector_internal
93 | - abseil/memory/memory
94 | - abseil/container/inlined_vector_internal (0.20200225.0):
95 | - abseil/base/core_headers
96 | - abseil/container/compressed_tuple
97 | - abseil/memory/memory
98 | - abseil/meta/type_traits
99 | - abseil/types/span
100 | - abseil/memory (0.20200225.0):
101 | - abseil/memory/memory (= 0.20200225.0)
102 | - abseil/memory/memory (0.20200225.0):
103 | - abseil/base/core_headers
104 | - abseil/meta/type_traits
105 | - abseil/meta (0.20200225.0):
106 | - abseil/meta/type_traits (= 0.20200225.0)
107 | - abseil/meta/type_traits (0.20200225.0):
108 | - abseil/base/config
109 | - abseil/numeric/int128 (0.20200225.0):
110 | - abseil/base/config
111 | - abseil/base/core_headers
112 | - abseil/strings/internal (0.20200225.0):
113 | - abseil/base/config
114 | - abseil/base/core_headers
115 | - abseil/base/endian
116 | - abseil/base/raw_logging_internal
117 | - abseil/meta/type_traits
118 | - abseil/strings/str_format (0.20200225.0):
119 | - abseil/strings/str_format_internal
120 | - abseil/strings/str_format_internal (0.20200225.0):
121 | - abseil/base/config
122 | - abseil/base/core_headers
123 | - abseil/meta/type_traits
124 | - abseil/numeric/int128
125 | - abseil/strings/strings
126 | - abseil/types/span
127 | - abseil/strings/strings (0.20200225.0):
128 | - abseil/base/base
129 | - abseil/base/bits
130 | - abseil/base/config
131 | - abseil/base/core_headers
132 | - abseil/base/endian
133 | - abseil/base/raw_logging_internal
134 | - abseil/base/throw_delegate
135 | - abseil/memory/memory
136 | - abseil/meta/type_traits
137 | - abseil/numeric/int128
138 | - abseil/strings/internal
139 | - abseil/time (0.20200225.0):
140 | - abseil/time/internal (= 0.20200225.0)
141 | - abseil/time/time (= 0.20200225.0)
142 | - abseil/time/internal (0.20200225.0):
143 | - abseil/time/internal/cctz (= 0.20200225.0)
144 | - abseil/time/internal/cctz (0.20200225.0):
145 | - abseil/time/internal/cctz/civil_time (= 0.20200225.0)
146 | - abseil/time/internal/cctz/time_zone (= 0.20200225.0)
147 | - abseil/time/internal/cctz/civil_time (0.20200225.0):
148 | - abseil/base/config
149 | - abseil/time/internal/cctz/time_zone (0.20200225.0):
150 | - abseil/base/config
151 | - abseil/time/internal/cctz/civil_time
152 | - abseil/time/time (0.20200225.0):
153 | - abseil/base/base
154 | - abseil/base/core_headers
155 | - abseil/base/raw_logging_internal
156 | - abseil/numeric/int128
157 | - abseil/strings/strings
158 | - abseil/time/internal/cctz/civil_time
159 | - abseil/time/internal/cctz/time_zone
160 | - abseil/types (0.20200225.0):
161 | - abseil/types/any (= 0.20200225.0)
162 | - abseil/types/bad_any_cast (= 0.20200225.0)
163 | - abseil/types/bad_any_cast_impl (= 0.20200225.0)
164 | - abseil/types/bad_optional_access (= 0.20200225.0)
165 | - abseil/types/bad_variant_access (= 0.20200225.0)
166 | - abseil/types/compare (= 0.20200225.0)
167 | - abseil/types/optional (= 0.20200225.0)
168 | - abseil/types/span (= 0.20200225.0)
169 | - abseil/types/variant (= 0.20200225.0)
170 | - abseil/types/any (0.20200225.0):
171 | - abseil/base/config
172 | - abseil/base/core_headers
173 | - abseil/meta/type_traits
174 | - abseil/types/bad_any_cast
175 | - abseil/utility/utility
176 | - abseil/types/bad_any_cast (0.20200225.0):
177 | - abseil/base/config
178 | - abseil/types/bad_any_cast_impl
179 | - abseil/types/bad_any_cast_impl (0.20200225.0):
180 | - abseil/base/config
181 | - abseil/base/raw_logging_internal
182 | - abseil/types/bad_optional_access (0.20200225.0):
183 | - abseil/base/config
184 | - abseil/base/raw_logging_internal
185 | - abseil/types/bad_variant_access (0.20200225.0):
186 | - abseil/base/config
187 | - abseil/base/raw_logging_internal
188 | - abseil/types/compare (0.20200225.0):
189 | - abseil/base/core_headers
190 | - abseil/meta/type_traits
191 | - abseil/types/optional (0.20200225.0):
192 | - abseil/base/base_internal
193 | - abseil/base/config
194 | - abseil/base/core_headers
195 | - abseil/memory/memory
196 | - abseil/meta/type_traits
197 | - abseil/types/bad_optional_access
198 | - abseil/utility/utility
199 | - abseil/types/span (0.20200225.0):
200 | - abseil/algorithm/algorithm
201 | - abseil/base/core_headers
202 | - abseil/base/throw_delegate
203 | - abseil/meta/type_traits
204 | - abseil/types/variant (0.20200225.0):
205 | - abseil/base/base_internal
206 | - abseil/base/config
207 | - abseil/base/core_headers
208 | - abseil/meta/type_traits
209 | - abseil/types/bad_variant_access
210 | - abseil/utility/utility
211 | - abseil/utility/utility (0.20200225.0):
212 | - abseil/base/base_internal
213 | - abseil/base/config
214 | - abseil/meta/type_traits
215 | - BoringSSL-GRPC (0.0.7):
216 | - BoringSSL-GRPC/Implementation (= 0.0.7)
217 | - BoringSSL-GRPC/Interface (= 0.0.7)
218 | - BoringSSL-GRPC/Implementation (0.0.7):
219 | - BoringSSL-GRPC/Interface (= 0.0.7)
220 | - BoringSSL-GRPC/Interface (0.0.7)
221 | - cloud_firestore (1.0.4):
222 | - Firebase/Firestore (= 7.3.0)
223 | - firebase_core
224 | - Flutter
225 | - Firebase/Auth (7.3.0):
226 | - Firebase/CoreOnly
227 | - FirebaseAuth (~> 7.3.0)
228 | - Firebase/CoreOnly (7.3.0):
229 | - FirebaseCore (= 7.3.0)
230 | - Firebase/Firestore (7.3.0):
231 | - Firebase/CoreOnly
232 | - FirebaseFirestore (~> 7.3.0)
233 | - firebase_auth (1.0.2):
234 | - Firebase/Auth (= 7.3.0)
235 | - firebase_core
236 | - Flutter
237 | - firebase_core (1.0.3):
238 | - Firebase/CoreOnly (= 7.3.0)
239 | - Flutter
240 | - FirebaseAuth (7.3.0):
241 | - FirebaseCore (~> 7.0)
242 | - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
243 | - GoogleUtilities/Environment (~> 7.0)
244 | - GTMSessionFetcher/Core (~> 1.4)
245 | - FirebaseCore (7.3.0):
246 | - FirebaseCoreDiagnostics (~> 7.0)
247 | - GoogleUtilities/Environment (~> 7.0)
248 | - GoogleUtilities/Logger (~> 7.0)
249 | - FirebaseCoreDiagnostics (7.3.0):
250 | - GoogleDataTransport (~> 8.0)
251 | - GoogleUtilities/Environment (~> 7.0)
252 | - GoogleUtilities/Logger (~> 7.0)
253 | - nanopb (~> 2.30906.0)
254 | - FirebaseFirestore (7.3.0):
255 | - abseil/algorithm (= 0.20200225.0)
256 | - abseil/base (= 0.20200225.0)
257 | - abseil/memory (= 0.20200225.0)
258 | - abseil/meta (= 0.20200225.0)
259 | - abseil/strings/strings (= 0.20200225.0)
260 | - abseil/time (= 0.20200225.0)
261 | - abseil/types (= 0.20200225.0)
262 | - FirebaseCore (~> 7.0)
263 | - "gRPC-C++ (~> 1.28.0)"
264 | - leveldb-library (~> 1.22)
265 | - nanopb (~> 2.30906.0)
266 | - Flutter (1.0.0)
267 | - GoogleDataTransport (8.1.0):
268 | - nanopb (~> 2.30906.0)
269 | - GoogleUtilities/AppDelegateSwizzler (7.2.2):
270 | - GoogleUtilities/Environment
271 | - GoogleUtilities/Logger
272 | - GoogleUtilities/Network
273 | - GoogleUtilities/Environment (7.2.2):
274 | - PromisesObjC (~> 1.2)
275 | - GoogleUtilities/Logger (7.2.2):
276 | - GoogleUtilities/Environment
277 | - GoogleUtilities/Network (7.2.2):
278 | - GoogleUtilities/Logger
279 | - "GoogleUtilities/NSData+zlib"
280 | - GoogleUtilities/Reachability
281 | - "GoogleUtilities/NSData+zlib (7.2.2)"
282 | - GoogleUtilities/Reachability (7.2.2):
283 | - GoogleUtilities/Logger
284 | - "gRPC-C++ (1.28.2)":
285 | - "gRPC-C++/Implementation (= 1.28.2)"
286 | - "gRPC-C++/Interface (= 1.28.2)"
287 | - "gRPC-C++/Implementation (1.28.2)":
288 | - abseil/container/inlined_vector (= 0.20200225.0)
289 | - abseil/memory/memory (= 0.20200225.0)
290 | - abseil/strings/str_format (= 0.20200225.0)
291 | - abseil/strings/strings (= 0.20200225.0)
292 | - abseil/types/optional (= 0.20200225.0)
293 | - "gRPC-C++/Interface (= 1.28.2)"
294 | - gRPC-Core (= 1.28.2)
295 | - "gRPC-C++/Interface (1.28.2)"
296 | - gRPC-Core (1.28.2):
297 | - gRPC-Core/Implementation (= 1.28.2)
298 | - gRPC-Core/Interface (= 1.28.2)
299 | - gRPC-Core/Implementation (1.28.2):
300 | - abseil/container/inlined_vector (= 0.20200225.0)
301 | - abseil/memory/memory (= 0.20200225.0)
302 | - abseil/strings/str_format (= 0.20200225.0)
303 | - abseil/strings/strings (= 0.20200225.0)
304 | - abseil/types/optional (= 0.20200225.0)
305 | - BoringSSL-GRPC (= 0.0.7)
306 | - gRPC-Core/Interface (= 1.28.2)
307 | - gRPC-Core/Interface (1.28.2)
308 | - GTMSessionFetcher/Core (1.5.0)
309 | - leveldb-library (1.22)
310 | - nanopb (2.30906.0):
311 | - nanopb/decode (= 2.30906.0)
312 | - nanopb/encode (= 2.30906.0)
313 | - nanopb/decode (2.30906.0)
314 | - nanopb/encode (2.30906.0)
315 | - path_provider (0.0.1):
316 | - Flutter
317 | - PromisesObjC (1.2.12)
318 |
319 | DEPENDENCIES:
320 | - cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`)
321 | - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
322 | - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
323 | - Flutter (from `Flutter`)
324 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
325 |
326 | SPEC REPOS:
327 | trunk:
328 | - abseil
329 | - BoringSSL-GRPC
330 | - Firebase
331 | - FirebaseAuth
332 | - FirebaseCore
333 | - FirebaseCoreDiagnostics
334 | - FirebaseFirestore
335 | - GoogleDataTransport
336 | - GoogleUtilities
337 | - "gRPC-C++"
338 | - gRPC-Core
339 | - GTMSessionFetcher
340 | - leveldb-library
341 | - nanopb
342 | - PromisesObjC
343 |
344 | EXTERNAL SOURCES:
345 | cloud_firestore:
346 | :path: ".symlinks/plugins/cloud_firestore/ios"
347 | firebase_auth:
348 | :path: ".symlinks/plugins/firebase_auth/ios"
349 | firebase_core:
350 | :path: ".symlinks/plugins/firebase_core/ios"
351 | Flutter:
352 | :path: Flutter
353 | path_provider:
354 | :path: ".symlinks/plugins/path_provider/ios"
355 |
356 | SPEC CHECKSUMS:
357 | abseil: 6c8eb7892aefa08d929b39f9bb108e5367e3228f
358 | BoringSSL-GRPC: 8edf627ee524575e2f8d19d56f068b448eea3879
359 | cloud_firestore: d5902cdb3c48c2e8c73cd093fc9471ebe7f44a4c
360 | Firebase: 26223c695fe322633274198cb19dca8cb7e54416
361 | firebase_auth: 9e9e667b904ee5701ab50330a5718cce0bf1a469
362 | firebase_core: b5d81dfd4fb2d6f700e67de34d9a633ae325c4e9
363 | FirebaseAuth: c224a0cf1afa0949bd5c7bfcf154b4f5ce8ddef2
364 | FirebaseCore: 4d3c72622ce0e2106aaa07bb4b2935ba2c370972
365 | FirebaseCoreDiagnostics: d50e11039e5984d92c8a512be2395f13df747350
366 | FirebaseFirestore: 1906bf163afdb7c432d2e3b5c40ceb9dd2df5820
367 | Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
368 | GoogleDataTransport: 116c84c4bdeb76be2a7a46de51244368f9794eab
369 | GoogleUtilities: 31c5b01f978a70c6cff2afc6272b3f1921614b43
370 | "gRPC-C++": 13d8ccef97d5c3c441b7e3c529ef28ebee86fad2
371 | gRPC-Core: 4afa11bfbedf7cdecd04de535a9e046893404ed5
372 | GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
373 | leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
374 | nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53
375 | path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
376 | PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
377 |
378 | PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
379 |
380 | COCOAPODS: 1.10.1
381 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 51;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 2E5833C324342ED500830150 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2E5833C224342ED500830150 /* GoogleService-Info.plist */; };
12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
14 | 82F798BCCFC6D6226ACA286F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30051A2D6B1659C900C28076 /* Pods_Runner.framework */; };
15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXCopyFilesBuildPhase section */
21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
22 | isa = PBXCopyFilesBuildPhase;
23 | buildActionMask = 2147483647;
24 | dstPath = "";
25 | dstSubfolderSpec = 10;
26 | files = (
27 | );
28 | name = "Embed Frameworks";
29 | runOnlyForDeploymentPostprocessing = 0;
30 | };
31 | /* End PBXCopyFilesBuildPhase section */
32 |
33 | /* Begin PBXFileReference section */
34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
36 | 21771023C31C7AD00E2E5700 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
37 | 2E5833C224342ED500830150 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
38 | 2EE2152924579A5C002431C5 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
39 | 30051A2D6B1659C900C28076 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
40 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
41 | 526314EF7DA2AD6AAC6CFB26 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; 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 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
48 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
49 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
50 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
51 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
52 | FF252FC998AB9F74EB188D26 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | 82F798BCCFC6D6226ACA286F /* Pods_Runner.framework in Frameworks */,
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXFrameworksBuildPhase section */
65 |
66 | /* Begin PBXGroup section */
67 | 6736A9D1F96982A3A594AB50 /* Frameworks */ = {
68 | isa = PBXGroup;
69 | children = (
70 | 30051A2D6B1659C900C28076 /* Pods_Runner.framework */,
71 | );
72 | name = Frameworks;
73 | sourceTree = "";
74 | };
75 | 8DD15DB468BEA89EBC7F2F1A /* Pods */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 21771023C31C7AD00E2E5700 /* Pods-Runner.debug.xcconfig */,
79 | FF252FC998AB9F74EB188D26 /* Pods-Runner.release.xcconfig */,
80 | 526314EF7DA2AD6AAC6CFB26 /* Pods-Runner.profile.xcconfig */,
81 | );
82 | path = Pods;
83 | sourceTree = "";
84 | };
85 | 9740EEB11CF90186004384FC /* Flutter */ = {
86 | isa = PBXGroup;
87 | children = (
88 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
89 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
90 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
91 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
92 | );
93 | name = Flutter;
94 | sourceTree = "";
95 | };
96 | 97C146E51CF9000F007C117D = {
97 | isa = PBXGroup;
98 | children = (
99 | 9740EEB11CF90186004384FC /* Flutter */,
100 | 97C146F01CF9000F007C117D /* Runner */,
101 | 97C146EF1CF9000F007C117D /* Products */,
102 | 8DD15DB468BEA89EBC7F2F1A /* Pods */,
103 | 6736A9D1F96982A3A594AB50 /* Frameworks */,
104 | );
105 | sourceTree = "";
106 | };
107 | 97C146EF1CF9000F007C117D /* Products */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 97C146EE1CF9000F007C117D /* Runner.app */,
111 | );
112 | name = Products;
113 | sourceTree = "";
114 | };
115 | 97C146F01CF9000F007C117D /* Runner */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 2EE2152924579A5C002431C5 /* Runner.entitlements */,
119 | 2E5833C224342ED500830150 /* GoogleService-Info.plist */,
120 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
121 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
122 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
123 | 97C147021CF9000F007C117D /* Info.plist */,
124 | 97C146F11CF9000F007C117D /* Supporting Files */,
125 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
126 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
127 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
128 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
129 | );
130 | path = Runner;
131 | sourceTree = "";
132 | };
133 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
134 | isa = PBXGroup;
135 | children = (
136 | );
137 | name = "Supporting Files";
138 | sourceTree = "";
139 | };
140 | /* End PBXGroup section */
141 |
142 | /* Begin PBXNativeTarget section */
143 | 97C146ED1CF9000F007C117D /* Runner */ = {
144 | isa = PBXNativeTarget;
145 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
146 | buildPhases = (
147 | C404887B96C841A9CE6156EF /* [CP] Check Pods Manifest.lock */,
148 | 9740EEB61CF901F6004384FC /* Run Script */,
149 | 97C146EA1CF9000F007C117D /* Sources */,
150 | 97C146EB1CF9000F007C117D /* Frameworks */,
151 | 97C146EC1CF9000F007C117D /* Resources */,
152 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
153 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
154 | 7E15B24DA6CDB511582AA638 /* [CP] Embed Pods Frameworks */,
155 | );
156 | buildRules = (
157 | );
158 | dependencies = (
159 | );
160 | name = Runner;
161 | productName = Runner;
162 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
163 | productType = "com.apple.product-type.application";
164 | };
165 | /* End PBXNativeTarget section */
166 |
167 | /* Begin PBXProject section */
168 | 97C146E61CF9000F007C117D /* Project object */ = {
169 | isa = PBXProject;
170 | attributes = {
171 | LastUpgradeCheck = 1240;
172 | ORGANIZATIONNAME = "";
173 | TargetAttributes = {
174 | 97C146ED1CF9000F007C117D = {
175 | CreatedOnToolsVersion = 7.3.1;
176 | LastSwiftMigration = 1100;
177 | };
178 | };
179 | };
180 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
181 | compatibilityVersion = "Xcode 9.3";
182 | developmentRegion = en;
183 | hasScannedForEncodings = 0;
184 | knownRegions = (
185 | en,
186 | Base,
187 | );
188 | mainGroup = 97C146E51CF9000F007C117D;
189 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
190 | projectDirPath = "";
191 | projectRoot = "";
192 | targets = (
193 | 97C146ED1CF9000F007C117D /* Runner */,
194 | );
195 | };
196 | /* End PBXProject section */
197 |
198 | /* Begin PBXResourcesBuildPhase section */
199 | 97C146EC1CF9000F007C117D /* Resources */ = {
200 | isa = PBXResourcesBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
204 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
205 | 2E5833C324342ED500830150 /* GoogleService-Info.plist in Resources */,
206 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
207 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
208 | );
209 | runOnlyForDeploymentPostprocessing = 0;
210 | };
211 | /* End PBXResourcesBuildPhase section */
212 |
213 | /* Begin PBXShellScriptBuildPhase section */
214 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
215 | isa = PBXShellScriptBuildPhase;
216 | buildActionMask = 2147483647;
217 | files = (
218 | );
219 | inputPaths = (
220 | );
221 | name = "Thin Binary";
222 | outputPaths = (
223 | );
224 | runOnlyForDeploymentPostprocessing = 0;
225 | shellPath = /bin/sh;
226 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
227 | };
228 | 7E15B24DA6CDB511582AA638 /* [CP] Embed Pods Frameworks */ = {
229 | isa = PBXShellScriptBuildPhase;
230 | buildActionMask = 2147483647;
231 | files = (
232 | );
233 | inputFileListPaths = (
234 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
235 | );
236 | name = "[CP] Embed Pods Frameworks";
237 | outputFileListPaths = (
238 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | shellPath = /bin/sh;
242 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
243 | showEnvVarsInLog = 0;
244 | };
245 | 9740EEB61CF901F6004384FC /* Run Script */ = {
246 | isa = PBXShellScriptBuildPhase;
247 | buildActionMask = 2147483647;
248 | files = (
249 | );
250 | inputPaths = (
251 | );
252 | name = "Run Script";
253 | outputPaths = (
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | shellPath = /bin/sh;
257 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
258 | };
259 | C404887B96C841A9CE6156EF /* [CP] Check Pods Manifest.lock */ = {
260 | isa = PBXShellScriptBuildPhase;
261 | buildActionMask = 2147483647;
262 | files = (
263 | );
264 | inputFileListPaths = (
265 | );
266 | inputPaths = (
267 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
268 | "${PODS_ROOT}/Manifest.lock",
269 | );
270 | name = "[CP] Check Pods Manifest.lock";
271 | outputFileListPaths = (
272 | );
273 | outputPaths = (
274 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
275 | );
276 | runOnlyForDeploymentPostprocessing = 0;
277 | shellPath = /bin/sh;
278 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
279 | showEnvVarsInLog = 0;
280 | };
281 | /* End PBXShellScriptBuildPhase section */
282 |
283 | /* Begin PBXSourcesBuildPhase section */
284 | 97C146EA1CF9000F007C117D /* Sources */ = {
285 | isa = PBXSourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
289 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
290 | );
291 | runOnlyForDeploymentPostprocessing = 0;
292 | };
293 | /* End PBXSourcesBuildPhase section */
294 |
295 | /* Begin PBXVariantGroup section */
296 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
297 | isa = PBXVariantGroup;
298 | children = (
299 | 97C146FB1CF9000F007C117D /* Base */,
300 | );
301 | name = Main.storyboard;
302 | sourceTree = "";
303 | };
304 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
305 | isa = PBXVariantGroup;
306 | children = (
307 | 97C147001CF9000F007C117D /* Base */,
308 | );
309 | name = LaunchScreen.storyboard;
310 | sourceTree = "";
311 | };
312 | /* End PBXVariantGroup section */
313 |
314 | /* Begin XCBuildConfiguration section */
315 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
316 | isa = XCBuildConfiguration;
317 | buildSettings = {
318 | ALWAYS_SEARCH_USER_PATHS = NO;
319 | CLANG_ANALYZER_NONNULL = YES;
320 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
321 | CLANG_CXX_LIBRARY = "libc++";
322 | CLANG_ENABLE_MODULES = YES;
323 | CLANG_ENABLE_OBJC_ARC = YES;
324 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
325 | CLANG_WARN_BOOL_CONVERSION = YES;
326 | CLANG_WARN_COMMA = YES;
327 | CLANG_WARN_CONSTANT_CONVERSION = YES;
328 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
329 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
330 | CLANG_WARN_EMPTY_BODY = YES;
331 | CLANG_WARN_ENUM_CONVERSION = YES;
332 | CLANG_WARN_INFINITE_RECURSION = YES;
333 | CLANG_WARN_INT_CONVERSION = YES;
334 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
335 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
336 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
337 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
338 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
339 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
340 | CLANG_WARN_STRICT_PROTOTYPES = YES;
341 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
342 | CLANG_WARN_UNREACHABLE_CODE = YES;
343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
344 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
345 | COPY_PHASE_STRIP = NO;
346 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
347 | ENABLE_NS_ASSERTIONS = NO;
348 | ENABLE_STRICT_OBJC_MSGSEND = YES;
349 | GCC_C_LANGUAGE_STANDARD = gnu99;
350 | GCC_NO_COMMON_BLOCKS = YES;
351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
353 | GCC_WARN_UNDECLARED_SELECTOR = YES;
354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
355 | GCC_WARN_UNUSED_FUNCTION = YES;
356 | GCC_WARN_UNUSED_VARIABLE = YES;
357 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
358 | MTL_ENABLE_DEBUG_INFO = NO;
359 | SDKROOT = iphoneos;
360 | SUPPORTED_PLATFORMS = iphoneos;
361 | TARGETED_DEVICE_FAMILY = "1,2";
362 | VALIDATE_PRODUCT = YES;
363 | };
364 | name = Profile;
365 | };
366 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
367 | isa = XCBuildConfiguration;
368 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
369 | buildSettings = {
370 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
371 | CLANG_ENABLE_MODULES = YES;
372 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
373 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
374 | DEVELOPMENT_TEAM = B64VL7ASS3;
375 | ENABLE_BITCODE = NO;
376 | FRAMEWORK_SEARCH_PATHS = (
377 | "$(inherited)",
378 | "$(PROJECT_DIR)/Flutter",
379 | );
380 | INFOPLIST_FILE = Runner/Info.plist;
381 | LD_RUNPATH_SEARCH_PATHS = (
382 | "$(inherited)",
383 | "@executable_path/Frameworks",
384 | );
385 | LIBRARY_SEARCH_PATHS = (
386 | "$(inherited)",
387 | "$(PROJECT_DIR)/Flutter",
388 | );
389 | PRODUCT_BUNDLE_IDENTIFIER = "com.tapmode.flutter-starter";
390 | PRODUCT_NAME = "$(TARGET_NAME)";
391 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
392 | SWIFT_VERSION = 5.0;
393 | VERSIONING_SYSTEM = "apple-generic";
394 | };
395 | name = Profile;
396 | };
397 | 97C147031CF9000F007C117D /* Debug */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | ALWAYS_SEARCH_USER_PATHS = NO;
401 | CLANG_ANALYZER_NONNULL = YES;
402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
403 | CLANG_CXX_LIBRARY = "libc++";
404 | CLANG_ENABLE_MODULES = YES;
405 | CLANG_ENABLE_OBJC_ARC = YES;
406 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
407 | CLANG_WARN_BOOL_CONVERSION = YES;
408 | CLANG_WARN_COMMA = YES;
409 | CLANG_WARN_CONSTANT_CONVERSION = YES;
410 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
411 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
412 | CLANG_WARN_EMPTY_BODY = YES;
413 | CLANG_WARN_ENUM_CONVERSION = YES;
414 | CLANG_WARN_INFINITE_RECURSION = YES;
415 | CLANG_WARN_INT_CONVERSION = YES;
416 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
417 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
418 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
419 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
420 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
421 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
422 | CLANG_WARN_STRICT_PROTOTYPES = YES;
423 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
424 | CLANG_WARN_UNREACHABLE_CODE = YES;
425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
426 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
427 | COPY_PHASE_STRIP = NO;
428 | DEBUG_INFORMATION_FORMAT = dwarf;
429 | ENABLE_STRICT_OBJC_MSGSEND = YES;
430 | ENABLE_TESTABILITY = YES;
431 | GCC_C_LANGUAGE_STANDARD = gnu99;
432 | GCC_DYNAMIC_NO_PIC = NO;
433 | GCC_NO_COMMON_BLOCKS = YES;
434 | GCC_OPTIMIZATION_LEVEL = 0;
435 | GCC_PREPROCESSOR_DEFINITIONS = (
436 | "DEBUG=1",
437 | "$(inherited)",
438 | );
439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
441 | GCC_WARN_UNDECLARED_SELECTOR = YES;
442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
443 | GCC_WARN_UNUSED_FUNCTION = YES;
444 | GCC_WARN_UNUSED_VARIABLE = YES;
445 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
446 | MTL_ENABLE_DEBUG_INFO = YES;
447 | ONLY_ACTIVE_ARCH = YES;
448 | SDKROOT = iphoneos;
449 | TARGETED_DEVICE_FAMILY = "1,2";
450 | };
451 | name = Debug;
452 | };
453 | 97C147041CF9000F007C117D /* Release */ = {
454 | isa = XCBuildConfiguration;
455 | buildSettings = {
456 | ALWAYS_SEARCH_USER_PATHS = NO;
457 | CLANG_ANALYZER_NONNULL = YES;
458 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
459 | CLANG_CXX_LIBRARY = "libc++";
460 | CLANG_ENABLE_MODULES = YES;
461 | CLANG_ENABLE_OBJC_ARC = YES;
462 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
463 | CLANG_WARN_BOOL_CONVERSION = YES;
464 | CLANG_WARN_COMMA = YES;
465 | CLANG_WARN_CONSTANT_CONVERSION = YES;
466 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
467 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
468 | CLANG_WARN_EMPTY_BODY = YES;
469 | CLANG_WARN_ENUM_CONVERSION = YES;
470 | CLANG_WARN_INFINITE_RECURSION = YES;
471 | CLANG_WARN_INT_CONVERSION = YES;
472 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
473 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
474 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
475 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
476 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
477 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
478 | CLANG_WARN_STRICT_PROTOTYPES = YES;
479 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
480 | CLANG_WARN_UNREACHABLE_CODE = YES;
481 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
482 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
483 | COPY_PHASE_STRIP = NO;
484 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
485 | ENABLE_NS_ASSERTIONS = NO;
486 | ENABLE_STRICT_OBJC_MSGSEND = YES;
487 | GCC_C_LANGUAGE_STANDARD = gnu99;
488 | GCC_NO_COMMON_BLOCKS = YES;
489 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
490 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
491 | GCC_WARN_UNDECLARED_SELECTOR = YES;
492 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
493 | GCC_WARN_UNUSED_FUNCTION = YES;
494 | GCC_WARN_UNUSED_VARIABLE = YES;
495 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
496 | MTL_ENABLE_DEBUG_INFO = NO;
497 | SDKROOT = iphoneos;
498 | SUPPORTED_PLATFORMS = iphoneos;
499 | SWIFT_COMPILATION_MODE = wholemodule;
500 | SWIFT_OPTIMIZATION_LEVEL = "-O";
501 | TARGETED_DEVICE_FAMILY = "1,2";
502 | VALIDATE_PRODUCT = YES;
503 | };
504 | name = Release;
505 | };
506 | 97C147061CF9000F007C117D /* Debug */ = {
507 | isa = XCBuildConfiguration;
508 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
509 | buildSettings = {
510 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
511 | CLANG_ENABLE_MODULES = YES;
512 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
513 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
514 | DEVELOPMENT_TEAM = B64VL7ASS3;
515 | ENABLE_BITCODE = NO;
516 | FRAMEWORK_SEARCH_PATHS = (
517 | "$(inherited)",
518 | "$(PROJECT_DIR)/Flutter",
519 | );
520 | INFOPLIST_FILE = Runner/Info.plist;
521 | LD_RUNPATH_SEARCH_PATHS = (
522 | "$(inherited)",
523 | "@executable_path/Frameworks",
524 | );
525 | LIBRARY_SEARCH_PATHS = (
526 | "$(inherited)",
527 | "$(PROJECT_DIR)/Flutter",
528 | );
529 | PRODUCT_BUNDLE_IDENTIFIER = "com.tapmode.flutter-starter";
530 | PRODUCT_NAME = "$(TARGET_NAME)";
531 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
532 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
533 | SWIFT_VERSION = 5.0;
534 | VERSIONING_SYSTEM = "apple-generic";
535 | };
536 | name = Debug;
537 | };
538 | 97C147071CF9000F007C117D /* Release */ = {
539 | isa = XCBuildConfiguration;
540 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
541 | buildSettings = {
542 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
543 | CLANG_ENABLE_MODULES = YES;
544 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
545 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
546 | DEVELOPMENT_TEAM = B64VL7ASS3;
547 | ENABLE_BITCODE = NO;
548 | FRAMEWORK_SEARCH_PATHS = (
549 | "$(inherited)",
550 | "$(PROJECT_DIR)/Flutter",
551 | );
552 | INFOPLIST_FILE = Runner/Info.plist;
553 | LD_RUNPATH_SEARCH_PATHS = (
554 | "$(inherited)",
555 | "@executable_path/Frameworks",
556 | );
557 | LIBRARY_SEARCH_PATHS = (
558 | "$(inherited)",
559 | "$(PROJECT_DIR)/Flutter",
560 | );
561 | PRODUCT_BUNDLE_IDENTIFIER = "com.tapmode.flutter-starter";
562 | PRODUCT_NAME = "$(TARGET_NAME)";
563 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
564 | SWIFT_VERSION = 5.0;
565 | VERSIONING_SYSTEM = "apple-generic";
566 | };
567 | name = Release;
568 | };
569 | /* End XCBuildConfiguration section */
570 |
571 | /* Begin XCConfigurationList section */
572 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
573 | isa = XCConfigurationList;
574 | buildConfigurations = (
575 | 97C147031CF9000F007C117D /* Debug */,
576 | 97C147041CF9000F007C117D /* Release */,
577 | 249021D3217E4FDB00AE95B9 /* Profile */,
578 | );
579 | defaultConfigurationIsVisible = 0;
580 | defaultConfigurationName = Release;
581 | };
582 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
583 | isa = XCConfigurationList;
584 | buildConfigurations = (
585 | 97C147061CF9000F007C117D /* Debug */,
586 | 97C147071CF9000F007C117D /* Release */,
587 | 249021D4217E4FDB00AE95B9 /* Profile */,
588 | );
589 | defaultConfigurationIsVisible = 0;
590 | defaultConfigurationName = Release;
591 | };
592 | /* End XCConfigurationList section */
593 | };
594 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
595 | }
596 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/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/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CLIENT_ID
6 | 524197078337-96irqf3smo96s6f48mc1neh2vh7jber5.apps.googleusercontent.com
7 | REVERSED_CLIENT_ID
8 | com.googleusercontent.apps.524197078337-96irqf3smo96s6f48mc1neh2vh7jber5
9 | API_KEY
10 | AIzaSyAZaaG4pky5QFv-P_mXKhmn8O5ms2ifWXE
11 | GCM_SENDER_ID
12 | 524197078337
13 | PLIST_VERSION
14 | 1
15 | BUNDLE_ID
16 | com.tapmode.flutter-starter
17 | PROJECT_ID
18 | flutter-starter-delay
19 | STORAGE_BUCKET
20 | flutter-starter-delay.appspot.com
21 | IS_ADS_ENABLED
22 |
23 | IS_ANALYTICS_ENABLED
24 |
25 | IS_APPINVITE_ENABLED
26 |
27 | IS_GCM_ENABLED
28 |
29 | IS_SIGNIN_ENABLED
30 |
31 | GOOGLE_APP_ID
32 | 1:524197078337:ios:7373a07c0abd9619fa2dc0
33 | DATABASE_URL
34 | https://flutter-starter-delay.firebaseio.com
35 |
36 |
--------------------------------------------------------------------------------
/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 | flutter_starter
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLSchemes
27 |
28 | com.googleusercontent.apps.524197078337-96irqf3smo96s6f48mc1neh2vh7jber5
29 |
30 |
31 |
32 | CFBundleVersion
33 | $(FLUTTER_BUILD_NUMBER)
34 | LSRequiresIPhoneOS
35 |
36 | UILaunchStoryboardName
37 | LaunchScreen
38 | UIMainStoryboardFile
39 | Main
40 | UISupportedInterfaceOrientations
41 |
42 | UIInterfaceOrientationPortrait
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 | UISupportedInterfaceOrientations~ipad
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationPortraitUpsideDown
50 | UIInterfaceOrientationLandscapeLeft
51 | UIInterfaceOrientationLandscapeRight
52 |
53 | UIViewControllerBasedStatusBarAppearance
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.applesignin
6 |
7 | Default
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/lib/constants/app_routes.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 | import 'package:flutter_starter/ui/ui.dart';
3 | import 'package:flutter_starter/ui/auth/auth.dart';
4 |
5 | class AppRoutes {
6 | AppRoutes._(); //this is to prevent anyone from instantiating this object
7 | static final routes = [
8 | GetPage(name: '/', page: () => SplashUI()),
9 | GetPage(name: '/signin', page: () => SignInUI()),
10 | GetPage(name: '/signup', page: () => SignUpUI()),
11 | GetPage(name: '/home', page: () => HomeUI()),
12 | GetPage(name: '/settings', page: () => SettingsUI()),
13 | GetPage(name: '/reset-password', page: () => ResetPasswordUI()),
14 | GetPage(name: '/update-profile', page: () => UpdateProfileUI()),
15 | ];
16 | }
17 |
--------------------------------------------------------------------------------
/lib/constants/app_themes.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppThemes {
4 | AppThemes._();
5 |
6 | static const Color dodgerBlue = Color.fromRGBO(29, 161, 242, 1);
7 | static const Color whiteLilac = Color.fromRGBO(248, 250, 252, 1);
8 | static const Color blackPearl = Color.fromRGBO(30, 31, 43, 1);
9 | static const Color brinkPink = Color.fromRGBO(255, 97, 136, 1);
10 | static const Color juneBud = Color.fromRGBO(186, 215, 97, 1);
11 | static const Color white = Color.fromRGBO(255, 255, 255, 1);
12 | static const Color nevada = Color.fromRGBO(105, 109, 119, 1);
13 | static const Color ebonyClay = Color.fromRGBO(40, 42, 58, 1);
14 |
15 | static String font1 = "ProductSans";
16 | static String font2 = "Roboto";
17 | //constants color range for light theme
18 | //main color
19 | static const Color _lightPrimaryColor = dodgerBlue;
20 |
21 | //Background Colors
22 | static const Color _lightBackgroundColor = whiteLilac;
23 | static const Color _lightBackgroundAppBarColor = _lightPrimaryColor;
24 | static const Color _lightBackgroundSecondaryColor = white;
25 | static const Color _lightBackgroundAlertColor = blackPearl;
26 | static const Color _lightBackgroundActionTextColor = white;
27 | static const Color _lightBackgroundErrorColor = brinkPink;
28 | static const Color _lightBackgroundSuccessColor = juneBud;
29 |
30 | //Text Colors
31 | static const Color _lightTextColor = Colors.black;
32 | static const Color _lightAlertTextColor = Colors.black;
33 | static const Color _lightTextSecondaryColor = Colors.black;
34 |
35 | //Border Color
36 | static const Color _lightBorderColor = nevada;
37 |
38 | //Icon Color
39 | static const Color _lightIconColor = nevada;
40 |
41 | //form input colors
42 | static const Color _lightInputFillColor = _lightBackgroundSecondaryColor;
43 | static const Color _lightBorderActiveColor = _lightPrimaryColor;
44 | static const Color _lightBorderErrorColor = brinkPink;
45 |
46 | //constants color range for dark theme
47 | static const Color _darkPrimaryColor = dodgerBlue;
48 |
49 | //Background Colors
50 | static const Color _darkBackgroundColor = ebonyClay;
51 | static const Color _darkBackgroundAppBarColor = _darkPrimaryColor;
52 | static const Color _darkBackgroundSecondaryColor =
53 | Color.fromRGBO(0, 0, 0, .6);
54 | static const Color _darkBackgroundAlertColor = blackPearl;
55 | static const Color _darkBackgroundActionTextColor = white;
56 |
57 | static const Color _darkBackgroundErrorColor =
58 | Color.fromRGBO(255, 97, 136, 1);
59 | static const Color _darkBackgroundSuccessColor =
60 | Color.fromRGBO(186, 215, 97, 1);
61 |
62 | //Text Colors
63 | static const Color _darkTextColor = Colors.white;
64 | static const Color _darkAlertTextColor = Colors.black;
65 | static const Color _darkTextSecondaryColor = Colors.black;
66 |
67 | //Border Color
68 | static const Color _darkBorderColor = nevada;
69 |
70 | //Icon Color
71 | static const Color _darkIconColor = nevada;
72 |
73 | static const Color _darkInputFillColor = _darkBackgroundSecondaryColor;
74 | static const Color _darkBorderActiveColor = _darkPrimaryColor;
75 | static const Color _darkBorderErrorColor = brinkPink;
76 |
77 | //text theme for light theme
78 | static final TextTheme _lightTextTheme = TextTheme(
79 | headline1: TextStyle(fontSize: 20.0, color: _lightTextColor),
80 | bodyText1: TextStyle(fontSize: 16.0, color: _lightTextColor),
81 | bodyText2: TextStyle(fontSize: 14.0, color: Colors.grey),
82 | button: TextStyle(
83 | fontSize: 15.0, color: _lightTextColor, fontWeight: FontWeight.w600),
84 | headline6: TextStyle(fontSize: 16.0, color: _lightTextColor),
85 | subtitle1: TextStyle(fontSize: 16.0, color: _lightTextColor),
86 | caption: TextStyle(fontSize: 12.0, color: _lightBackgroundAppBarColor),
87 | );
88 |
89 | //the light theme
90 | static final ThemeData lightTheme = ThemeData(
91 | brightness: Brightness.light,
92 | fontFamily: font1,
93 | scaffoldBackgroundColor: _lightBackgroundColor,
94 | floatingActionButtonTheme: FloatingActionButtonThemeData(
95 | backgroundColor: _lightPrimaryColor,
96 | ),
97 | appBarTheme: AppBarTheme(
98 | color: _lightBackgroundAppBarColor,
99 | iconTheme: IconThemeData(color: _lightTextColor),
100 | textTheme: _lightTextTheme,
101 | ),
102 | colorScheme: ColorScheme.light(
103 | primary: _lightPrimaryColor,
104 | primaryVariant: _lightBackgroundColor,
105 | // secondary: _lightSecondaryColor,
106 | ),
107 | snackBarTheme: SnackBarThemeData(
108 | backgroundColor: _lightBackgroundAlertColor,
109 | actionTextColor: _lightBackgroundActionTextColor),
110 | iconTheme: IconThemeData(
111 | color: _lightIconColor,
112 | ),
113 | popupMenuTheme: PopupMenuThemeData(color: _lightBackgroundAppBarColor),
114 | textTheme: _lightTextTheme,
115 | buttonTheme: ButtonThemeData(
116 | shape: RoundedRectangleBorder(
117 | borderRadius: BorderRadius.circular(8),
118 | ),
119 | buttonColor: _lightPrimaryColor,
120 | textTheme: ButtonTextTheme.primary),
121 | unselectedWidgetColor: _lightPrimaryColor,
122 | inputDecorationTheme: InputDecorationTheme(
123 | //prefixStyle: TextStyle(color: _lightIconColor),
124 | border: OutlineInputBorder(
125 | borderSide: BorderSide(width: 1.0),
126 | borderRadius: BorderRadius.all(
127 | Radius.circular(8.0),
128 | )),
129 | enabledBorder: OutlineInputBorder(
130 | borderSide: BorderSide(color: _lightBorderColor, width: 1.0),
131 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
132 | ),
133 | focusedBorder: OutlineInputBorder(
134 | borderSide: BorderSide(color: _lightBorderActiveColor),
135 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
136 | ),
137 | errorBorder: OutlineInputBorder(
138 | borderSide: BorderSide(color: _lightBorderErrorColor),
139 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
140 | ),
141 | focusedErrorBorder: OutlineInputBorder(
142 | borderSide: BorderSide(color: _lightBorderErrorColor),
143 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
144 | ),
145 | fillColor: _lightBackgroundSecondaryColor,
146 | //focusColor: _lightBorderActiveColor,
147 | ),
148 | );
149 |
150 | //text theme for dark theme
151 | /*static final TextStyle _darkScreenHeadingTextStyle =
152 | _lightScreenHeadingTextStyle.copyWith(color: _darkTextColor);
153 | static final TextStyle _darkScreenTaskNameTextStyle =
154 | _lightScreenTaskNameTextStyle.copyWith(color: _darkTextColor);
155 | static final TextStyle _darkScreenTaskDurationTextStyle =
156 | _lightScreenTaskDurationTextStyle;
157 | static final TextStyle _darkScreenButtonTextStyle = TextStyle(
158 | fontSize: 14.0, color: _darkTextColor, fontWeight: FontWeight.w500);
159 | static final TextStyle _darkScreenCaptionTextStyle = TextStyle(
160 | fontSize: 12.0,
161 | color: _darkBackgroundAppBarColor,
162 | fontWeight: FontWeight.w100);*/
163 |
164 | static final TextTheme _darkTextTheme = TextTheme(
165 | headline1: TextStyle(fontSize: 20.0, color: _darkTextColor),
166 | bodyText1: TextStyle(fontSize: 16.0, color: _darkTextColor),
167 | bodyText2: TextStyle(fontSize: 14.0, color: Colors.grey),
168 | button: TextStyle(
169 | fontSize: 15.0, color: _darkTextColor, fontWeight: FontWeight.w600),
170 | headline6: TextStyle(fontSize: 16.0, color: _darkTextColor),
171 | subtitle1: TextStyle(fontSize: 16.0, color: _darkTextColor),
172 | caption: TextStyle(fontSize: 12.0, color: _darkBackgroundAppBarColor),
173 | );
174 |
175 | //the dark theme
176 | static final ThemeData darkTheme = ThemeData(
177 | brightness: Brightness.dark,
178 | //primarySwatch: _darkPrimaryColor, //cant be Color on MaterialColor so it can compute different shades.
179 | accentColor: _darkPrimaryColor, //prefix icon color form input on focus
180 |
181 | fontFamily: font1,
182 | scaffoldBackgroundColor: _darkBackgroundColor,
183 | floatingActionButtonTheme: FloatingActionButtonThemeData(
184 | backgroundColor: _darkPrimaryColor,
185 | ),
186 | appBarTheme: AppBarTheme(
187 | color: _darkBackgroundAppBarColor,
188 | iconTheme: IconThemeData(color: _darkTextColor),
189 | textTheme: _darkTextTheme,
190 | ),
191 | colorScheme: ColorScheme.dark(
192 | primary: _darkPrimaryColor,
193 | primaryVariant: _darkBackgroundColor,
194 |
195 | // secondary: _darkSecondaryColor,
196 | ),
197 | snackBarTheme: SnackBarThemeData(
198 | contentTextStyle: TextStyle(color: Colors.white),
199 | backgroundColor: _darkBackgroundAlertColor,
200 | actionTextColor: _darkBackgroundActionTextColor),
201 | iconTheme: IconThemeData(
202 | color: _darkIconColor, //_darkIconColor,
203 | ),
204 | popupMenuTheme: PopupMenuThemeData(color: _darkBackgroundAppBarColor),
205 | textTheme: _darkTextTheme,
206 | buttonTheme: ButtonThemeData(
207 | shape: RoundedRectangleBorder(
208 | borderRadius: BorderRadius.circular(8),
209 | ),
210 | buttonColor: _darkPrimaryColor,
211 | textTheme: ButtonTextTheme.primary),
212 | unselectedWidgetColor: _darkPrimaryColor,
213 | inputDecorationTheme: InputDecorationTheme(
214 | prefixStyle: TextStyle(color: _darkIconColor),
215 | //labelStyle: TextStyle(color: nevada),
216 | border: OutlineInputBorder(
217 | borderSide: BorderSide(width: 1.0),
218 | borderRadius: BorderRadius.all(
219 | Radius.circular(8.0),
220 | )),
221 | enabledBorder: OutlineInputBorder(
222 | borderSide: BorderSide(color: _darkBorderColor, width: 1.0),
223 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
224 | ),
225 | focusedBorder: OutlineInputBorder(
226 | borderSide: BorderSide(color: _darkBorderActiveColor),
227 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
228 | ),
229 | errorBorder: OutlineInputBorder(
230 | borderSide: BorderSide(color: _darkBorderErrorColor),
231 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
232 | ),
233 | focusedErrorBorder: OutlineInputBorder(
234 | borderSide: BorderSide(color: _darkBorderErrorColor),
235 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
236 | ),
237 | fillColor: _darkInputFillColor,
238 | //focusColor: _darkBorderActiveColor,
239 | ),
240 | );
241 | }
242 |
--------------------------------------------------------------------------------
/lib/constants/constants.dart:
--------------------------------------------------------------------------------
1 | export 'app_routes.dart';
2 | export 'globals.dart';
3 | export 'app_themes.dart';
4 |
--------------------------------------------------------------------------------
/lib/constants/globals.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_starter/models/models.dart';
2 |
3 | class Globals {
4 | static final String defaultLanguage = 'en';
5 | //List of languages that are supported. Used in selector.
6 | //Follow this plugin for translating a google sheet to languages
7 | //https://github.com/aloisdeniel/flutter_sheet_localization
8 | //Flutter App translations google sheet
9 | //https://docs.google.com/spreadsheets/d/1oS7iJ6ocrZBA53SxRfKF0CG9HAaXeKtzvsTBhgG4Zzk/edit?usp=sharing
10 |
11 | static final List languageOptions = [
12 | MenuOptionsModel(key: "zh", value: "中文"), //Chinese
13 | MenuOptionsModel(key: "de", value: "Deutsche"), //German
14 | MenuOptionsModel(key: "en", value: "English"), //English
15 | MenuOptionsModel(key: "es", value: "Español"), //Spanish
16 | MenuOptionsModel(key: "fr", value: "Français"), //French
17 | MenuOptionsModel(key: "hi", value: "हिन्दी"), //Hindi
18 | MenuOptionsModel(key: "ja", value: "日本語"), //Japanese
19 | MenuOptionsModel(key: "pt", value: "Português"), //Portuguese
20 | MenuOptionsModel(key: "ru", value: "русский"), //Russian
21 | ];
22 | }
23 |
--------------------------------------------------------------------------------
/lib/controllers/auth_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'dart:async';
4 | import 'package:firebase_auth/firebase_auth.dart';
5 | import 'package:get/get.dart';
6 | import 'package:cloud_firestore/cloud_firestore.dart';
7 | import 'package:flutter_starter/models/models.dart';
8 | import 'package:flutter_starter/ui/auth/auth.dart';
9 | import 'package:flutter_starter/ui/ui.dart';
10 | import 'package:flutter_starter/ui/components/components.dart';
11 | import 'package:flutter_starter/helpers/helpers.dart';
12 |
13 | class AuthController extends GetxController {
14 | static AuthController to = Get.find();
15 | TextEditingController nameController = TextEditingController();
16 | TextEditingController emailController = TextEditingController();
17 | TextEditingController passwordController = TextEditingController();
18 | final FirebaseAuth _auth = FirebaseAuth.instance;
19 | final FirebaseFirestore _db = FirebaseFirestore.instance;
20 | Rxn firebaseUser = Rxn();
21 | Rxn firestoreUser = Rxn();
22 | final RxBool admin = false.obs;
23 |
24 | @override
25 | void onReady() async {
26 | //run every time auth state changes
27 | ever(firebaseUser, handleAuthChanged);
28 |
29 | firebaseUser.bindStream(user);
30 |
31 | super.onReady();
32 | }
33 |
34 | @override
35 | void onClose() {
36 | nameController.dispose();
37 | emailController.dispose();
38 | passwordController.dispose();
39 | super.onClose();
40 | }
41 |
42 | handleAuthChanged(_firebaseUser) async {
43 | //get user data from firestore
44 | if (_firebaseUser?.uid != null) {
45 | firestoreUser.bindStream(streamFirestoreUser());
46 | await isAdmin();
47 | }
48 |
49 | if (_firebaseUser == null) {
50 | print('Send to signin');
51 | Get.offAll(SignInUI());
52 | } else {
53 | Get.offAll(HomeUI());
54 | }
55 | }
56 |
57 | // Firebase user one-time fetch
58 | Future get getUser async => _auth.currentUser!;
59 |
60 | // Firebase user a realtime stream
61 | Stream get user => _auth.authStateChanges();
62 |
63 | //Streams the firestore user from the firestore collection
64 | Stream streamFirestoreUser() {
65 | print('streamFirestoreUser()');
66 |
67 | return _db
68 | .doc('/users/${firebaseUser.value!.uid}')
69 | .snapshots()
70 | .map((snapshot) => UserModel.fromMap(snapshot.data()!));
71 | }
72 |
73 | //get the firestore user from the firestore collection
74 | Future getFirestoreUser() {
75 | return _db.doc('/users/${firebaseUser.value!.uid}').get().then(
76 | (documentSnapshot) => UserModel.fromMap(documentSnapshot.data()!));
77 | }
78 |
79 | //Method to handle user sign in using email and password
80 | signInWithEmailAndPassword(BuildContext context) async {
81 | showLoadingIndicator();
82 | try {
83 | await _auth.signInWithEmailAndPassword(
84 | email: emailController.text.trim(),
85 | password: passwordController.text.trim());
86 | emailController.clear();
87 | passwordController.clear();
88 | hideLoadingIndicator();
89 | } catch (error) {
90 | hideLoadingIndicator();
91 | Get.snackbar('auth.signInErrorTitle'.tr, 'auth.signInError'.tr,
92 | snackPosition: SnackPosition.BOTTOM,
93 | duration: Duration(seconds: 7),
94 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
95 | colorText: Get.theme.snackBarTheme.actionTextColor);
96 | }
97 | }
98 |
99 | // User registration using email and password
100 | registerWithEmailAndPassword(BuildContext context) async {
101 | showLoadingIndicator();
102 | try {
103 | await _auth
104 | .createUserWithEmailAndPassword(
105 | email: emailController.text, password: passwordController.text)
106 | .then((result) async {
107 | print('uID: ' + result.user!.uid.toString());
108 | print('email: ' + result.user!.email.toString());
109 | //get photo url from gravatar if user has one
110 | Gravatar gravatar = Gravatar(emailController.text);
111 | String gravatarUrl = gravatar.imageUrl(
112 | size: 200,
113 | defaultImage: GravatarImage.retro,
114 | rating: GravatarRating.pg,
115 | fileExtension: true,
116 | );
117 | //create the new user object
118 | UserModel _newUser = UserModel(
119 | uid: result.user!.uid,
120 | email: result.user!.email!,
121 | name: nameController.text,
122 | photoUrl: gravatarUrl);
123 | //create the user in firestore
124 | _createUserFirestore(_newUser, result.user!);
125 | emailController.clear();
126 | passwordController.clear();
127 | hideLoadingIndicator();
128 | });
129 | } on FirebaseAuthException catch (error) {
130 | hideLoadingIndicator();
131 | Get.snackbar('auth.signUpErrorTitle'.tr, error.message!,
132 | snackPosition: SnackPosition.BOTTOM,
133 | duration: Duration(seconds: 10),
134 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
135 | colorText: Get.theme.snackBarTheme.actionTextColor);
136 | }
137 | }
138 |
139 | //handles updating the user when updating profile
140 | Future updateUser(BuildContext context, UserModel user, String oldEmail,
141 | String password) async {
142 | String _authUpdateUserNoticeTitle = 'auth.updateUserSuccessNoticeTitle'.tr;
143 | String _authUpdateUserNotice = 'auth.updateUserSuccessNotice'.tr;
144 | try {
145 | showLoadingIndicator();
146 | try {
147 | await _auth
148 | .signInWithEmailAndPassword(email: oldEmail, password: password)
149 | .then((_firebaseUser) async {
150 | await _firebaseUser.user!
151 | .updateEmail(user.email)
152 | .then((value) => _updateUserFirestore(user, _firebaseUser.user!));
153 | });
154 | } catch (err) {
155 | print('Caught error: $err');
156 | //not yet working, see this issue https://github.com/delay/flutter_starter/issues/21
157 | if (err.toString() ==
158 | "[firebase_auth/email-already-in-use] The email address is already in use by another account.") {
159 | _authUpdateUserNoticeTitle = 'auth.updateUserEmailInUse'.tr;
160 | _authUpdateUserNotice = 'auth.updateUserEmailInUse'.tr;
161 | } else {
162 | _authUpdateUserNoticeTitle = 'auth.wrongPasswordNotice'.tr;
163 | _authUpdateUserNotice = 'auth.wrongPasswordNotice'.tr;
164 | }
165 | }
166 | hideLoadingIndicator();
167 | Get.snackbar(_authUpdateUserNoticeTitle, _authUpdateUserNotice,
168 | snackPosition: SnackPosition.BOTTOM,
169 | duration: Duration(seconds: 5),
170 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
171 | colorText: Get.theme.snackBarTheme.actionTextColor);
172 | } on PlatformException catch (error) {
173 | //List errors = error.toString().split(',');
174 | // print("Error: " + errors[1]);
175 | hideLoadingIndicator();
176 | print(error.code);
177 | String authError;
178 | switch (error.code) {
179 | case 'ERROR_WRONG_PASSWORD':
180 | authError = 'auth.wrongPasswordNotice'.tr;
181 | break;
182 | default:
183 | authError = 'auth.unknownError'.tr;
184 | break;
185 | }
186 | Get.snackbar('auth.wrongPasswordNoticeTitle'.tr, authError,
187 | snackPosition: SnackPosition.BOTTOM,
188 | duration: Duration(seconds: 10),
189 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
190 | colorText: Get.theme.snackBarTheme.actionTextColor);
191 | }
192 | }
193 |
194 | //updates the firestore user in users collection
195 | void _updateUserFirestore(UserModel user, User _firebaseUser) {
196 | _db.doc('/users/${_firebaseUser.uid}').update(user.toJson());
197 | update();
198 | }
199 |
200 | //create the firestore user in users collection
201 | void _createUserFirestore(UserModel user, User _firebaseUser) {
202 | _db.doc('/users/${_firebaseUser.uid}').set(user.toJson());
203 | update();
204 | }
205 |
206 | //password reset email
207 | Future sendPasswordResetEmail(BuildContext context) async {
208 | showLoadingIndicator();
209 | try {
210 | await _auth.sendPasswordResetEmail(email: emailController.text);
211 | hideLoadingIndicator();
212 | Get.snackbar(
213 | 'auth.resetPasswordNoticeTitle'.tr, 'auth.resetPasswordNotice'.tr,
214 | snackPosition: SnackPosition.BOTTOM,
215 | duration: Duration(seconds: 5),
216 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
217 | colorText: Get.theme.snackBarTheme.actionTextColor);
218 | } on FirebaseAuthException catch (error) {
219 | hideLoadingIndicator();
220 | Get.snackbar('auth.resetPasswordFailed'.tr, error.message!,
221 | snackPosition: SnackPosition.BOTTOM,
222 | duration: Duration(seconds: 10),
223 | backgroundColor: Get.theme.snackBarTheme.backgroundColor,
224 | colorText: Get.theme.snackBarTheme.actionTextColor);
225 | }
226 | }
227 |
228 | //check if user is an admin user
229 | isAdmin() async {
230 | await getUser.then((user) async {
231 | DocumentSnapshot adminRef =
232 | await _db.collection('admin').doc(user.uid).get();
233 | if (adminRef.exists) {
234 | admin.value = true;
235 | } else {
236 | admin.value = false;
237 | }
238 | update();
239 | });
240 | }
241 |
242 | // Sign out
243 | Future signOut() {
244 | nameController.clear();
245 | emailController.clear();
246 | passwordController.clear();
247 | return _auth.signOut();
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/lib/controllers/controllers.dart:
--------------------------------------------------------------------------------
1 | export 'theme_controller.dart';
2 | export 'language_controller.dart';
3 | export 'auth_controller.dart';
4 |
--------------------------------------------------------------------------------
/lib/controllers/language_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_starter/constants/globals.dart';
3 | import 'package:get/get.dart';
4 | import 'package:get_storage/get_storage.dart';
5 | import 'dart:ui' as ui;
6 |
7 | class LanguageController extends GetxController {
8 | static LanguageController get to => Get.find();
9 | final language = "".obs;
10 | final store = GetStorage();
11 |
12 | String get currentLanguage => language.value;
13 |
14 | @override
15 | void onReady() async {
16 | //setInitialLocalLanguage();
17 | super.onInit();
18 | }
19 |
20 | // Retrieves and Sets language based on device settings
21 | setInitialLocalLanguage() {
22 | if (currentLanguageStore.value == '') {
23 | String _deviceLanguage = ui.window.locale.toString();
24 | _deviceLanguage =
25 | _deviceLanguage.substring(0, 2); //only get 1st 2 characters
26 | print(ui.window.locale.toString());
27 | updateLanguage(_deviceLanguage);
28 | }
29 | }
30 |
31 | // Gets current language stored
32 | RxString get currentLanguageStore {
33 | language.value = store.read('language') ?? '';
34 | return language;
35 | }
36 |
37 | // gets the language locale app is set to
38 | Locale? get getLocale {
39 | if (currentLanguageStore.value == '') {
40 | language.value = Globals.defaultLanguage;
41 | updateLanguage(Globals.defaultLanguage);
42 | } else if (currentLanguageStore.value != '') {
43 | //set the stored string country code to the locale
44 | return Locale(currentLanguageStore.value);
45 | }
46 | // gets the default language key for the system.
47 | return Get.deviceLocale;
48 | }
49 |
50 | // updates the language stored
51 | Future updateLanguage(String value) async {
52 | language.value = value;
53 | await store.write('language', value);
54 | if (getLocale != null) {
55 | Get.updateLocale(getLocale!);
56 | }
57 | update();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/controllers/theme_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get.dart';
3 | import 'package:get_storage/get_storage.dart';
4 |
5 | // https://gist.github.com/RodBr/37310335c6639f486bb3c8a628052405
6 | //https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3
7 |
8 | class ThemeController extends GetxController {
9 | static ThemeController get to => Get.find();
10 | final theme = "system".obs;
11 | final store = GetStorage();
12 | late ThemeMode _themeMode;
13 |
14 | ThemeMode get themeMode => _themeMode;
15 | String get currentTheme => theme.value;
16 |
17 | Future setThemeMode(String value) async {
18 | theme.value = value;
19 | _themeMode = getThemeModeFromString(value);
20 | Get.changeThemeMode(_themeMode);
21 | await store.write('theme', value);
22 | update();
23 | }
24 |
25 | ThemeMode getThemeModeFromString(String themeString) {
26 | ThemeMode _setThemeMode = ThemeMode.system;
27 | if (themeString == 'light') {
28 | _setThemeMode = ThemeMode.light;
29 | }
30 | if (themeString == 'dark') {
31 | _setThemeMode = ThemeMode.dark;
32 | }
33 | return _setThemeMode;
34 | }
35 |
36 | getThemeModeFromStore() async {
37 | String _themeString = store.read('theme') ?? 'system';
38 | setThemeMode(_themeString);
39 | }
40 |
41 | // checks whether darkmode is set via system or previously by user
42 | bool get isDarkModeOn {
43 | if (currentTheme == 'system') {
44 | if (WidgetsBinding.instance!.window.platformBrightness ==
45 | Brightness.dark) {
46 | return true;
47 | }
48 | }
49 | if (currentTheme == 'dark') {
50 | return true;
51 | }
52 | return false;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/helpers/gravatar.dart:
--------------------------------------------------------------------------------
1 | //code from uses wrong version of crypto
2 | //to use default package https://github.com/subosito/simple_gravatar/blob/master/lib/simple_gravatar.dart
3 |
4 | import 'dart:convert';
5 | import 'package:crypto/crypto.dart';
6 |
7 | enum GravatarImage {
8 | nf, // 404
9 | mp, // mystery person
10 | identicon,
11 | monsterid,
12 | wavatar,
13 | retro,
14 | robohash,
15 | blank,
16 | }
17 |
18 | enum GravatarRating {
19 | g,
20 | pg,
21 | r,
22 | x,
23 | }
24 |
25 | class Gravatar {
26 | final String email;
27 | final String hash;
28 |
29 | Gravatar(this.email) : this.hash = _generateHash(email);
30 |
31 | static String _generateHash(String email) {
32 | String preparedEmail = email.trim().toLowerCase();
33 | return md5.convert(utf8.encode(preparedEmail)).toString();
34 | }
35 |
36 | String imageUrl({
37 | int? size,
38 | GravatarImage? defaultImage,
39 | bool forceDefault = false,
40 | bool fileExtension = false,
41 | GravatarRating? rating,
42 | }) {
43 | String hashDigest = hash;
44 | Map query = {};
45 |
46 | if (size != null) query['s'] = size.toString();
47 | if (defaultImage != null) query['d'] = _imageString(defaultImage);
48 | if (forceDefault) query['f'] = 'y';
49 | if (rating != null) query['r'] = _ratingString(rating);
50 | if (fileExtension) hashDigest += '.png';
51 | //if (query.isEmpty) query = null;
52 |
53 | return Uri.https('www.gravatar.com', '/avatar/$hashDigest', query)
54 | .toString();
55 | }
56 |
57 | String jsonUrl() {
58 | return Uri.https('www.gravatar.com', '/$hash.json').toString();
59 | }
60 |
61 | String qrUrl() {
62 | return Uri.https('www.gravatar.com', '/$hash.qr').toString();
63 | }
64 |
65 | String toString() {
66 | return imageUrl();
67 | }
68 |
69 | String _imageString(GravatarImage value) {
70 | switch (value) {
71 | case GravatarImage.nf:
72 | return '404';
73 | case GravatarImage.mp:
74 | return 'mp';
75 | case GravatarImage.identicon:
76 | return 'identicon';
77 | case GravatarImage.monsterid:
78 | return 'monsterid';
79 | case GravatarImage.wavatar:
80 | return 'wavatar';
81 | case GravatarImage.retro:
82 | return 'retro';
83 | case GravatarImage.robohash:
84 | return 'robohash';
85 | case GravatarImage.blank:
86 | return 'blank';
87 | }
88 | }
89 |
90 | String _ratingString(GravatarRating value) {
91 | switch (value) {
92 | case GravatarRating.g:
93 | return 'g';
94 | case GravatarRating.pg:
95 | return 'pg';
96 | case GravatarRating.r:
97 | return 'r';
98 | case GravatarRating.x:
99 | return 'x';
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/lib/helpers/helpers.dart:
--------------------------------------------------------------------------------
1 | export 'validator.dart';
2 | export 'gravatar.dart';
3 | export 'localization.g.dart';
4 |
--------------------------------------------------------------------------------
/lib/helpers/localization.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | class Localization extends Translations {
4 | @override
5 | Map> get keys => {
6 | 'en': {
7 | 'auth.signInButton': 'Sign In',
8 | 'auth.signUpButton': 'Sign Up',
9 | 'auth.resetPasswordButton': 'Send Password Reset',
10 | 'auth.emailFormField': 'Email',
11 | 'auth.passwordFormField': 'Password',
12 | 'auth.nameFormField': 'Name',
13 | 'auth.signInErrorTitle': 'Sign In Error',
14 | 'auth.signInError': 'Login failed: email or password incorrect.',
15 | 'auth.resetPasswordLabelButton': 'Forgot password?',
16 | 'auth.signUpLabelButton': 'Create an Account',
17 | 'auth.signUpErrorTitle': 'Sign Up Failed.',
18 | 'auth.signUpError': 'There was a problem signing up. Please try again later.',
19 | 'auth.signInLabelButton': 'Have an Account? Sign In.',
20 | 'auth.resetPasswordNoticeTitle': 'Password Reset Email Sent',
21 | 'auth.resetPasswordNotice': 'Check your email and follow the instructions to reset your password.',
22 | 'auth.resetPasswordFailed': 'Password Reset Email Failed',
23 | 'auth.signInonResetPasswordLabelButton': 'Sign In',
24 | 'auth.updateUser': 'Update Profile',
25 | 'auth.updateUserSuccessNoticeTitle': 'User Updated',
26 | 'auth.updateUserSuccessNotice': 'User information successfully updated.',
27 | 'auth.updateUserEmailInUse': 'That email address already has an account.',
28 | 'auth.updateUserFailNotice': 'Failed to update user',
29 | 'auth.enterPassword': 'Enter your password',
30 | 'auth.cancel': 'Cancel',
31 | 'auth.submit': 'Submit',
32 | 'auth.changePasswordLabelButton': 'Change Password',
33 | 'auth.resetPasswordTitle': 'Reset Password',
34 | 'auth.updateProfileTitle': 'Update Profile',
35 | 'auth.wrongPasswordNoticeTitle': 'Login Failed',
36 | 'auth.wrongPasswordNotice': 'The password does not match our records.',
37 | 'auth.unknownError': 'Unknown Error',
38 | 'settings.title': 'Settings',
39 | 'settings.language': 'Language',
40 | 'settings.theme': 'Theme',
41 | 'settings.signOut': 'Sign Out',
42 | 'settings.dark': 'Dark',
43 | 'settings.light': 'Light',
44 | 'settings.system': 'System',
45 | 'settings.updateProfile': 'Update Profile',
46 | 'home.title': 'Home',
47 | 'home.nameLabel': 'Name',
48 | 'home.uidLabel': 'UID',
49 | 'home.emailLabel': 'Email',
50 | 'home.adminUserLabel': 'Admin User',
51 | 'app.title': 'Flutter Starter Project',
52 | 'validator.email': 'Please enter a valid email address.',
53 | 'validator.password': 'Password must be at least 6 characters.',
54 | 'validator.name': 'Please enter a name.',
55 | 'validator.number': 'Please enter a number.',
56 | 'validator.notEmpty': 'This is a required field.',
57 | 'validator.amount': 'Please enter a number i.e. 250 - no dollar symbol and no cents',
58 | },
59 | 'fr': {
60 | 'auth.signInButton': 'S\'identifier',
61 | 'auth.signUpButton': 'S\'inscrire',
62 | 'auth.resetPasswordButton': 'Envoyer Password Reset',
63 | 'auth.emailFormField': 'E-mail',
64 | 'auth.passwordFormField': 'Mot de passe',
65 | 'auth.nameFormField': 'Nom',
66 | 'auth.signInErrorTitle': 'Erreur de connexion',
67 | 'auth.signInError': 'Échec de la connexion: e-mail ou mot de passe incorrect.',
68 | 'auth.resetPasswordLabelButton': 'Mot de passe oublié?',
69 | 'auth.signUpLabelButton': 'Créer un compte',
70 | 'auth.signUpErrorTitle': 'Échec de l\'inscription.',
71 | 'auth.signUpError': 'Il y avait un problème de signer. Veuillez réessayer plus tard.',
72 | 'auth.signInLabelButton': 'Avoir un compte? S\'identifier.',
73 | 'auth.resetPasswordNoticeTitle': 'Réinitialiser le mot de passe e-mail envoyé',
74 | 'auth.resetPasswordNotice': 'Vérifiez votre e-mail et suivez les instructions pour réinitialiser votre mot de passe.',
75 | 'auth.resetPasswordFailed': 'Réinitialiser le mot de passe Email Échec',
76 | 'auth.signInonResetPasswordLabelButton': 'S\'identifier',
77 | 'auth.updateUser': 'Mettre à jour le profil',
78 | 'auth.updateUserSuccessNoticeTitle': 'Mise à jour l\'utilisateur',
79 | 'auth.updateUserSuccessNotice': 'Informations sur l\'utilisateur mis à jour avec succès.',
80 | 'auth.updateUserEmailInUse': 'Cette adresse e-mail a déjà un compte.',
81 | 'auth.updateUserFailNotice': 'Impossible de mettre à jour l\'utilisateur',
82 | 'auth.enterPassword': 'Tapez votre mot de passe',
83 | 'auth.cancel': 'Annuler',
84 | 'auth.submit': 'Soumettre',
85 | 'auth.changePasswordLabelButton': 'Changer le mot de passe',
86 | 'auth.resetPasswordTitle': 'réinitialiser le mot de passe',
87 | 'auth.updateProfileTitle': 'Mettre à jour le profil',
88 | 'auth.wrongPasswordNoticeTitle': 'Échec de la connexion',
89 | 'auth.wrongPasswordNotice': 'Le mot de passe ne correspond pas à nos dossiers.',
90 | 'auth.unknownError': 'Erreur inconnue',
91 | 'settings.title': 'Paramètres',
92 | 'settings.language': 'Langue',
93 | 'settings.theme': 'Thème',
94 | 'settings.signOut': 'Se déconnecter',
95 | 'settings.dark': 'Sombre',
96 | 'settings.light': 'Lumière',
97 | 'settings.system': 'Système',
98 | 'settings.updateProfile': 'Mettre à jour le profil',
99 | 'home.title': 'Domicile',
100 | 'home.nameLabel': 'Nom',
101 | 'home.uidLabel': 'UID',
102 | 'home.emailLabel': 'E-mail',
103 | 'home.adminUserLabel': 'utilisateur admin',
104 | 'app.title': 'Flutter projet de démarrage',
105 | 'validator.email': 'S\'il vous plaît, mettez une adresse email valide.',
106 | 'validator.password': 'Le mot de passe doit être au moins de 6 caractères.',
107 | 'validator.name': 'S\'il vous plaît entrer un nom.',
108 | 'validator.number': 'S\'il vous plaît entrer un numéro.',
109 | 'validator.notEmpty': 'Ceci est un champ obligatoire.',
110 | 'validator.amount': 'S\'il vous plaît entrer un numéro à savoir 250 - aucun symbole du dollar et pas cents',
111 | },
112 | 'es': {
113 | 'auth.signInButton': 'Iniciar sesión',
114 | 'auth.signUpButton': 'Inscribirse',
115 | 'auth.resetPasswordButton': 'Enviar restablecimiento de contraseña',
116 | 'auth.emailFormField': 'Correo electrónico',
117 | 'auth.passwordFormField': 'Contraseña',
118 | 'auth.nameFormField': 'Nombre',
119 | 'auth.signInErrorTitle': 'Error al iniciar sesión',
120 | 'auth.signInError': 'La conexión falló: correo electrónico o contraseña incorrecta.',
121 | 'auth.resetPasswordLabelButton': '¿Se te olvidó tu contraseña?',
122 | 'auth.signUpLabelButton': 'Crea una cuenta',
123 | 'auth.signUpErrorTitle': 'Registro fallido.',
124 | 'auth.signUpError': 'Hubo un problema al inscribirse. Por favor, inténtelo de nuevo más tarde.',
125 | 'auth.signInLabelButton': '¿Tener una cuenta? Iniciar sesión.',
126 | 'auth.resetPasswordNoticeTitle': 'Restablecer contraseña de correo electrónico enviados',
127 | 'auth.resetPasswordNotice': 'Consultar su correo electrónico y siga las instrucciones para restablecer su contraseña.',
128 | 'auth.resetPasswordFailed': 'Restablecer contraseña de correo electrónico incorrecto',
129 | 'auth.signInonResetPasswordLabelButton': 'Iniciar sesión',
130 | 'auth.updateUser': 'Actualización del perfil',
131 | 'auth.updateUserSuccessNoticeTitle': 'Actualización de usuario',
132 | 'auth.updateUserSuccessNotice': 'La información de usuario actualizada correctamente.',
133 | 'auth.updateUserEmailInUse': 'Esa dirección de correo electrónico ya tiene una cuenta.',
134 | 'auth.updateUserFailNotice': 'Error al usuario la actualización',
135 | 'auth.enterPassword': 'Ingresa tu contraseña',
136 | 'auth.cancel': 'Cancelar',
137 | 'auth.submit': 'Enviar',
138 | 'auth.changePasswordLabelButton': 'Cambiar la contraseña',
139 | 'auth.resetPasswordTitle': 'Restablecer la contraseña',
140 | 'auth.updateProfileTitle': 'Actualización del perfil',
141 | 'auth.wrongPasswordNoticeTitle': 'Error de inicio de sesion',
142 | 'auth.wrongPasswordNotice': 'La contraseña no coincide con nuestros registros.',
143 | 'auth.unknownError': 'Error desconocido',
144 | 'settings.title': 'Ajustes',
145 | 'settings.language': 'Idioma',
146 | 'settings.theme': 'Tema',
147 | 'settings.signOut': 'Desconectar',
148 | 'settings.dark': 'Oscuro',
149 | 'settings.light': 'Luz',
150 | 'settings.system': 'Sistema',
151 | 'settings.updateProfile': 'Actualización del perfil',
152 | 'home.title': 'Casa',
153 | 'home.nameLabel': 'Nombre',
154 | 'home.uidLabel': 'UID',
155 | 'home.emailLabel': 'Correo electrónico',
156 | 'home.adminUserLabel': 'admin User',
157 | 'app.title': 'Proyecto de arranque aleteo',
158 | 'validator.email': 'Por favor, introduce una dirección de correo electrónico válida.',
159 | 'validator.password': 'La contraseña debe tener al menos 6 caracteres.',
160 | 'validator.name': 'Por favor, introduzca un nombre.',
161 | 'validator.number': 'Por favor, introduzca un número.',
162 | 'validator.notEmpty': 'Este es un campo obligatorio.',
163 | 'validator.amount': 'Por favor, introduzca un número, es decir 250 - ningún símbolo del dólar y sin centavos',
164 | },
165 | 'de': {
166 | 'auth.signInButton': 'Einloggen',
167 | 'auth.signUpButton': 'Anmeldung',
168 | 'auth.resetPasswordButton': 'Senden Passwort zurücksetzen',
169 | 'auth.emailFormField': 'Email',
170 | 'auth.passwordFormField': 'Passwort',
171 | 'auth.nameFormField': 'Name',
172 | 'auth.signInErrorTitle': 'Anmelden Fehler',
173 | 'auth.signInError': 'Fehler bei der Anmeldung: E-Mail oder Passwort falsch.',
174 | 'auth.resetPasswordLabelButton': 'Passwort vergessen?',
175 | 'auth.signUpLabelButton': 'Ein Konto erstellen',
176 | 'auth.signUpErrorTitle': 'Anmeldung gescheitert.',
177 | 'auth.signUpError': 'Es gab ein Problem anmeldest. Bitte versuchen Sie es später noch einmal.',
178 | 'auth.signInLabelButton': 'Ein Konto haben? Einloggen.',
179 | 'auth.resetPasswordNoticeTitle': 'Passwort zurücksetzen E-Mail gesendet',
180 | 'auth.resetPasswordNotice': 'Überprüfen Sie Ihre E-Mail und folgen Sie den Anweisungen, um Ihr Passwort zurücksetzen können.',
181 | 'auth.resetPasswordFailed': 'Passwort zurücksetzen E-Mail fehlgeschlagen',
182 | 'auth.signInonResetPasswordLabelButton': 'Einloggen',
183 | 'auth.updateUser': 'Profil aktualisieren',
184 | 'auth.updateUserSuccessNoticeTitle': 'Benutzer Aktualisiert',
185 | 'auth.updateUserSuccessNotice': 'Benutzerinformationen erfolgreich aktualisiert.',
186 | 'auth.updateUserEmailInUse': 'Die E-Mail-Adresse hat bereits ein Konto.',
187 | 'auth.updateUserFailNotice': 'Fehler beim Update Benutzer',
188 | 'auth.enterPassword': 'Geben Sie Ihr Passwort',
189 | 'auth.cancel': 'Stornieren',
190 | 'auth.submit': 'einreichen',
191 | 'auth.changePasswordLabelButton': 'Kennwort ändern',
192 | 'auth.resetPasswordTitle': 'Passwort zurücksetzen',
193 | 'auth.updateProfileTitle': 'Profil aktualisieren',
194 | 'auth.wrongPasswordNoticeTitle': 'Fehler bei der Anmeldung',
195 | 'auth.wrongPasswordNotice': 'Das Passwort nicht unsere entsprechenden Datensätze gefunden.',
196 | 'auth.unknownError': 'Unbekannter Fehler',
197 | 'settings.title': 'die Einstellungen',
198 | 'settings.language': 'Sprache',
199 | 'settings.theme': 'Thema',
200 | 'settings.signOut': 'Austragen',
201 | 'settings.dark': 'Dunkel',
202 | 'settings.light': 'Licht',
203 | 'settings.system': 'System',
204 | 'settings.updateProfile': 'Profil aktualisieren',
205 | 'home.title': 'Zuhause',
206 | 'home.nameLabel': 'Name',
207 | 'home.uidLabel': 'UID',
208 | 'home.emailLabel': 'Email',
209 | 'home.adminUserLabel': 'Admin Benutzer',
210 | 'app.title': 'Flutter Starter-Projekt',
211 | 'validator.email': 'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
212 | 'validator.password': 'Passwort muss mindestens 6 Zeichen lang sein.',
213 | 'validator.name': 'Bitte geben Sie einen Namen.',
214 | 'validator.number': 'Bitte gebe eine Nummer ein.',
215 | 'validator.notEmpty': 'Dies ist ein Pflichtfeld.',
216 | 'validator.amount': 'Bitte geben Sie eine Zahl das heißt 250 - kein Dollar-Symbol und keinen Cent',
217 | },
218 | 'hi': {
219 | 'auth.signInButton': 'दाखिल करना',
220 | 'auth.signUpButton': 'साइन अप करें',
221 | 'auth.resetPasswordButton': 'भेजें पासवर्ड रीसेट',
222 | 'auth.emailFormField': 'ईमेल',
223 | 'auth.passwordFormField': 'कुंजिका',
224 | 'auth.nameFormField': 'नाम',
225 | 'auth.signInErrorTitle': 'साइन इन त्रुटि',
226 | 'auth.signInError': 'लॉगइन असफल: ईमेल या पासवर्ड गलत है।',
227 | 'auth.resetPasswordLabelButton': 'पासवर्ड भूल गए?',
228 | 'auth.signUpLabelButton': 'खाता बनाएं',
229 | 'auth.signUpErrorTitle': 'साइन अप करने में विफल रहा।',
230 | 'auth.signUpError': 'साइन अप करने में समस्या हुई थी। बाद में पुन: प्रयास करें।',
231 | 'auth.signInLabelButton': 'एक खाता है? दाखिल करना।',
232 | 'auth.resetPasswordNoticeTitle': 'पासवर्ड रीसेट ईमेल भेजा',
233 | 'auth.resetPasswordNotice': 'अपने ईमेल की जाँच करें और निर्देशों का अपना पासवर्ड रीसेट करने का पालन करें।',
234 | 'auth.resetPasswordFailed': 'पासवर्ड रीसेट ईमेल में विफल',
235 | 'auth.signInonResetPasswordLabelButton': 'दाखिल करना',
236 | 'auth.updateUser': 'प्रोफ़ाइल अपडेट करें',
237 | 'auth.updateUserSuccessNoticeTitle': 'उपयोगकर्ता अपडेट किया गया',
238 | 'auth.updateUserSuccessNotice': 'उपयोगकर्ता जानकारी सफलतापूर्वक अपडेट।',
239 | 'auth.updateUserEmailInUse': 'यही कारण है कि ईमेल पता पहले से ही खाता है।',
240 | 'auth.updateUserFailNotice': 'उपयोगकर्ता अद्यतन करने में विफल',
241 | 'auth.enterPassword': 'अपना पासवर्ड डालें',
242 | 'auth.cancel': 'रद्द करना',
243 | 'auth.submit': 'प्रस्तुत',
244 | 'auth.changePasswordLabelButton': 'पासवर्ड बदलें',
245 | 'auth.resetPasswordTitle': 'पासवर्ड रीसेट',
246 | 'auth.updateProfileTitle': 'प्रोफ़ाइल अपडेट करें',
247 | 'auth.wrongPasswordNoticeTitle': 'लॉगिन विफल',
248 | 'auth.wrongPasswordNotice': 'पासवर्ड हमारे रिकॉर्ड से मेल नहीं खाता।',
249 | 'auth.unknownError': 'अज्ञात त्रुटि',
250 | 'settings.title': 'समायोजन',
251 | 'settings.language': 'भाषा: हिन्दी',
252 | 'settings.theme': 'विषय',
253 | 'settings.signOut': 'प्रस्थान करें',
254 | 'settings.dark': 'अंधेरा',
255 | 'settings.light': 'रोशनी',
256 | 'settings.system': 'प्रणाली',
257 | 'settings.updateProfile': 'प्रोफ़ाइल अपडेट करें',
258 | 'home.title': 'घर',
259 | 'home.nameLabel': 'नाम',
260 | 'home.uidLabel': 'यूआईडी',
261 | 'home.emailLabel': 'ईमेल',
262 | 'home.adminUserLabel': 'व्यवस्थापक उपयोगकर्ता',
263 | 'app.title': 'स्पंदन स्टार्टर परियोजना',
264 | 'validator.email': 'कृपया एक वैध ई - मेल एड्रेस डालें।',
265 | 'validator.password': 'पासवर्ड कम से कम 6 अंकों का होना चाहिए।',
266 | 'validator.name': 'एक नाम दर्ज करें।',
267 | 'validator.number': 'एक संख्या दर्ज करें।',
268 | 'validator.notEmpty': 'यह एक आवश्यक फील्ड है।',
269 | 'validator.amount': 'कोई डॉलर प्रतीक और कोई सेंट - एक नंबर अर्थात 250 दर्ज करें',
270 | },
271 | 'pt': {
272 | 'auth.signInButton': 'Entrar',
273 | 'auth.signUpButton': 'Inscrever-se',
274 | 'auth.resetPasswordButton': 'Enviar Password Reset',
275 | 'auth.emailFormField': 'E-mail',
276 | 'auth.passwordFormField': 'Senha',
277 | 'auth.nameFormField': 'Nome',
278 | 'auth.signInErrorTitle': 'Entrar erro',
279 | 'auth.signInError': 'Falha de logon: e-mail ou senha incorreta.',
280 | 'auth.resetPasswordLabelButton': 'Esqueceu a senha?',
281 | 'auth.signUpLabelButton': 'Crie a sua conta aqui',
282 | 'auth.signUpErrorTitle': 'Registre-se Falhou.',
283 | 'auth.signUpError': 'Houve um problema se inscrever. Por favor, tente novamente mais tarde.',
284 | 'auth.signInLabelButton': 'Ter uma conta? Entrar.',
285 | 'auth.resetPasswordNoticeTitle': 'Senha enviada uma reinicialização',
286 | 'auth.resetPasswordNotice': 'Verifique se o seu e-mail e siga as instruções para redefinir sua senha.',
287 | 'auth.resetPasswordFailed': 'Password Reset-mail Falha',
288 | 'auth.signInonResetPasswordLabelButton': 'Entrar',
289 | 'auth.updateUser': 'Atualizar perfil',
290 | 'auth.updateUserSuccessNoticeTitle': 'do usuário atualizada',
291 | 'auth.updateUserSuccessNotice': 'informações do usuário atualizado com sucesso.',
292 | 'auth.updateUserEmailInUse': 'Este endereço de email já tem uma conta.',
293 | 'auth.updateUserFailNotice': 'Falha ao usuário de atualização',
294 | 'auth.enterPassword': 'Coloque sua senha',
295 | 'auth.cancel': 'Cancelar',
296 | 'auth.submit': 'Enviar',
297 | 'auth.changePasswordLabelButton': 'Alterar a senha',
298 | 'auth.resetPasswordTitle': 'Password Reset',
299 | 'auth.updateProfileTitle': 'Atualizar perfil',
300 | 'auth.wrongPasswordNoticeTitle': 'Falha no login',
301 | 'auth.wrongPasswordNotice': 'A senha não coincide com nossos registros.',
302 | 'auth.unknownError': 'Erro desconhecido',
303 | 'settings.title': 'Definições',
304 | 'settings.language': 'Língua',
305 | 'settings.theme': 'Tema',
306 | 'settings.signOut': 'Sair',
307 | 'settings.dark': 'Escuro',
308 | 'settings.light': 'Luz',
309 | 'settings.system': 'Sistema',
310 | 'settings.updateProfile': 'Atualizar perfil',
311 | 'home.title': 'Casa',
312 | 'home.nameLabel': 'Nome',
313 | 'home.uidLabel': 'UID',
314 | 'home.emailLabel': 'E-mail',
315 | 'home.adminUserLabel': 'admin User',
316 | 'app.title': 'Projeto de arranque Flutter',
317 | 'validator.email': 'Por favor insira um endereço de e-mail válido.',
318 | 'validator.password': 'A senha deve ter pelo menos 6 caracteres.',
319 | 'validator.name': 'Por favor, indique um nome.',
320 | 'validator.number': 'Por favor, coloque um numero.',
321 | 'validator.notEmpty': 'Este é um campo obrigatório.',
322 | 'validator.amount': 'Por favor insira um número ou seja 250 - nenhum símbolo dólar e há centavos',
323 | },
324 | 'zh': {
325 | 'auth.signInButton': '登入',
326 | 'auth.signUpButton': '报名',
327 | 'auth.resetPasswordButton': '发送密码重置',
328 | 'auth.emailFormField': '电子邮件',
329 | 'auth.passwordFormField': '密码',
330 | 'auth.nameFormField': '名称',
331 | 'auth.signInErrorTitle': '登录错误',
332 | 'auth.signInError': '登录失败:电子邮件或密码不正确。',
333 | 'auth.resetPasswordLabelButton': '忘记密码?',
334 | 'auth.signUpLabelButton': '创建一个帐户',
335 | 'auth.signUpErrorTitle': '注册失败。',
336 | 'auth.signUpError': '有注册的问题。请稍后再试。',
337 | 'auth.signInLabelButton': '有一个账户?登入。',
338 | 'auth.resetPasswordNoticeTitle': '密码重置邮件已发送',
339 | 'auth.resetPasswordNotice': '检查你的电子邮件,并按照重置密码的说明。',
340 | 'auth.resetPasswordFailed': '密码重置电子邮件失败',
341 | 'auth.signInonResetPasswordLabelButton': '登入',
342 | 'auth.updateUser': '更新个人信息',
343 | 'auth.updateUserSuccessNoticeTitle': '用户更新',
344 | 'auth.updateUserSuccessNotice': '用户信息更新成功。',
345 | 'auth.updateUserEmailInUse': '该电子邮件地址已经有一个帐户。',
346 | 'auth.updateUserFailNotice': '无法更新用户',
347 | 'auth.enterPassword': '输入您的密码',
348 | 'auth.cancel': '取消',
349 | 'auth.submit': '提交',
350 | 'auth.changePasswordLabelButton': '更改密码',
351 | 'auth.resetPasswordTitle': '重设密码',
352 | 'auth.updateProfileTitle': '更新个人信息',
353 | 'auth.wrongPasswordNoticeTitle': '登录失败',
354 | 'auth.wrongPasswordNotice': '该密码不符合我们的记录。',
355 | 'auth.unknownError': '未知错误',
356 | 'settings.title': '设置',
357 | 'settings.language': '语',
358 | 'settings.theme': '主题',
359 | 'settings.signOut': '登出',
360 | 'settings.dark': '黑暗的',
361 | 'settings.light': '光',
362 | 'settings.system': '系统',
363 | 'settings.updateProfile': '更新个人信息',
364 | 'home.title': '家',
365 | 'home.nameLabel': '名称',
366 | 'home.uidLabel': 'UID',
367 | 'home.emailLabel': '电子邮件',
368 | 'home.adminUserLabel': '管理员用户',
369 | 'app.title': '扑启动项目',
370 | 'validator.email': '请输入有效的电子邮件地址。',
371 | 'validator.password': '密码必须至少6个字符。',
372 | 'validator.name': '请输入姓名。',
373 | 'validator.number': '请输入一个数字。',
374 | 'validator.notEmpty': '这是一个必填字段。',
375 | 'validator.amount': '请输入一个数,即250 - 没有美元符号和无分',
376 | },
377 | 'ja': {
378 | 'auth.signInButton': 'サインイン',
379 | 'auth.signUpButton': 'サインアップ',
380 | 'auth.resetPasswordButton': '送信パスワードリセット',
381 | 'auth.emailFormField': 'Eメール',
382 | 'auth.passwordFormField': 'パスワード',
383 | 'auth.nameFormField': '名前',
384 | 'auth.signInErrorTitle': 'エラーサインイン',
385 | 'auth.signInError': 'ログインに失敗しました:電子メールまたはパスワードが正しくありません。',
386 | 'auth.resetPasswordLabelButton': 'パスワードをお忘れですか?',
387 | 'auth.signUpLabelButton': 'アカウントを作成する',
388 | 'auth.signUpErrorTitle': 'サインアップは失敗しました。',
389 | 'auth.signUpError': 'サインアップする問題が発生しました。後ほど再度お試しください。',
390 | 'auth.signInLabelButton': 'アカウントを持っています?サインイン。',
391 | 'auth.resetPasswordNoticeTitle': 'パスワードリセットのメール送信され',
392 | 'auth.resetPasswordNotice': 'あなたの電子メールをチェックして、あなたのパスワードをリセットするための指示に従ってください。',
393 | 'auth.resetPasswordFailed': 'パスワードリセットのメールが失敗しました。',
394 | 'auth.signInonResetPasswordLabelButton': 'サインイン',
395 | 'auth.updateUser': 'プロフィールを更新',
396 | 'auth.updateUserSuccessNoticeTitle': 'ユーザーの更新',
397 | 'auth.updateUserSuccessNotice': 'ユーザー情報が正常に更新します。',
398 | 'auth.updateUserEmailInUse': 'そのメールアドレスは、既にアカウントを持っています。',
399 | 'auth.updateUserFailNotice': '更新ユーザーに失敗しました。',
400 | 'auth.enterPassword': 'パスワードを入力してください',
401 | 'auth.cancel': 'キャンセル',
402 | 'auth.submit': '参加する',
403 | 'auth.changePasswordLabelButton': 'パスワードを変更する',
404 | 'auth.resetPasswordTitle': 'パスワードを再設定する',
405 | 'auth.updateProfileTitle': 'プロフィールを更新',
406 | 'auth.wrongPasswordNoticeTitle': 'ログインに失敗しました',
407 | 'auth.wrongPasswordNotice': 'パスワードは我々の記録と一致しません。',
408 | 'auth.unknownError': '不明なエラー',
409 | 'settings.title': '設定',
410 | 'settings.language': '言語',
411 | 'settings.theme': 'テーマ',
412 | 'settings.signOut': 'サインアウト',
413 | 'settings.dark': '闇',
414 | 'settings.light': '光',
415 | 'settings.system': 'システム',
416 | 'settings.updateProfile': 'プロフィールを更新',
417 | 'home.title': '家',
418 | 'home.nameLabel': '名前',
419 | 'home.uidLabel': 'UID',
420 | 'home.emailLabel': 'Eメール',
421 | 'home.adminUserLabel': '管理者ユーザー',
422 | 'app.title': 'フラッタースタータープロジェクト',
423 | 'validator.email': '有効なメールアドレスを入力してください。',
424 | 'validator.password': 'パスワードは少なくとも6文字でなければなりません。',
425 | 'validator.name': '名前を入力してください。',
426 | 'validator.number': '番号を入力してください。',
427 | 'validator.notEmpty': 'これは必要項目です。',
428 | 'validator.amount': 'ノードル記号なしセント - すなわち、250番号を入力してください。',
429 | },
430 | 'ru': {
431 | 'auth.signInButton': 'Войти',
432 | 'auth.signUpButton': 'Зарегистрироваться',
433 | 'auth.resetPasswordButton': 'Отправить Сброс пароля',
434 | 'auth.emailFormField': 'Электронное письмо',
435 | 'auth.passwordFormField': 'Пароль',
436 | 'auth.nameFormField': 'Имя',
437 | 'auth.signInErrorTitle': 'Ошибка входа',
438 | 'auth.signInError': 'Войти не удалось: адрес электронной почты или пароль неверен.',
439 | 'auth.resetPasswordLabelButton': 'забыл пароль?',
440 | 'auth.signUpLabelButton': 'Завести аккаунт',
441 | 'auth.signUpErrorTitle': 'Регистрация прошла неудачно.',
442 | 'auth.signUpError': 'Была проблема подписания. Пожалуйста, повторите попытку позже.',
443 | 'auth.signInLabelButton': 'Иметь аккаунт? Войти.',
444 | 'auth.resetPasswordNoticeTitle': 'Сброс пароля Email Sent',
445 | 'auth.resetPasswordNotice': 'Проверьте электронную почту и следуйте инструкциям, чтобы сбросить пароль.',
446 | 'auth.resetPasswordFailed': 'Сброс пароля Email Failed',
447 | 'auth.signInonResetPasswordLabelButton': 'Войти',
448 | 'auth.updateUser': 'Обновить профиль',
449 | 'auth.updateUserSuccessNoticeTitle': 'Пользователь Обновлено',
450 | 'auth.updateUserSuccessNotice': 'Информация о пользователе успешно обновлена.',
451 | 'auth.updateUserEmailInUse': 'Этот адрес электронной почты уже есть учетная запись.',
452 | 'auth.updateUserFailNotice': 'Не удался пользователь обновления',
453 | 'auth.enterPassword': 'Введите свой пароль',
454 | 'auth.cancel': 'Отмена',
455 | 'auth.submit': 'Представлять на рассмотрение',
456 | 'auth.changePasswordLabelButton': 'Измени пароль',
457 | 'auth.resetPasswordTitle': 'Сброс пароля',
458 | 'auth.updateProfileTitle': 'Обновить профиль',
459 | 'auth.wrongPasswordNoticeTitle': 'Ошибка входа',
460 | 'auth.wrongPasswordNotice': 'Пароль не соответствует нашим данным.',
461 | 'auth.unknownError': 'Неизвестная ошибка',
462 | 'settings.title': 'Настройки',
463 | 'settings.language': 'Язык',
464 | 'settings.theme': 'Тема',
465 | 'settings.signOut': 'Выход',
466 | 'settings.dark': 'Темный',
467 | 'settings.light': 'Свет',
468 | 'settings.system': 'Система',
469 | 'settings.updateProfile': 'Обновить профиль',
470 | 'home.title': 'Дом',
471 | 'home.nameLabel': 'Имя',
472 | 'home.uidLabel': 'UID',
473 | 'home.emailLabel': 'Электронное письмо',
474 | 'home.adminUserLabel': 'Пользователь Admin',
475 | 'app.title': 'Проект флаттер Starter',
476 | 'validator.email': 'Пожалуйста, введите действительный адрес электронной почты.',
477 | 'validator.password': 'Пароль должен быть не менее 6 символов.',
478 | 'validator.name': 'Пожалуйста, введите имя.',
479 | 'validator.number': 'Пожалуйста, введите номер.',
480 | 'validator.notEmpty': 'Это поле обязательно для заполнения.',
481 | 'validator.amount': 'Пожалуйста, введите номер 250 - т.е. без символа доллара и ни цента',
482 | },
483 | };
484 | }
485 |
--------------------------------------------------------------------------------
/lib/helpers/update_localizations.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 | import 'dart:async';
3 | import 'dart:convert';
4 | import 'package:http/http.dart' as http;
5 | import 'package:csv/csv.dart';
6 |
7 | void main() {
8 | updateLocalizationFile();
9 | }
10 |
11 | Future updateLocalizationFile() async {
12 | //the document id for your google sheet
13 | String documentId = "1oS7iJ6ocrZBA53SxRfKF0CG9HAaXeKtzvsTBhgG4Zzk";
14 | //the sheetid of your google sheet
15 | String sheetId = "0";
16 |
17 | String _phraseKey = '';
18 | List _localizations = [];
19 | String _localizationFile = """import 'package:get/get.dart';
20 |
21 | class Localization extends Translations {
22 | @override
23 | Map> get keys => {
24 | """;
25 |
26 | try {
27 | final url =
28 | 'https://docs.google.com/spreadsheets/d/$documentId/export?format=csv&id=$documentId&gid=$sheetId';
29 |
30 | stdout.writeln('');
31 | stdout.writeln('---------------------------------------');
32 | stdout.writeln('Downloading Google sheet url "$url" ...');
33 | stdout.writeln('---------------------------------------');
34 | var response = await http
35 | .get(Uri.parse(url), headers: {'accept': 'text/csv;charset=UTF-8'});
36 |
37 | // print('Google sheet csv:\n ${response.body}');
38 |
39 | final bytes = response.bodyBytes.toList();
40 | final csv = Stream>.fromIterable([bytes]);
41 |
42 | final fields = await csv
43 | .transform(utf8.decoder)
44 | .transform(CsvToListConverter(
45 | shouldParseNumbers: false,
46 | ))
47 | .toList();
48 |
49 | final index = fields[0]
50 | .cast()
51 | .map(_uniformizeKey)
52 | .takeWhile((x) => x.isNotEmpty)
53 | .toList();
54 |
55 | for (var r = 1; r < fields.length; r++) {
56 | final rowValues = fields[r];
57 |
58 | /// Creating a map
59 | final row = Map.fromEntries(
60 | rowValues
61 | .asMap()
62 | .entries
63 | .where(
64 | (e) => e.key < index.length,
65 | )
66 | .map(
67 | (e) => MapEntry(index[e.key], e.value),
68 | ),
69 | );
70 |
71 | row.forEach((key, value) {
72 | if (key == 'key') {
73 | _phraseKey = value;
74 | } else {
75 | bool _languageAdded = false;
76 | _localizations.forEach((element) {
77 | if (element.language == key) {
78 | element.phrases.add(PhraseModel(key: _phraseKey, phrase: value));
79 | _languageAdded = true;
80 | }
81 | });
82 | if (_languageAdded == false) {
83 | _localizations.add(LocalizationModel(
84 | language: key,
85 | phrases: [PhraseModel(key: _phraseKey, phrase: value)]));
86 | }
87 | }
88 | });
89 | }
90 |
91 | _localizations.forEach((_localization) {
92 | String _language = _localization.language;
93 | String _currentLanguageTextCode = "'$_language': {\n";
94 | _localizationFile = _localizationFile + _currentLanguageTextCode;
95 | _localization.phrases.forEach((_phrase) {
96 | String _phraseKey = _phrase.key;
97 | String _phrasePhrase = _phrase.phrase.replaceAll(r"'", "\\\'");
98 | String _currentPhraseTextCode = "'$_phraseKey': '$_phrasePhrase',\n";
99 | _localizationFile = _localizationFile + _currentPhraseTextCode;
100 | });
101 | String _currentLanguageCodeEnding = "},\n";
102 | _localizationFile = _localizationFile + _currentLanguageCodeEnding;
103 | });
104 | String _fileEnding = """
105 | };
106 | }
107 | """;
108 | _localizationFile = _localizationFile + _fileEnding;
109 |
110 | stdout.writeln('');
111 | stdout.writeln('---------------------------------------');
112 | stdout.writeln('Saving localization.g.dart');
113 | stdout.writeln('---------------------------------------');
114 | final file = File('localization.g.dart');
115 | await file.writeAsString(_localizationFile);
116 | stdout.writeln('Done...');
117 | } catch (e) {
118 | //output error
119 | stderr.writeln('error: networking error');
120 | stderr.writeln(e.toString());
121 | }
122 | }
123 |
124 | String _uniformizeKey(String key) {
125 | key = key.trim().replaceAll('\n', '').toLowerCase();
126 | return key;
127 | }
128 |
129 | //Localization Model
130 | class LocalizationModel {
131 | final String language;
132 | final List phrases;
133 |
134 | LocalizationModel({
135 | required this.language,
136 | required this.phrases,
137 | });
138 |
139 | factory LocalizationModel.fromMap(Map data) {
140 | return LocalizationModel(
141 | language: data['language'],
142 | phrases:
143 | (data['phrases'] as List).map((v) => PhraseModel.fromMap(v)).toList(),
144 | );
145 | }
146 |
147 | Map toJson() => {
148 | "language": language,
149 | "phrases": List.from(phrases.map((x) => x.toJson())),
150 | };
151 | }
152 |
153 | class PhraseModel {
154 | String key;
155 | String phrase;
156 |
157 | PhraseModel({required this.key, required this.phrase});
158 |
159 | factory PhraseModel.fromMap(Map data) {
160 | return PhraseModel(
161 | key: data['key'],
162 | phrase: data['phrase'] ?? '',
163 | );
164 | }
165 | Map toJson() => {
166 | "key": key,
167 | "phrase": phrase,
168 | };
169 | }
170 |
--------------------------------------------------------------------------------
/lib/helpers/validator.dart:
--------------------------------------------------------------------------------
1 | // matching various patterns for kinds of data
2 | import 'package:get/get.dart';
3 |
4 | class Validator {
5 | Validator();
6 |
7 | String? email(String? value) {
8 | String pattern = r'^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+';
9 | RegExp regex = RegExp(pattern);
10 | if (!regex.hasMatch(value!))
11 | return 'validator.email'.tr;
12 | else
13 | return null;
14 | }
15 |
16 | String? password(String? value) {
17 | String pattern = r'^.{6,}$';
18 | RegExp regex = RegExp(pattern);
19 | if (!regex.hasMatch(value!))
20 | return 'validator.password'.tr;
21 | else
22 | return null;
23 | }
24 |
25 | String? name(String? value) {
26 | String pattern = r"^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$";
27 | RegExp regex = RegExp(pattern);
28 | if (!regex.hasMatch(value!))
29 | return 'validator.name'.tr;
30 | else
31 | return null;
32 | }
33 |
34 | String? number(String? value) {
35 | String pattern = r'^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$';
36 | RegExp regex = RegExp(pattern);
37 | if (!regex.hasMatch(value!))
38 | return 'validator.number'.tr;
39 | else
40 | return null;
41 | }
42 |
43 | String? amount(String? value) {
44 | String pattern = r'^\d+$';
45 | RegExp regex = RegExp(pattern);
46 | if (!regex.hasMatch(value!))
47 | return 'validator.amount'.tr;
48 | else
49 | return null;
50 | }
51 |
52 | String? notEmpty(String? value) {
53 | String pattern = r'^\S+$';
54 | RegExp regex = RegExp(pattern);
55 | if (!regex.hasMatch(value!))
56 | return 'validator.notEmpty'.tr;
57 | else
58 | return null;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:firebase_core/firebase_core.dart';
3 | //import 'package:firebase_analytics/firebase_analytics.dart';
4 | //import 'package:firebase_analytics/observer.dart';
5 | import 'package:flutter_starter/controllers/controllers.dart';
6 | import 'package:flutter_starter/constants/constants.dart';
7 | import 'package:flutter_starter/ui/components/components.dart';
8 | import 'package:flutter_starter/helpers/helpers.dart';
9 | import 'package:get/get.dart';
10 | import 'package:get_storage/get_storage.dart';
11 |
12 | void main() async {
13 | WidgetsFlutterBinding.ensureInitialized();
14 | await Firebase.initializeApp();
15 | await GetStorage.init();
16 | Get.put(AuthController());
17 | Get.put(ThemeController());
18 | Get.put(LanguageController());
19 | runApp(MyApp());
20 | }
21 |
22 | class MyApp extends StatelessWidget {
23 | @override
24 | Widget build(BuildContext context) {
25 | ThemeController.to.getThemeModeFromStore();
26 | return GetBuilder(
27 | builder: (languageController) => Loading(
28 | child: GetMaterialApp(
29 | translations: Localization(),
30 | locale: languageController.getLocale, // <- Current locale
31 | navigatorObservers: [
32 | // FirebaseAnalyticsObserver(analytics: FirebaseAnalytics()),
33 | ],
34 | debugShowCheckedModeBanner: false,
35 | //defaultTransition: Transition.fade,
36 | theme: AppThemes.lightTheme,
37 | darkTheme: AppThemes.darkTheme,
38 | themeMode: ThemeMode.system,
39 | initialRoute: "/",
40 | getPages: AppRoutes.routes,
41 | ),
42 | ),
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/models/menu_option_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | // Model class to hold menu option data (language and theme)
4 | class MenuOptionsModel {
5 | final String key;
6 | final String value;
7 | final IconData? icon;
8 |
9 | MenuOptionsModel({required this.key, required this.value, this.icon});
10 | }
11 |
--------------------------------------------------------------------------------
/lib/models/models.dart:
--------------------------------------------------------------------------------
1 | export 'user_model.dart';
2 | export 'menu_option_model.dart';
3 |
--------------------------------------------------------------------------------
/lib/models/user_model.dart:
--------------------------------------------------------------------------------
1 | //User Model
2 | class UserModel {
3 | final String uid;
4 | final String email;
5 | final String name;
6 | final String photoUrl;
7 |
8 | UserModel(
9 | {required this.uid,
10 | required this.email,
11 | required this.name,
12 | required this.photoUrl});
13 |
14 | factory UserModel.fromMap(Map data) {
15 | return UserModel(
16 | uid: data['uid'],
17 | email: data['email'] ?? '',
18 | name: data['name'] ?? '',
19 | photoUrl: data['photoUrl'] ?? '',
20 | );
21 | }
22 |
23 | Map toJson() =>
24 | {"uid": uid, "email": email, "name": name, "photoUrl": photoUrl};
25 | }
26 |
--------------------------------------------------------------------------------
/lib/ui/auth/auth.dart:
--------------------------------------------------------------------------------
1 | export 'sign_in_ui.dart';
2 | export 'sign_up_ui.dart';
3 | export 'reset_password_ui.dart';
4 | export 'update_profile_ui.dart';
5 |
--------------------------------------------------------------------------------
/lib/ui/auth/reset_password_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:get/get.dart';
4 | import 'package:flutter_starter/ui/auth/auth.dart';
5 | import 'package:flutter_starter/ui/components/components.dart';
6 | import 'package:flutter_starter/helpers/helpers.dart';
7 | import 'package:flutter_starter/controllers/controllers.dart';
8 |
9 | class ResetPasswordUI extends StatelessWidget {
10 | final AuthController authController = AuthController.to;
11 | final GlobalKey _formKey = GlobalKey();
12 |
13 | Widget build(BuildContext context) {
14 | return Scaffold(
15 | appBar: appBar(context),
16 | body: Form(
17 | key: _formKey,
18 | child: Padding(
19 | padding: const EdgeInsets.symmetric(horizontal: 24.0),
20 | child: Center(
21 | child: SingleChildScrollView(
22 | child: Column(
23 | mainAxisAlignment: MainAxisAlignment.center,
24 | crossAxisAlignment: CrossAxisAlignment.stretch,
25 | children: [
26 | LogoGraphicHeader(),
27 | SizedBox(height: 48.0),
28 | FormInputFieldWithIcon(
29 | controller: authController.emailController,
30 | iconPrefix: Icons.email,
31 | labelText: 'auth.emailFormField'.tr,
32 | validator: Validator().email,
33 | keyboardType: TextInputType.emailAddress,
34 | onChanged: (value) => null,
35 | onSaved: (value) =>
36 | authController.emailController.text = value as String,
37 | ),
38 | FormVerticalSpace(),
39 | PrimaryButton(
40 | labelText: 'auth.resetPasswordButton'.tr,
41 | onPressed: () async {
42 | if (_formKey.currentState!.validate()) {
43 | await authController.sendPasswordResetEmail(context);
44 | }
45 | }),
46 | FormVerticalSpace(),
47 | signInLink(context),
48 | ],
49 | ),
50 | ),
51 | ),
52 | ),
53 | ),
54 | );
55 | }
56 |
57 | appBar(BuildContext context) {
58 | if (authController.emailController.text == '') {
59 | return null;
60 | }
61 | return AppBar(title: Text('auth.resetPasswordTitle'.tr));
62 | }
63 |
64 | signInLink(BuildContext context) {
65 | if (authController.emailController.text == '') {
66 | return LabelButton(
67 | labelText: 'auth.signInonResetPasswordLabelButton'.tr,
68 | onPressed: () => Get.offAll(SignInUI()),
69 | );
70 | }
71 | return Container(width: 0, height: 0);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/ui/auth/sign_in_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 |
4 | import 'dart:core';
5 | import 'package:get/get.dart';
6 | import 'package:flutter_starter/ui/auth/auth.dart';
7 | import 'package:flutter_starter/ui/components/components.dart';
8 | import 'package:flutter_starter/helpers/helpers.dart';
9 | import 'package:flutter_starter/controllers/controllers.dart';
10 |
11 | class SignInUI extends StatelessWidget {
12 | final AuthController authController = AuthController.to;
13 | final GlobalKey _formKey = GlobalKey();
14 |
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | body: Form(
18 | key: _formKey,
19 | child: Padding(
20 | padding: const EdgeInsets.symmetric(horizontal: 24.0),
21 | child: Center(
22 | child: SingleChildScrollView(
23 | child: Column(
24 | mainAxisAlignment: MainAxisAlignment.center,
25 | crossAxisAlignment: CrossAxisAlignment.stretch,
26 | children: [
27 | LogoGraphicHeader(),
28 | SizedBox(height: 48.0),
29 | FormInputFieldWithIcon(
30 | controller: authController.emailController,
31 | iconPrefix: Icons.email,
32 | labelText: 'auth.emailFormField'.tr,
33 | validator: Validator().email,
34 | keyboardType: TextInputType.emailAddress,
35 | onChanged: (value) => null,
36 | onSaved: (value) =>
37 | authController.emailController.text = value!,
38 | ),
39 | FormVerticalSpace(),
40 | FormInputFieldWithIcon(
41 | controller: authController.passwordController,
42 | iconPrefix: Icons.lock,
43 | labelText: 'auth.passwordFormField'.tr,
44 | validator: Validator().password,
45 | obscureText: true,
46 | onChanged: (value) => null,
47 | onSaved: (value) =>
48 | authController.passwordController.text = value!,
49 | maxLines: 1,
50 | ),
51 | FormVerticalSpace(),
52 | PrimaryButton(
53 | labelText: 'auth.signInButton'.tr,
54 | onPressed: () async {
55 | if (_formKey.currentState!.validate()) {
56 | authController.signInWithEmailAndPassword(context);
57 | }
58 | }),
59 | FormVerticalSpace(),
60 | LabelButton(
61 | labelText: 'auth.resetPasswordLabelButton'.tr,
62 | onPressed: () => Get.to(ResetPasswordUI()),
63 | ),
64 | LabelButton(
65 | labelText: 'auth.signUpLabelButton'.tr,
66 | onPressed: () => Get.to(SignUpUI()),
67 | ),
68 | ],
69 | ),
70 | ),
71 | ),
72 | ),
73 | ),
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/ui/auth/sign_up_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:get/get.dart';
4 | import 'package:flutter_starter/ui/components/components.dart';
5 | import 'package:flutter_starter/helpers/helpers.dart';
6 | import 'package:flutter_starter/controllers/controllers.dart';
7 | import 'package:flutter_starter/ui/auth/auth.dart';
8 |
9 | class SignUpUI extends StatelessWidget {
10 | final AuthController authController = AuthController.to;
11 | final GlobalKey _formKey = GlobalKey();
12 |
13 | Widget build(BuildContext context) {
14 | return Scaffold(
15 | body: Form(
16 | key: _formKey,
17 | child: Padding(
18 | padding: const EdgeInsets.symmetric(horizontal: 24.0),
19 | child: Center(
20 | child: SingleChildScrollView(
21 | child: Column(
22 | mainAxisAlignment: MainAxisAlignment.center,
23 | crossAxisAlignment: CrossAxisAlignment.stretch,
24 | children: [
25 | LogoGraphicHeader(),
26 | SizedBox(height: 48.0),
27 | FormInputFieldWithIcon(
28 | controller: authController.nameController,
29 | iconPrefix: Icons.person,
30 | labelText: 'auth.nameFormField'.tr,
31 | validator: Validator().name,
32 | onChanged: (value) => null,
33 | onSaved: (value) =>
34 | authController.nameController.text = value!,
35 | ),
36 | FormVerticalSpace(),
37 | FormInputFieldWithIcon(
38 | controller: authController.emailController,
39 | iconPrefix: Icons.email,
40 | labelText: 'auth.emailFormField'.tr,
41 | validator: Validator().email,
42 | keyboardType: TextInputType.emailAddress,
43 | onChanged: (value) => null,
44 | onSaved: (value) =>
45 | authController.emailController.text = value!,
46 | ),
47 | FormVerticalSpace(),
48 | FormInputFieldWithIcon(
49 | controller: authController.passwordController,
50 | iconPrefix: Icons.lock,
51 | labelText: 'auth.passwordFormField'.tr,
52 | validator: Validator().password,
53 | obscureText: true,
54 | onChanged: (value) => null,
55 | onSaved: (value) =>
56 | authController.passwordController.text = value!,
57 | maxLines: 1,
58 | ),
59 | FormVerticalSpace(),
60 | PrimaryButton(
61 | labelText: 'auth.signUpButton'.tr,
62 | onPressed: () async {
63 | if (_formKey.currentState!.validate()) {
64 | SystemChannels.textInput.invokeMethod(
65 | 'TextInput.hide'); //to hide the keyboard - if any
66 | authController.registerWithEmailAndPassword(context);
67 | }
68 | }),
69 | FormVerticalSpace(),
70 | LabelButton(
71 | labelText: 'auth.signInLabelButton'.tr,
72 | onPressed: () => Get.to(SignInUI()),
73 | ),
74 | ],
75 | ),
76 | ),
77 | ),
78 | ),
79 | ),
80 | );
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/lib/ui/auth/update_profile_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:get/get.dart';
4 | import 'package:flutter_starter/models/models.dart';
5 | import 'package:flutter_starter/ui/components/components.dart';
6 | import 'package:flutter_starter/helpers/helpers.dart';
7 | import 'package:flutter_starter/controllers/controllers.dart';
8 | import 'package:flutter_starter/ui/auth/auth.dart';
9 |
10 | class UpdateProfileUI extends StatelessWidget {
11 | final AuthController authController = AuthController.to;
12 | final GlobalKey _formKey = GlobalKey();
13 |
14 | Widget build(BuildContext context) {
15 | //print('user.name: ' + user?.value?.name);
16 | authController.nameController.text =
17 | authController.firestoreUser.value!.name;
18 | authController.emailController.text =
19 | authController.firestoreUser.value!.email;
20 | return Scaffold(
21 | appBar: AppBar(title: Text('auth.updateProfileTitle'.tr)),
22 | body: Form(
23 | key: _formKey,
24 | child: Padding(
25 | padding: const EdgeInsets.symmetric(horizontal: 24.0),
26 | child: Center(
27 | child: SingleChildScrollView(
28 | child: Column(
29 | mainAxisAlignment: MainAxisAlignment.center,
30 | crossAxisAlignment: CrossAxisAlignment.stretch,
31 | children: [
32 | LogoGraphicHeader(),
33 | SizedBox(height: 48.0),
34 | FormInputFieldWithIcon(
35 | controller: authController.nameController,
36 | iconPrefix: Icons.person,
37 | labelText: 'auth.nameFormField'.tr,
38 | validator: Validator().name,
39 | onChanged: (value) => null,
40 | onSaved: (value) =>
41 | authController.nameController.text = value!,
42 | ),
43 | FormVerticalSpace(),
44 | FormInputFieldWithIcon(
45 | controller: authController.emailController,
46 | iconPrefix: Icons.email,
47 | labelText: 'auth.emailFormField'.tr,
48 | validator: Validator().email,
49 | keyboardType: TextInputType.emailAddress,
50 | onChanged: (value) => null,
51 | onSaved: (value) =>
52 | authController.emailController.text = value!,
53 | ),
54 | FormVerticalSpace(),
55 | PrimaryButton(
56 | labelText: 'auth.updateUser'.tr,
57 | onPressed: () async {
58 | if (_formKey.currentState!.validate()) {
59 | SystemChannels.textInput
60 | .invokeMethod('TextInput.hide');
61 | UserModel _updatedUser = UserModel(
62 | uid: authController.firestoreUser.value!.uid,
63 | name: authController.nameController.text,
64 | email: authController.emailController.text,
65 | photoUrl:
66 | authController.firestoreUser.value!.photoUrl);
67 | _updateUserConfirm(context, _updatedUser,
68 | authController.firestoreUser.value!.email);
69 | }
70 | }),
71 | FormVerticalSpace(),
72 | LabelButton(
73 | labelText: 'auth.resetPasswordLabelButton'.tr,
74 | onPressed: () => Get.to(ResetPasswordUI()),
75 | ),
76 | ],
77 | ),
78 | ),
79 | ),
80 | ),
81 | ),
82 | );
83 | }
84 |
85 | Future _updateUserConfirm(
86 | BuildContext context, UserModel updatedUser, String oldEmail) async {
87 | final AuthController authController = AuthController.to;
88 | final TextEditingController _password = new TextEditingController();
89 | return Get.dialog(
90 | AlertDialog(
91 | shape: RoundedRectangleBorder(
92 | borderRadius: BorderRadius.all(Radius.circular(8.0))),
93 | title: Text(
94 | 'auth.enterPassword'.tr,
95 | ),
96 | content: FormInputFieldWithIcon(
97 | controller: _password,
98 | iconPrefix: Icons.lock,
99 | labelText: 'auth.passwordFormField'.tr,
100 | validator: (value) {
101 | String pattern = r'^.{6,}$';
102 | RegExp regex = RegExp(pattern);
103 | if (!regex.hasMatch(value!))
104 | return 'validator.password'.tr;
105 | else
106 | return null;
107 | },
108 | obscureText: true,
109 | onChanged: (value) => null,
110 | onSaved: (value) => _password.text = value!,
111 | maxLines: 1,
112 | ),
113 | actions: [
114 | new TextButton(
115 | child: new Text('auth.cancel'.tr.toUpperCase()),
116 | onPressed: () {
117 | Get.back();
118 | },
119 | ),
120 | new TextButton(
121 | child: new Text('auth.submit'.tr.toUpperCase()),
122 | onPressed: () async {
123 | Get.back();
124 | await authController.updateUser(
125 | context, updatedUser, oldEmail, _password.text);
126 | },
127 | )
128 | ],
129 | ),
130 | );
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/lib/ui/components/avatar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_starter/models/models.dart';
3 | import 'package:flutter_starter/ui/components/components.dart';
4 |
5 | class Avatar extends StatelessWidget {
6 | Avatar(
7 | this.user,
8 | );
9 | final UserModel user;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | if (user.photoUrl == '') {
14 | return LogoGraphicHeader();
15 | }
16 | return Hero(
17 | tag: 'User Avatar Image',
18 | child: CircleAvatar(
19 | foregroundColor: Colors.blue,
20 | backgroundColor: Colors.white,
21 | radius: 70.0,
22 | child: ClipOval(
23 | child: Image.network(
24 | user.photoUrl,
25 | fit: BoxFit.cover,
26 | width: 120.0,
27 | height: 120.0,
28 | ),
29 | )),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/ui/components/components.dart:
--------------------------------------------------------------------------------
1 | export 'form_input_field_with_icon.dart';
2 | export 'form_input_field.dart';
3 | export 'form_vertical_spacing.dart';
4 | export 'primary_button.dart';
5 | export 'label_button.dart';
6 | export 'logo_graphic_header.dart';
7 | export 'dropdown_picker.dart';
8 | export 'dropdown_picker_with_icon.dart';
9 | export 'avatar.dart';
10 | export 'loading.dart';
11 |
--------------------------------------------------------------------------------
/lib/ui/components/dropdown_picker.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | /*
3 | DropdownPicker(
4 | menuOptions: list of dropdown options in key value pairs,
5 | selectedOption: menu option string value,
6 | onChanged: (value) => print('changed'),
7 | ),
8 | */
9 |
10 | class DropdownPicker extends StatelessWidget {
11 | DropdownPicker(
12 | {required this.menuOptions,
13 | required this.selectedOption,
14 | required this.onChanged});
15 |
16 | final List menuOptions;
17 | final String selectedOption;
18 | final void Function(String?) onChanged;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return DropdownButton(
23 | items: menuOptions
24 | .map((data) => DropdownMenuItem(
25 | child: Text(
26 | data.value,
27 | ),
28 | value: data.key,
29 | ))
30 | .toList(),
31 | value: selectedOption,
32 | onChanged: onChanged);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/ui/components/dropdown_picker_with_icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /*
4 | DropdownPickerWithIcon(
5 | menuOptions: list of dropdown options in key value pairs,
6 | selectedOption: menu option string value,
7 | onChanged: (value) => print('changed'),
8 | ),
9 | */
10 | class DropdownPickerWithIcon extends StatelessWidget {
11 | DropdownPickerWithIcon(
12 | {required this.menuOptions,
13 | required this.selectedOption,
14 | this.onChanged});
15 |
16 | final List menuOptions;
17 | final String selectedOption;
18 | final void Function(String?)? onChanged;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | //if (Platform.isIOS) {}
23 | return DropdownButton(
24 | items: menuOptions
25 | .map((data) => DropdownMenuItem(
26 | child: Row(
27 | mainAxisAlignment: MainAxisAlignment.start,
28 | children: [
29 | Icon(data.icon),
30 | SizedBox(width: 10),
31 | Text(
32 | data.value,
33 | ),
34 | ],
35 | ),
36 | value: data.key,
37 | ))
38 | .toList(),
39 | value: selectedOption,
40 | onChanged: onChanged);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/ui/components/form_input_field.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /*
4 | FormInputField(
5 | controller: _url,
6 | labelText: 'Post URL',
7 | validator: Validator.notEmpty,
8 | keyboardType: TextInputType.multiline,
9 | minLines: 3,
10 | onChanged: (value) => print('changed'),
11 | onSaved: (value) => print('implement me'),
12 | ),
13 | */
14 |
15 | class FormInputField extends StatelessWidget {
16 | FormInputField(
17 | {required this.controller,
18 | required this.labelText,
19 | required this.validator,
20 | this.keyboardType = TextInputType.text,
21 | this.obscureText = false,
22 | this.minLines = 1,
23 | required this.onChanged,
24 | required this.onSaved});
25 |
26 | final TextEditingController controller;
27 | final String labelText;
28 | final String? Function(String?)? validator;
29 | final TextInputType keyboardType;
30 | final bool obscureText;
31 | final int minLines;
32 | final void Function(String) onChanged;
33 | final void Function(String?)? onSaved;
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return TextFormField(
38 | decoration: InputDecoration(
39 | border: OutlineInputBorder(
40 | borderRadius: BorderRadius.all(
41 | Radius.circular(8.0),
42 | )),
43 | enabledBorder: OutlineInputBorder(
44 | borderSide: BorderSide(color: Colors.black45, width: 1.0),
45 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
46 | ),
47 | focusedBorder: OutlineInputBorder(
48 | borderSide: BorderSide(
49 | color: /*Palette.focusedinputBorderColor*/ Colors.black45,
50 | width: 1.0),
51 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
52 | ),
53 | filled: true,
54 | fillColor: Colors.black45, //Palette.inputFillColor,
55 | labelText: labelText,
56 | ),
57 | controller: controller,
58 | onSaved: onSaved,
59 | onChanged: onChanged,
60 | keyboardType: keyboardType,
61 | obscureText: obscureText,
62 | maxLines: null,
63 | minLines: minLines,
64 | validator: validator,
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/ui/components/form_input_field_with_icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | /*
3 | FormInputFieldWithIcon(
4 | controller: _email,
5 | iconPrefix: Icons.link,
6 | labelText: 'Post URL',
7 | validator: Validator.notEmpty,
8 | keyboardType: TextInputType.multiline,
9 | minLines: 3,
10 | onChanged: (value) => print('changed'),
11 | onSaved: (value) => print('implement me'),
12 | ),
13 | */
14 |
15 | class FormInputFieldWithIcon extends StatelessWidget {
16 | FormInputFieldWithIcon(
17 | {required this.controller,
18 | required this.iconPrefix,
19 | required this.labelText,
20 | required this.validator,
21 | this.keyboardType = TextInputType.text,
22 | this.obscureText = false,
23 | this.minLines = 1,
24 | this.maxLines,
25 | required this.onChanged,
26 | required this.onSaved});
27 |
28 | final TextEditingController controller;
29 | final IconData iconPrefix;
30 | final String labelText;
31 | final String? Function(String?)? validator;
32 | final TextInputType keyboardType;
33 | final bool obscureText;
34 | final int minLines;
35 | final int? maxLines;
36 | final void Function(String) onChanged;
37 | final void Function(String?)? onSaved;
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return TextFormField(
42 | decoration: InputDecoration(
43 | filled: true,
44 | prefixIcon: Icon(iconPrefix),
45 | labelText: labelText,
46 | ),
47 | controller: controller,
48 | onSaved: onSaved,
49 | onChanged: onChanged,
50 | keyboardType: keyboardType,
51 | obscureText: obscureText,
52 | maxLines: maxLines,
53 | minLines: minLines,
54 | validator: validator,
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/ui/components/form_vertical_spacing.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FormVerticalSpace extends SizedBox {
4 | FormVerticalSpace({double height = 24.0}) : super(height: height);
5 | }
6 |
--------------------------------------------------------------------------------
/lib/ui/components/label_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | /*
3 | LabelButton(
4 | labelText: 'Some Text',
5 | onPressed: () => print('implement me'),
6 | ),
7 | */
8 |
9 | class LabelButton extends StatelessWidget {
10 | LabelButton({required this.labelText, required this.onPressed});
11 | final String labelText;
12 | final void Function() onPressed;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return TextButton(
17 | child: Text(
18 | labelText,
19 | ),
20 | onPressed: onPressed,
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/ui/components/loading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 |
4 | //loading indicator code is a modified and simplified version of this code
5 | //https://github.com/fayaz07/ots
6 |
7 | final _tKey = GlobalKey(debugLabel: 'overlay_parent');
8 |
9 | /// Updates with the latest [OverlayEntry] child
10 | late OverlayEntry _loaderEntry;
11 |
12 | /// is dark theme
13 | bool isDarkTheme = false;
14 |
15 | /// To keep track if the [Overlay] is shown
16 | bool _loaderShown = false;
17 |
18 | class Loading extends StatelessWidget {
19 | final Widget? child;
20 | final bool darkTheme;
21 |
22 | const Loading({Key? key, this.child, this.darkTheme = false})
23 | : super(key: key);
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | isDarkTheme = darkTheme;
28 | return SizedBox(
29 | key: _tKey,
30 | child: child,
31 | );
32 | }
33 | }
34 |
35 | OverlayState? get _overlayState {
36 | final context = _tKey.currentContext;
37 | if (context == null) return null;
38 |
39 | NavigatorState? navigator;
40 |
41 | void visitor(Element element) {
42 | if (navigator != null) return;
43 |
44 | if (element.widget is Navigator) {
45 | navigator = (element as StatefulElement).state as NavigatorState;
46 | } else {
47 | element.visitChildElements(visitor);
48 | }
49 | }
50 |
51 | // ignore: unused_element
52 | context.visitChildElements(visitor);
53 |
54 | assert(navigator != null, '''unable to show overlay''');
55 | return navigator!.overlay;
56 | }
57 |
58 | /// To handle a loader for the application
59 | Future showLoadingIndicator(
60 | {bool isModal = true, Color? modalColor}) async {
61 | try {
62 | debugPrint('Showing loading overlay');
63 | final _child = Center(
64 | child: SizedBox(
65 | child: CircularProgressIndicator(),
66 | /*(Platform.isAndroid
67 | ? CircularProgressIndicator()
68 | : CupertinoActivityIndicator()),*/
69 | width: 30,
70 | height: 30,
71 | ),
72 | );
73 | await _showOverlay(
74 | child: isModal
75 | ? Stack(
76 | children: [
77 | ModalBarrier(
78 | color: modalColor,
79 | ),
80 | _child
81 | ],
82 | )
83 | : _child,
84 | );
85 | } catch (err) {
86 | debugPrint('Exception showing loading overlay\n${err.toString()}');
87 | throw err;
88 | }
89 | }
90 |
91 | Future hideLoadingIndicator() async {
92 | try {
93 | debugPrint('Hiding loading overlay');
94 | await _hideOverlay();
95 | } catch (err) {
96 | debugPrint('Exception hiding loading overlay');
97 | throw err;
98 | }
99 | }
100 |
101 | ///----------------------------------------------------------------------------
102 | /// These methods deal with showing and hiding the overlay
103 | Future _showOverlay({required Widget child}) async {
104 | try {
105 | final overlay = _overlayState;
106 |
107 | if (_loaderShown) {
108 | debugPrint('An overlay is already showing');
109 | return Future.value(false);
110 | }
111 |
112 | final overlayEntry = OverlayEntry(
113 | builder: (context) => child,
114 | );
115 |
116 | overlay?.insert(overlayEntry);
117 | _loaderEntry = overlayEntry;
118 | _loaderShown = true;
119 | } catch (err) {
120 | debugPrint('Exception inserting loading overlay\n${err.toString()}');
121 | throw err;
122 | }
123 | }
124 |
125 | Future _hideOverlay() async {
126 | try {
127 | _loaderEntry.remove();
128 | _loaderShown = false;
129 | } catch (err) {
130 | debugPrint('Exception removing loading overlay\n${err.toString()}');
131 | throw err;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/lib/ui/components/logo_graphic_header.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_starter/controllers/controllers.dart';
3 |
4 | class LogoGraphicHeader extends StatelessWidget {
5 | LogoGraphicHeader();
6 | final ThemeController themeController = ThemeController.to;
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | String _imageLogo = 'assets/images/default.png';
11 | if (themeController.isDarkModeOn == true) {
12 | _imageLogo = 'assets/images/defaultDark.png';
13 | }
14 | return Hero(
15 | tag: 'App Logo',
16 | child: CircleAvatar(
17 | foregroundColor: Colors.blue,
18 | backgroundColor: Colors.transparent,
19 | radius: 60.0,
20 | child: ClipOval(
21 | child: Image.asset(
22 | _imageLogo,
23 | fit: BoxFit.cover,
24 | width: 120.0,
25 | height: 120.0,
26 | ),
27 | )),
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/ui/components/primary_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /*
4 | PrimaryButton(
5 | labelText: 'UPDATE',
6 | onPressed: () => print('Submit'),
7 | ),
8 | */
9 |
10 | class PrimaryButton extends StatelessWidget {
11 | PrimaryButton({required this.labelText, required this.onPressed});
12 |
13 | final String labelText;
14 | final void Function() onPressed;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return ElevatedButton(
19 | onPressed: onPressed,
20 | child: Text(
21 | labelText.toUpperCase(),
22 | style: TextStyle(fontWeight: FontWeight.bold),
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/ui/components/segmented_selector.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 | //import 'package:flutter_starter/ui/components/sliding_segmented_control.dart';
4 | /*
5 | SegmentedSelector(
6 | menuOptions: list of dropdown options in key value pairs,
7 | selectedOption: menu option string value,
8 | onChanged: (value) => print('changed'),
9 | ),
10 | */
11 |
12 | class SegmentedSelector extends StatelessWidget {
13 | SegmentedSelector(
14 | {required this.menuOptions,
15 | required this.selectedOption,
16 | required this.onValueChanged});
17 |
18 | final List menuOptions;
19 | final String selectedOption;
20 | final void Function(dynamic) onValueChanged;
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | //if (Platform.isIOS) {}
25 |
26 | return CupertinoSlidingSegmentedControl(
27 | //thumbColor: Theme.of(context).primaryColor,
28 | groupValue: selectedOption,
29 | children: Map.fromIterable(
30 | menuOptions,
31 | key: (option) => option.key,
32 | value: (option) => Row(
33 | mainAxisAlignment: MainAxisAlignment.center,
34 | children: [
35 | Icon(option.icon),
36 | SizedBox(width: 6),
37 | Text(option.value),
38 | ],
39 | ),
40 | ),
41 | onValueChanged: onValueChanged);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/ui/home_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_starter/controllers/controllers.dart';
3 | import 'package:flutter_starter/ui/components/components.dart';
4 | import 'package:flutter_starter/ui/ui.dart';
5 | import 'package:get/get.dart';
6 |
7 | class HomeUI extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return GetBuilder(
11 | init: AuthController(),
12 | builder: (controller) => controller.firestoreUser.value!.uid == null
13 | ? Center(
14 | child: CircularProgressIndicator(),
15 | )
16 | : Scaffold(
17 | appBar: AppBar(
18 | title: Text('home.title'.tr),
19 | actions: [
20 | IconButton(
21 | icon: Icon(Icons.settings),
22 | onPressed: () {
23 | Get.to(SettingsUI());
24 | }),
25 | ],
26 | ),
27 | body: Center(
28 | child: Column(
29 | children: [
30 | SizedBox(height: 120),
31 | Avatar(controller.firestoreUser.value!),
32 | Column(
33 | mainAxisAlignment: MainAxisAlignment.start,
34 | crossAxisAlignment: CrossAxisAlignment.start,
35 | children: [
36 | FormVerticalSpace(),
37 | Text(
38 | 'home.uidLabel'.tr +
39 | ': ' +
40 | controller.firestoreUser.value!.uid,
41 | style: TextStyle(fontSize: 16)),
42 | FormVerticalSpace(),
43 | Text(
44 | 'home.nameLabel'.tr +
45 | ': ' +
46 | controller.firestoreUser.value!.name,
47 | style: TextStyle(fontSize: 16)),
48 | FormVerticalSpace(),
49 | Text(
50 | 'home.emailLabel'.tr +
51 | ': ' +
52 | controller.firestoreUser.value!.email,
53 | style: TextStyle(fontSize: 16)),
54 | FormVerticalSpace(),
55 | Text(
56 | 'home.adminUserLabel'.tr +
57 | ': ' +
58 | controller.admin.value.toString(),
59 | style: TextStyle(fontSize: 16)),
60 | ],
61 | ),
62 | ],
63 | ),
64 | ),
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/ui/settings_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:flutter_starter/ui/auth/auth.dart';
4 | import 'package:get/get.dart';
5 | import 'package:flutter_starter/ui/components/segmented_selector.dart';
6 | import 'package:flutter_starter/controllers/controllers.dart';
7 | import 'package:flutter_starter/ui/components/components.dart';
8 | import 'package:flutter_starter/models/models.dart';
9 | import 'package:flutter_starter/constants/constants.dart';
10 |
11 | class SettingsUI extends StatelessWidget {
12 | //final LanguageController languageController = LanguageController.to;
13 | //final ThemeController themeController = ThemeController.to;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | appBar: AppBar(
19 | title: Text('settings.title'.tr),
20 | ),
21 | body: _buildLayoutSection(context),
22 | );
23 | }
24 |
25 | Widget _buildLayoutSection(BuildContext context) {
26 | return ListView(
27 | children: [
28 | languageListTile(context),
29 | themeListTile(context),
30 | ListTile(
31 | title: Text('settings.updateProfile'.tr),
32 | trailing: ElevatedButton(
33 | onPressed: () async {
34 | Get.to(UpdateProfileUI());
35 | },
36 | child: Text(
37 | 'settings.updateProfile'.tr,
38 | ),
39 | )),
40 | ListTile(
41 | title: Text('settings.signOut'.tr),
42 | trailing: ElevatedButton(
43 | onPressed: () {
44 | AuthController.to.signOut();
45 | },
46 | child: Text(
47 | 'settings.signOut'.tr,
48 | ),
49 | ),
50 | )
51 | ],
52 | );
53 | }
54 |
55 | languageListTile(BuildContext context) {
56 | return GetBuilder(
57 | builder: (controller) => ListTile(
58 | title: Text('settings.language'.tr),
59 | trailing: DropdownPicker(
60 | menuOptions: Globals.languageOptions,
61 | selectedOption: controller.currentLanguage,
62 | onChanged: (value) async {
63 | await controller.updateLanguage(value!);
64 | Get.forceAppUpdate();
65 | },
66 | ),
67 | ),
68 | );
69 | }
70 |
71 | themeListTile(BuildContext context) {
72 | final List themeOptions = [
73 | MenuOptionsModel(
74 | key: "system", value: 'settings.system'.tr, icon: Icons.brightness_4),
75 | MenuOptionsModel(
76 | key: "light", value: 'settings.light'.tr, icon: Icons.brightness_low),
77 | MenuOptionsModel(
78 | key: "dark", value: 'settings.dark'.tr, icon: Icons.brightness_3)
79 | ];
80 | return GetBuilder(
81 | builder: (controller) => ListTile(
82 | title: Text('settings.theme'.tr),
83 | trailing: SegmentedSelector(
84 | selectedOption: controller.currentTheme,
85 | menuOptions: themeOptions,
86 | onValueChanged: (value) {
87 | controller.setThemeMode(value);
88 | },
89 | ),
90 | ),
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/ui/splash_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SplashUI extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Scaffold(
7 | body: Container(
8 | child: Center(
9 | child: CircularProgressIndicator(),
10 | ),
11 | ),
12 | );
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/ui/ui.dart:
--------------------------------------------------------------------------------
1 | export 'home_ui.dart';
2 | export 'settings_ui.dart';
3 | export 'splash_ui.dart';
4 |
--------------------------------------------------------------------------------
/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.9.0"
11 | characters:
12 | dependency: transitive
13 | description:
14 | name: characters
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.2.0"
18 | charcode:
19 | dependency: transitive
20 | description:
21 | name: charcode
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.2.0"
25 | clock:
26 | dependency: transitive
27 | description:
28 | name: clock
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.1.0"
32 | cloud_firestore:
33 | dependency: "direct main"
34 | description:
35 | name: cloud_firestore
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.0.4"
39 | cloud_firestore_platform_interface:
40 | dependency: transitive
41 | description:
42 | name: cloud_firestore_platform_interface
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "4.0.1"
46 | cloud_firestore_web:
47 | dependency: transitive
48 | description:
49 | name: cloud_firestore_web
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.0.4"
53 | collection:
54 | dependency: transitive
55 | description:
56 | name: collection
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "1.16.0"
60 | crypto:
61 | dependency: "direct main"
62 | description:
63 | name: crypto
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "3.0.1"
67 | csv:
68 | dependency: "direct main"
69 | description:
70 | name: csv
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "5.0.0"
74 | cupertino_icons:
75 | dependency: "direct main"
76 | description:
77 | name: cupertino_icons
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "0.1.3"
81 | ffi:
82 | dependency: transitive
83 | description:
84 | name: ffi
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "1.0.0"
88 | file:
89 | dependency: transitive
90 | description:
91 | name: file
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "6.0.0"
95 | firebase_auth:
96 | dependency: "direct main"
97 | description:
98 | name: firebase_auth
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "1.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: "4.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: "1.0.4"
116 | firebase_core:
117 | dependency: "direct main"
118 | description:
119 | name: firebase_core
120 | url: "https://pub.dartlang.org"
121 | source: hosted
122 | version: "1.0.3"
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.0"
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.0.2"
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_web_plugins:
148 | dependency: transitive
149 | description: flutter
150 | source: sdk
151 | version: "0.0.0"
152 | get:
153 | dependency: "direct main"
154 | description:
155 | name: get
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "4.1.3"
159 | get_storage:
160 | dependency: "direct main"
161 | description:
162 | name: get_storage
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "2.0.2"
166 | http:
167 | dependency: "direct main"
168 | description:
169 | name: http
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "0.13.5"
173 | http_parser:
174 | dependency: transitive
175 | description:
176 | name: http_parser
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "4.0.0"
180 | intl:
181 | dependency: transitive
182 | description:
183 | name: intl
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "0.17.0"
187 | js:
188 | dependency: transitive
189 | description:
190 | name: js
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "0.6.4"
194 | material_color_utilities:
195 | dependency: transitive
196 | description:
197 | name: material_color_utilities
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "0.1.4"
201 | meta:
202 | dependency: transitive
203 | description:
204 | name: meta
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "1.7.0"
208 | path:
209 | dependency: transitive
210 | description:
211 | name: path
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "1.8.1"
215 | path_provider:
216 | dependency: transitive
217 | description:
218 | name: path_provider
219 | url: "https://pub.dartlang.org"
220 | source: hosted
221 | version: "2.0.1"
222 | path_provider_linux:
223 | dependency: transitive
224 | description:
225 | name: path_provider_linux
226 | url: "https://pub.dartlang.org"
227 | source: hosted
228 | version: "2.0.0"
229 | path_provider_macos:
230 | dependency: transitive
231 | description:
232 | name: path_provider_macos
233 | url: "https://pub.dartlang.org"
234 | source: hosted
235 | version: "2.0.0"
236 | path_provider_platform_interface:
237 | dependency: transitive
238 | description:
239 | name: path_provider_platform_interface
240 | url: "https://pub.dartlang.org"
241 | source: hosted
242 | version: "2.0.1"
243 | path_provider_windows:
244 | dependency: transitive
245 | description:
246 | name: path_provider_windows
247 | url: "https://pub.dartlang.org"
248 | source: hosted
249 | version: "2.0.0"
250 | platform:
251 | dependency: transitive
252 | description:
253 | name: platform
254 | url: "https://pub.dartlang.org"
255 | source: hosted
256 | version: "3.0.0"
257 | plugin_platform_interface:
258 | dependency: transitive
259 | description:
260 | name: plugin_platform_interface
261 | url: "https://pub.dartlang.org"
262 | source: hosted
263 | version: "2.0.0"
264 | process:
265 | dependency: transitive
266 | description:
267 | name: process
268 | url: "https://pub.dartlang.org"
269 | source: hosted
270 | version: "4.0.0"
271 | sky_engine:
272 | dependency: transitive
273 | description: flutter
274 | source: sdk
275 | version: "0.0.99"
276 | source_span:
277 | dependency: transitive
278 | description:
279 | name: source_span
280 | url: "https://pub.dartlang.org"
281 | source: hosted
282 | version: "1.8.1"
283 | string_scanner:
284 | dependency: transitive
285 | description:
286 | name: string_scanner
287 | url: "https://pub.dartlang.org"
288 | source: hosted
289 | version: "1.1.0"
290 | term_glyph:
291 | dependency: transitive
292 | description:
293 | name: term_glyph
294 | url: "https://pub.dartlang.org"
295 | source: hosted
296 | version: "1.2.0"
297 | typed_data:
298 | dependency: transitive
299 | description:
300 | name: typed_data
301 | url: "https://pub.dartlang.org"
302 | source: hosted
303 | version: "1.3.0"
304 | vector_math:
305 | dependency: transitive
306 | description:
307 | name: vector_math
308 | url: "https://pub.dartlang.org"
309 | source: hosted
310 | version: "2.1.2"
311 | win32:
312 | dependency: transitive
313 | description:
314 | name: win32
315 | url: "https://pub.dartlang.org"
316 | source: hosted
317 | version: "2.0.5"
318 | xdg_directories:
319 | dependency: transitive
320 | description:
321 | name: xdg_directories
322 | url: "https://pub.dartlang.org"
323 | source: hosted
324 | version: "0.2.0"
325 | sdks:
326 | dart: ">=2.17.0-0 <3.0.0"
327 | flutter: ">=1.20.0"
328 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_starter
2 | description: A new Flutter project.
3 |
4 | version: 2.0.0
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 | flutter_localizations:
13 | sdk: flutter
14 | cupertino_icons:
15 | firebase_core: ^1.0.3
16 | # firebase_analytics: ^7.1.1 no nullsafe... skip it for now
17 | firebase_auth: ^1.0.2
18 | cloud_firestore: ^1.0.4
19 |
20 | # google_sign_in:
21 | # apple_sign_in:
22 | get: ^4.1.3
23 | get_storage: ^2.0.2
24 |
25 | crypto: ^3.0.1
26 | http: ^0.13.5
27 | csv: ^5.0.0
28 |
29 | dependency_overrides:
30 | # analyzer: 1.4.0
31 | # intl: 0.17.0
32 |
33 | dev_dependencies:
34 |
35 | flutter:
36 | uses-material-design: true
37 | assets:
38 | - assets/images/default.png
39 | - assets/images/defaultDark.png
40 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delay/flutter_starter/4d3077eb4efbc850b93d69a28f461e761b0bf49a/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | flutter_starter
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
46 |
49 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flutter_starter",
3 | "short_name": "flutter_starter",
4 | "start_url": ".",
5 | "display": "minimal-ui",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------