├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── 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-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── project.pbxproj
└── .gitignore
├── media
├── flavor-step-1.png
├── flavor-step-1b.png
├── flavor-step-2.png
├── flavor-step-3.png
├── flavor-step-4.png
├── flavor-step-4b.png
├── flavor-step-5.png
├── flavor-step-5b.png
├── how-to-use-step2.png
├── how-to-use-step4a.png
├── how-to-use-step4b.png
├── how-to-use-step5.png
├── how-to-use-step6.png
├── how-to-use-step7.png
├── how-to-use-step8.png
├── how-to-use-step9.png
├── language_control.gif
└── todo-app-screenshots.png
├── assets
├── fonts
│ ├── Product-Sans-Bold.ttf
│ ├── Product-Sans-Italic.ttf
│ ├── Product-Sans-Regular.ttf
│ └── Product-Sans-Bold-Italic.ttf
└── lang
│ ├── zh.json
│ └── en.json
├── android
├── gradle.properties
├── .gitignore
├── app
│ ├── src
│ │ ├── dev
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ └── strings.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
│ │ │ └── google-services.json
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.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
│ │ │ │ └── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── venturearkstudio
│ │ │ │ │ └── noteapp
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── prod
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ └── strings.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
│ │ │ └── google-services.json
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── build.gradle
├── lib
├── constants
│ ├── app_font_family.dart
│ └── app_themes.dart
├── flavor.dart
├── models
│ ├── user_model.dart
│ └── todo_model.dart
├── ui
│ ├── home
│ │ └── home.dart
│ ├── todo
│ │ ├── empty_content.dart
│ │ ├── todos_extra_actions.dart
│ │ ├── create_edit_todo_screen.dart
│ │ └── todos_screen.dart
│ ├── splash
│ │ └── splash_screen.dart
│ ├── setting
│ │ ├── setting_language_actions.dart
│ │ └── setting_screen.dart
│ └── auth
│ │ ├── register_screen.dart
│ │ └── sign_in_screen.dart
├── services
│ ├── firestore_path.dart
│ ├── firestore_service.dart
│ └── firestore_database.dart
├── providers
│ ├── theme_provider.dart
│ ├── language_provider.dart
│ └── auth_provider.dart
├── caches
│ └── sharedpref
│ │ └── shared_preference_helper.dart
├── routes.dart
├── main.dart
├── main_prod.dart
├── auth_widget_builder.dart
├── app_localizations.dart
└── my_app.dart
├── .metadata
├── .gitignore
├── LICENSE.md
├── pubspec.yaml
├── pubspec.lock
└── README.md
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/media/flavor-step-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-1.png
--------------------------------------------------------------------------------
/media/flavor-step-1b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-1b.png
--------------------------------------------------------------------------------
/media/flavor-step-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-2.png
--------------------------------------------------------------------------------
/media/flavor-step-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-3.png
--------------------------------------------------------------------------------
/media/flavor-step-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-4.png
--------------------------------------------------------------------------------
/media/flavor-step-4b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-4b.png
--------------------------------------------------------------------------------
/media/flavor-step-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-5.png
--------------------------------------------------------------------------------
/media/flavor-step-5b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/flavor-step-5b.png
--------------------------------------------------------------------------------
/media/how-to-use-step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step2.png
--------------------------------------------------------------------------------
/media/how-to-use-step4a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step4a.png
--------------------------------------------------------------------------------
/media/how-to-use-step4b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step4b.png
--------------------------------------------------------------------------------
/media/how-to-use-step5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step5.png
--------------------------------------------------------------------------------
/media/how-to-use-step6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step6.png
--------------------------------------------------------------------------------
/media/how-to-use-step7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step7.png
--------------------------------------------------------------------------------
/media/how-to-use-step8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step8.png
--------------------------------------------------------------------------------
/media/how-to-use-step9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/how-to-use-step9.png
--------------------------------------------------------------------------------
/media/language_control.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/language_control.gif
--------------------------------------------------------------------------------
/media/todo-app-screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/media/todo-app-screenshots.png
--------------------------------------------------------------------------------
/assets/fonts/Product-Sans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/assets/fonts/Product-Sans-Bold.ttf
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/assets/fonts/Product-Sans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/assets/fonts/Product-Sans-Italic.ttf
--------------------------------------------------------------------------------
/assets/fonts/Product-Sans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/assets/fonts/Product-Sans-Regular.ttf
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/assets/fonts/Product-Sans-Bold-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/assets/fonts/Product-Sans-Bold-Italic.ttf
--------------------------------------------------------------------------------
/android/app/src/dev/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Note-Dev
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Default App Name
4 |
--------------------------------------------------------------------------------
/android/app/src/prod/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Note-Prod
4 |
--------------------------------------------------------------------------------
/android/app/src/dev/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/dev/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/dev/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/dev/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/dev/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/dev/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/prod/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/prod/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/prod/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/prod/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/constants/app_font_family.dart:
--------------------------------------------------------------------------------
1 | class AppFontFamily{
2 | AppFontFamily._();
3 |
4 | static String productSans = "ProductSans";
5 | static String roboto = "Roboto";
6 | }
--------------------------------------------------------------------------------
/android/app/src/dev/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/dev/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/dev/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/dev/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/prod/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/prod/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/prod/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/prod/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/prod/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/android/app/src/prod/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/flavor.dart:
--------------------------------------------------------------------------------
1 | /*
2 | Available commands:
3 |
4 | flutter run --flavor dev -t lib/main.dart
5 | flutter run --flavor prod -t lib/main_prod.dart
6 | */
7 |
8 | enum Flavor {dev, prod}
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/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/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KenAragorn/create_flutter_provider_app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/models/user_model.dart:
--------------------------------------------------------------------------------
1 | class UserModel {
2 | String uid;
3 | String? email;
4 | String? displayName;
5 | String? phoneNumber;
6 | String? photoUrl;
7 |
8 | UserModel(
9 | {required this.uid,
10 | this.email,
11 | this.displayName,
12 | this.phoneNumber,
13 | this.photoUrl});
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 0b8abb4724aa590dd0f429683339b1e045a1594d
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/ui/home/home.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/ui/splash/splash_screen.dart';
3 |
4 | class HomeScreen extends StatefulWidget {
5 | @override
6 | _HomeScreenState createState() => _HomeScreenState();
7 | }
8 |
9 | class _HomeScreenState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return SplashScreen();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/services/firestore_path.dart:
--------------------------------------------------------------------------------
1 | /*
2 | This class defines all the possible read/write locations from the FirebaseFirestore database.
3 | In future, any new path can be added here.
4 | This class work together with FirestoreService and FirestoreDatabase.
5 | */
6 |
7 | class FirestorePath {
8 | static String todo(String uid, String todoId) => 'users/$uid/todos/$todoId';
9 | static String todos(String uid) => 'users/$uid/todos';
10 | }
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/venturearkstudio/noteapp/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.venturearkstudio.noteapp
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/ui/todo/empty_content.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class EmptyContentWidget extends StatelessWidget {
4 | final String title;
5 | final String message;
6 |
7 | EmptyContentWidget(
8 | {required Key key,
9 | required this.title,
10 | required this.message})
11 | : super(key: key);
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Center(
16 | child: Column(
17 | mainAxisAlignment: MainAxisAlignment.center,
18 | children: [
19 | Text(title),
20 | Text(message),
21 | ],
22 | ),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 | /android/app/google-services.json
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Exceptions to above rules.
38 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
39 |
--------------------------------------------------------------------------------
/lib/models/todo_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:meta/meta.dart';
2 |
3 | class TodoModel {
4 | final String id;
5 | final String task;
6 | final String extraNote;
7 | final bool complete;
8 |
9 | TodoModel(
10 | {required this.id,
11 | required this.task,
12 | required this.extraNote,
13 | required this.complete});
14 |
15 | factory TodoModel.fromMap(Map data, String documentId) {
16 | String task = data['task'];
17 | String extraNote = data['extraNote'];
18 | bool complete = data['complete'];
19 |
20 | return TodoModel(
21 | id: documentId, task: task, extraNote: extraNote, complete: complete);
22 | }
23 |
24 | Map toMap() {
25 | return {
26 | 'task': task,
27 | 'extraNote': extraNote,
28 | 'complete': complete,
29 | };
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/providers/theme_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/caches/sharedpref/shared_preference_helper.dart';
3 |
4 | class ThemeProvider extends ChangeNotifier {
5 | // shared pref object
6 | late SharedPreferenceHelper _sharedPrefsHelper;
7 |
8 | bool _isDarkModeOn = false;
9 |
10 | ThemeProvider() {
11 | _sharedPrefsHelper = SharedPreferenceHelper();
12 | }
13 |
14 | bool get isDarkModeOn {
15 | _sharedPrefsHelper.isDarkMode.then((statusValue) {
16 | _isDarkModeOn = statusValue;
17 | });
18 |
19 | return _isDarkModeOn;
20 | }
21 |
22 | void updateTheme(bool isDarkModeOn) {
23 | _sharedPrefsHelper.changeTheme(isDarkModeOn);
24 | _sharedPrefsHelper.isDarkMode.then((darkModeStatus) {
25 | _isDarkModeOn = darkModeStatus;
26 | });
27 |
28 | notifyListeners();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/providers/language_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/caches/sharedpref/shared_preference_helper.dart';
3 |
4 | class LanguageProvider extends ChangeNotifier {
5 | // shared pref object
6 | late SharedPreferenceHelper _sharedPrefsHelper;
7 |
8 | Locale _appLocale = Locale('en');
9 |
10 | LanguageProvider() {
11 | _sharedPrefsHelper = SharedPreferenceHelper();
12 | }
13 |
14 | Locale get appLocale {
15 | _sharedPrefsHelper.appLocale?.then((localeValue) {
16 | _appLocale = Locale(localeValue);
17 | });
18 |
19 | return _appLocale;
20 | }
21 |
22 | void updateLanguage(String languageCode) {
23 | if (languageCode == "zh") {
24 | _appLocale = Locale("zh");
25 | } else {
26 | _appLocale = Locale("en");
27 | }
28 |
29 | _sharedPrefsHelper.changeLanguage(languageCode);
30 | notifyListeners();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Ken Lee Chiaw Huat [kenaragorn@gmail.com](mailto:kenaragorn@gmail.com)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/lib/caches/sharedpref/shared_preference_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | class SharedPreferenceHelper {
4 | Future? _sharedPreference;
5 | static const String is_dark_mode = "is_dark_mode";
6 | static const String language_code = "language_code";
7 |
8 | SharedPreferenceHelper() {
9 | _sharedPreference = SharedPreferences.getInstance();
10 | }
11 |
12 | //Theme module
13 | Future changeTheme(bool value) {
14 | return _sharedPreference!.then((prefs) {
15 | return prefs.setBool(is_dark_mode, value);
16 | });
17 | }
18 |
19 | Future get isDarkMode {
20 | return _sharedPreference!.then((prefs) {
21 | return prefs.getBool(is_dark_mode) ?? false;
22 | });
23 | }
24 |
25 | //Locale module
26 | Future? get appLocale {
27 | return _sharedPreference?.then((prefs) {
28 | return prefs.getString(language_code) ?? 'en';
29 | });
30 | }
31 |
32 | Future changeLanguage(String value) {
33 | return _sharedPreference!.then((prefs) {
34 | return prefs.setString(language_code, value);
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/routes.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/ui/auth/register_screen.dart';
3 | import 'package:noteapp/ui/auth/sign_in_screen.dart';
4 | import 'package:noteapp/ui/setting/setting_screen.dart';
5 | import 'package:noteapp/ui/splash/splash_screen.dart';
6 | import 'package:noteapp/ui/todo/create_edit_todo_screen.dart';
7 | import 'package:noteapp/ui/todo/todos_screen.dart';
8 |
9 | class Routes {
10 | Routes._(); //this is to prevent anyone from instantiate this object
11 |
12 | static const String splash = '/splash';
13 | static const String login = '/login';
14 | static const String register = '/register';
15 | static const String home = '/home';
16 | static const String setting = '/setting';
17 | static const String create_edit_todo = '/create_edit_todo';
18 |
19 | static final routes = {
20 | splash: (BuildContext context) => SplashScreen(),
21 | login: (BuildContext context) => SignInScreen(),
22 | register: (BuildContext context) => RegisterScreen(),
23 | home: (BuildContext context) => TodosScreen(),
24 | setting: (BuildContext context) => SettingScreen(),
25 | create_edit_todo: (BuildContext context) => CreateEditTodoScreen(),
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/android/app/src/dev/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "747799024060",
4 | "firebase_url": "https://note-app-dev.firebaseio.com",
5 | "project_id": "note-app-dev",
6 | "storage_bucket": "note-app-dev.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:747799024060:android:12a44c09b32bf75c3d5bb9",
12 | "android_client_info": {
13 | "package_name": "com.example.create_flutter_provider_app.dev"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "747799024060-0i7261mp5tipeb817cpcr7s0cn29ck0a.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyA_mDikkCUSSDXiwFKly7GlC25LJEJHsFA"
25 | }
26 | ],
27 | "services": {
28 | "appinvite_service": {
29 | "other_platform_oauth_client": [
30 | {
31 | "client_id": "747799024060-0i7261mp5tipeb817cpcr7s0cn29ck0a.apps.googleusercontent.com",
32 | "client_type": 3
33 | }
34 | ]
35 | }
36 | }
37 | }
38 | ],
39 | "configuration_version": "1"
40 | }
--------------------------------------------------------------------------------
/android/app/src/prod/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "514413640785",
4 | "firebase_url": "https://note-app-prod-aa3d9.firebaseio.com",
5 | "project_id": "note-app-prod-aa3d9",
6 | "storage_bucket": "note-app-prod-aa3d9.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:514413640785:android:2a7848a3d2174f40098c70",
12 | "android_client_info": {
13 | "package_name": "com.example.create_flutter_provider_app.prod"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "514413640785-pb983pp7c9kdgthvq1vqp6q3fstqnusa.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyB9uzuxTzPD9HeR_h_I7yFoiQ8Nmo7Hirs"
25 | }
26 | ],
27 | "services": {
28 | "appinvite_service": {
29 | "other_platform_oauth_client": [
30 | {
31 | "client_id": "514413640785-pb983pp7c9kdgthvq1vqp6q3fstqnusa.apps.googleusercontent.com",
32 | "client_type": 3
33 | }
34 | ]
35 | }
36 | }
37 | }
38 | ],
39 | "configuration_version": "1"
40 | }
--------------------------------------------------------------------------------
/lib/ui/splash/splash_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'package:noteapp/app_localizations.dart';
4 | import 'package:noteapp/routes.dart';
5 |
6 | class SplashScreen extends StatefulWidget {
7 | @override
8 | _SplashScreenState createState() => _SplashScreenState();
9 | }
10 |
11 | class _SplashScreenState extends State {
12 | @override
13 | void initState() {
14 | super.initState();
15 | startTimer();
16 | }
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Scaffold(
21 | body: Center(
22 | child: Column(
23 | mainAxisAlignment: MainAxisAlignment.center,
24 | crossAxisAlignment: CrossAxisAlignment.stretch,
25 | children: [
26 | Center(
27 | child: Text(
28 | AppLocalizations.of(context).translate("splashTitle"),
29 | style: TextStyle(
30 | fontSize: Theme.of(context).textTheme.headline!.fontSize,
31 | ),
32 | )),
33 | FlutterLogo(
34 | size: 128,
35 | ),
36 | ],
37 | )));
38 | }
39 |
40 | startTimer() {
41 | var duration = Duration(milliseconds: 3000);
42 | return Timer(duration, redirect);
43 | }
44 |
45 | redirect() async {
46 | Navigator.of(context).pushReplacementNamed(Routes.home);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/ui/todo/todos_extra_actions.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/app_localizations.dart';
3 | import 'package:noteapp/services/firestore_database.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | enum TodosActions { toggleAllComplete, clearCompleted }
7 |
8 | class TodosExtraActions extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) {
11 | FirestoreDatabase firestoreDatabase = Provider.of(context);
12 |
13 | return PopupMenuButton(
14 | icon: Icon(Icons.more_horiz),
15 | onSelected: (TodosActions result) {
16 | switch (result) {
17 | case TodosActions.toggleAllComplete:
18 | firestoreDatabase.setAllTodoComplete();
19 | break;
20 | case TodosActions.clearCompleted:
21 | firestoreDatabase.deleteAllTodoWithComplete();
22 | }
23 | },
24 | itemBuilder: (BuildContext context) => >[
25 | PopupMenuItem(
26 | value: TodosActions.toggleAllComplete,
27 | child: Text(AppLocalizations.of(context)
28 | .translate("todosPopUpToggleAllComplete")),
29 | ),
30 | PopupMenuItem(
31 | value: TodosActions.clearCompleted,
32 | child: Text(AppLocalizations.of(context)
33 | .translate("todosPopUpToggleClearCompleted")),
34 | ),
35 | ],
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:noteapp/flavor.dart';
4 | import 'package:noteapp/my_app.dart';
5 | import 'package:noteapp/providers/auth_provider.dart';
6 | import 'package:noteapp/providers/language_provider.dart';
7 | import 'package:noteapp/providers/theme_provider.dart';
8 | import 'package:noteapp/services/firestore_database.dart';
9 | import 'package:provider/provider.dart';
10 |
11 | void main() {
12 | WidgetsFlutterBinding.ensureInitialized();
13 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
14 | .then((_) async {
15 | runApp(
16 | /*
17 | * MultiProvider for top services that do not depends on any runtime values
18 | * such as user uid/email.
19 | */
20 | MultiProvider(
21 | providers: [
22 | Provider.value(value: Flavor.dev),
23 | ChangeNotifierProvider(
24 | create: (context) => ThemeProvider(),
25 | ),
26 | ChangeNotifierProvider(
27 | create: (context) => AuthProvider(),
28 | ),
29 | ChangeNotifierProvider(
30 | create: (context) => LanguageProvider(),
31 | ),
32 | ],
33 | child: MyApp(
34 | databaseBuilder: (_, uid) => FirestoreDatabase(uid: uid),
35 | key: Key('MyApp'),
36 | ),
37 | ),
38 | );
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/lib/main_prod.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:noteapp/flavor.dart';
4 | import 'package:noteapp/my_app.dart';
5 | import 'package:noteapp/providers/auth_provider.dart';
6 | import 'package:noteapp/providers/language_provider.dart';
7 | import 'package:noteapp/providers/theme_provider.dart';
8 | import 'package:noteapp/services/firestore_database.dart';
9 | import 'package:provider/provider.dart';
10 |
11 | void main() {
12 | WidgetsFlutterBinding.ensureInitialized();
13 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
14 | .then((_) async {
15 | runApp(
16 | /*
17 | * MultiProvider for top services that do not depends on any runtime values
18 | * such as user uid/email.
19 | */
20 | MultiProvider(
21 | providers: [
22 | Provider.value(value: Flavor.prod),
23 | ChangeNotifierProvider(
24 | create: (context) => ThemeProvider(),
25 | ),
26 | ChangeNotifierProvider(
27 | create: (context) => AuthProvider(),
28 | ),
29 | ChangeNotifierProvider(
30 | create: (context) => LanguageProvider(),
31 | ),
32 | ],
33 | child: MyApp(
34 | databaseBuilder: (_, uid) => FirestoreDatabase(uid: uid),
35 | key: Key('SimpleFinance'),
36 | ),
37 | ),
38 | );
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/lib/ui/setting/setting_language_actions.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/app_localizations.dart';
3 | import 'package:noteapp/providers/language_provider.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | enum LanguagesActions { english, chinese }
7 |
8 | class SettingLanguageActions extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) {
11 | LanguageProvider languageProvider = Provider.of(context);
12 | Locale _appCurrentLocale = languageProvider.appLocale;
13 |
14 | return PopupMenuButton(
15 | icon: Icon(Icons.language),
16 | onSelected: (LanguagesActions result) {
17 | switch (result) {
18 | case LanguagesActions.english:
19 | languageProvider.updateLanguage("en");
20 | break;
21 | case LanguagesActions.chinese:
22 | languageProvider.updateLanguage("zh");
23 | }
24 | },
25 | itemBuilder: (BuildContext context) => >[
26 | PopupMenuItem(
27 | value: LanguagesActions.english,
28 | enabled: _appCurrentLocale == Locale("en") ? false : true,
29 | child: Text(AppLocalizations.of(context)
30 | .translate("settingPopUpToggleEnglish")),
31 | ),
32 | PopupMenuItem(
33 | value: LanguagesActions.chinese,
34 | enabled: _appCurrentLocale == Locale("zh") ? false : true,
35 | child: Text(AppLocalizations.of(context)
36 | .translate("settingPopUpToggleChinese")),
37 | ),
38 | ],
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/assets/lang/zh.json:
--------------------------------------------------------------------------------
1 | {
2 | "splashTitle": "欢迎来到 ",
3 | "alertDialogTitle": "警报",
4 | "alertDialogMessage": "这将注销。 你确定吗?",
5 | "alertDialogCancelBtn": "取消",
6 | "alertDialogYesBtn": "是",
7 | "loginTxtEmail": "电子邮件",
8 | "loginTxtPassword": "密码",
9 | "loginBtnSignIn": "登入",
10 | "loginBtnSignUp": "注册",
11 | "loginTxtDontHaveAccount": "还没有帐号?",
12 | "loginTxtHaveAccount": "已经有帐号了?",
13 | "loginBtnLinkCreateAccount": "创建帐号",
14 | "loginBtnLinkSignIn": "登入",
15 | "loginTxtErrorEmail": "请输入电子邮件",
16 | "loginTxtErrorPassword": "请输入超过6个字符的密码",
17 | "loginTxtErrorSignIn": "无效的电子邮件和/或密码",
18 | "homeAppBarTitle": "全部",
19 | "settingAppTitle": "设置",
20 | "settingThemeListTitle": "黑暗主题",
21 | "settingThemeListSubTitle": "打开黑暗的一面",
22 | "settingLogoutListTitle": "登出",
23 | "settingLogoutListSubTitle": "从这里注销我",
24 | "settingLogoutButton": "登出",
25 | "settingLanguageListTitle": "语言",
26 | "settingLanguageListSubTitle": "设定您的偏好语言",
27 | "settingPopUpToggleEnglish": "改成英文",
28 | "settingPopUpToggleChinese": "改成中文",
29 | "todosSnackBarContent": "已删除 ",
30 | "todosSnackBarActionLbl": "撤消",
31 | "todosErrorTopMsgTxt": "出问题了",
32 | "todosErrorBottomMsgTxt": "现在无法加载数据",
33 | "todosDismissibleMsgTxt": "删除",
34 | "todosPopUpToggleAllComplete": "标记所有完成",
35 | "todosPopUpToggleClearCompleted": "清除所有已完成",
36 | "todosCreateEditAppBarTitleNewTxt": "新渡渡鸟",
37 | "todosCreateEditAppBarTitleEditTxt": "编辑一切",
38 | "todosCreateEditTaskNameTxt": "待办事项名称",
39 | "todosCreateEditNotesTxt": "笔记",
40 | "todosCreateEditTaskNameValidatorMsg": "名称不能为空",
41 | "todosCreateEditCompletedTxt": "完成了吗 ?",
42 | "todosEmptyTopMsgDefaultTxt": "这里没有什么",
43 | "todosEmptyBottomDefaultMsgTxt": "添加新项目以开始"
44 | }
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | noteapp
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/assets/lang/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "splashTitle": "Welcome to ",
3 | "alertDialogTitle": "Alert",
4 | "alertDialogMessage": "This will logout. Are you sure?",
5 | "alertDialogCancelBtn": "Cancel",
6 | "alertDialogYesBtn": "Yes",
7 | "loginTxtEmail": "Email",
8 | "loginTxtPassword": "Password",
9 | "loginBtnSignIn": "Sign In",
10 | "loginBtnSignUp": "Sign Up",
11 | "loginTxtDontHaveAccount": "Don't have an account?",
12 | "loginTxtHaveAccount": "Already have an account?",
13 | "loginBtnLinkCreateAccount": "Create account",
14 | "loginBtnLinkSignIn": "Sign in",
15 | "loginTxtErrorEmail": "Please enter an email",
16 | "loginTxtErrorPassword": "Please enter a password with 6+ chars long",
17 | "loginTxtErrorSignIn": "Invalid email and/or password",
18 | "homeAppBarTitle": "Todos",
19 | "settingAppTitle": "Setting",
20 | "settingThemeListTitle": "Dark theme",
21 | "settingThemeListSubTitle": "Turn On the Dark Side",
22 | "settingLogoutListTitle": "Logout",
23 | "settingLogoutListSubTitle": "Log me out from here",
24 | "settingLogoutButton": "Logout",
25 | "settingLanguageListTitle": "Language",
26 | "settingLanguageListSubTitle": "Set Your Prefer Language",
27 | "settingPopUpToggleEnglish": "Change to English",
28 | "settingPopUpToggleChinese": "Change to Chinese",
29 | "todosSnackBarContent": "Deleted ",
30 | "todosSnackBarActionLbl": "Undo",
31 | "todosErrorTopMsgTxt": "Something went wrong",
32 | "todosErrorBottomMsgTxt": "Can't load data right now",
33 | "todosDismissibleMsgTxt": "Delete",
34 | "todosPopUpToggleAllComplete": "Mark all complete",
35 | "todosPopUpToggleClearCompleted": "Clear all completed",
36 | "todosCreateEditAppBarTitleNewTxt": "New Todo",
37 | "todosCreateEditAppBarTitleEditTxt": "Edit Todo",
38 | "todosCreateEditTaskNameTxt": "Todo Name",
39 | "todosCreateEditNotesTxt": "Notes",
40 | "todosCreateEditTaskNameValidatorMsg": "Name can't be empty",
41 | "todosCreateEditCompletedTxt": "Completed ?",
42 | "todosEmptyTopMsgDefaultTxt": "Nothing here",
43 | "todosEmptyBottomDefaultMsgTxt": "Add a new item to get started"
44 | }
--------------------------------------------------------------------------------
/lib/auth_widget_builder.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:noteapp/models/user_model.dart';
3 | import 'package:noteapp/providers/auth_provider.dart';
4 | import 'package:noteapp/services/firestore_database.dart';
5 | import 'package:provider/provider.dart';
6 |
7 | /*
8 | * This class is mainly to help with creating user dependent object that
9 | * need to be available by all downstream widgets.
10 | * Thus, this widget builder is a must to live above [MaterialApp].
11 | * As we rely on uid to decide which main screen to display (eg: Home or Sign In),
12 | * this class will helps to create all providers needed that depends on
13 | * the user logged data uid.
14 | */
15 | class AuthWidgetBuilder extends StatelessWidget {
16 | const AuthWidgetBuilder(
17 | {required Key key, required this.builder, required this.databaseBuilder})
18 | : super(key: key);
19 | final Widget Function(BuildContext, AsyncSnapshot) builder;
20 | final FirestoreDatabase Function(BuildContext context, String uid)
21 | databaseBuilder;
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | final authService = Provider.of(context, listen: false);
26 | return StreamBuilder(
27 | stream: authService.user,
28 | builder: (BuildContext context, AsyncSnapshot snapshot) {
29 | final UserModel? user = snapshot.data;
30 | if (user != null) {
31 | /*
32 | * For any other Provider services that rely on user data can be
33 | * added to the following MultiProvider list.
34 | * Once a user has been detected, a re-build will be initiated.
35 | */
36 | return MultiProvider(
37 | providers: [
38 | Provider.value(value: user),
39 | Provider(
40 | create: (context) => databaseBuilder(context, user.uid),
41 | ),
42 | ],
43 | child: builder(context, snapshot),
44 | );
45 | }
46 | return builder(context, snapshot);
47 | },
48 | );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/app_localizations.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/services.dart';
6 |
7 | class AppLocalizations {
8 | final Locale locale;
9 |
10 | AppLocalizations(this.locale);
11 |
12 | // Helper method to keep the code in the widgets concise
13 | // Localizations are accessed using an InheritedWidget "of" syntax
14 | static AppLocalizations of(BuildContext context) {
15 | return Localizations.of(context, AppLocalizations)!;
16 | }
17 |
18 | //This is the static member for allowing simple access to the delegate from the MaterialApp
19 | static const LocalizationsDelegate delegate =
20 | _AppLocalizationsDelegate();
21 |
22 | Map _localizedStrings = Map();
23 |
24 | Future load() async {
25 | // Load the language JSON file from the "lang" folder
26 | String jsonString =
27 | await rootBundle.loadString('lang/${locale.languageCode}.json');
28 | Map jsonMap = json.decode(jsonString);
29 |
30 | _localizedStrings = jsonMap.map((key, value) {
31 | return MapEntry(key, value.toString());
32 | });
33 |
34 | return true;
35 | }
36 |
37 | // This method will be called from every widgets which needs a localized text
38 | String translate(String key) {
39 | return _localizedStrings[key] ?? key;
40 | }
41 | }
42 |
43 | // LocalizationsDelegate is a factory for a set of localized resources
44 | // In this case, the localized strings will be gotten in an AppLocalizations object
45 | class _AppLocalizationsDelegate
46 | extends LocalizationsDelegate {
47 | const _AppLocalizationsDelegate();
48 |
49 | @override
50 | bool isSupported(Locale locale) {
51 | // Include all of your supported language codes here
52 | return ['en', 'zh'].contains(locale.languageCode);
53 | }
54 |
55 | @override
56 | Future load(Locale locale) async {
57 | // AppLocalizations class is where the JSON loading actually runs
58 | AppLocalizations localizations = new AppLocalizations(locale);
59 | await localizations.load();
60 | return localizations;
61 | }
62 |
63 | @override
64 | bool shouldReload(_AppLocalizationsDelegate old) => false;
65 | }
66 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/services/firestore_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:cloud_firestore/cloud_firestore.dart';
2 |
3 | /*
4 | This class represent all possible CRUD operation for FirebaseFirestore.
5 | It contains all generic implementation needed based on the provided document
6 | path and documentID,since most of the time in FirebaseFirestore design, we will have
7 | documentID and path for any document and collections.
8 | */
9 | class FirestoreService {
10 | FirestoreService._();
11 | static final instance = FirestoreService._();
12 |
13 | Future set({
14 | required String path,
15 | required Map data,
16 | bool merge = false,
17 | }) async {
18 | final reference = FirebaseFirestore.instance.doc(path);
19 | print('$path: $data');
20 | await reference.set(data);
21 | }
22 |
23 | Future bulkSet({
24 | required String path,
25 | required List