├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ ├── google-services.json │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── todo_app │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── debug.keystore ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── key.jks ├── key.properties └── settings.gradle ├── assets └── logo.png ├── fonts └── Poppins │ ├── Poppins-Light.ttf │ ├── Poppins-Medium.ttf │ └── Poppins-Regular.ttf ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ └── contents.xcworkspacedata └── Runner │ ├── AppDelegate.swift │ ├── AppIcon.appiconset │ ├── 1024.png │ ├── 114.png │ ├── 120.png │ ├── 180.png │ ├── 29.png │ ├── 40.png │ ├── 57.png │ ├── 58.png │ ├── 60.png │ ├── 80.png │ ├── 87.png │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── main.dart └── src │ ├── bloc_delegate.dart │ ├── core │ ├── constants │ │ └── Constants.dart │ ├── error │ │ ├── exceptions.dart │ │ └── failure.dart │ ├── priority │ │ └── Priority.dart │ └── user │ │ └── user.dart │ ├── features │ └── todo_manager_features │ │ ├── data │ │ ├── datasources │ │ │ ├── auth_service.dart │ │ │ └── firestore_interactions.dart │ │ ├── models │ │ │ ├── ListModel.dart │ │ │ ├── ListTodoModel.dart │ │ │ └── QuickNoteModel.dart │ │ └── repositories │ │ │ ├── auth_repository_impl.dart │ │ │ └── todo_manager_repository_impl.dart │ │ ├── domain │ │ ├── entities │ │ │ ├── List.dart │ │ │ ├── ListTodo.dart │ │ │ └── QuickNote.dart │ │ ├── repositories │ │ │ ├── auth_repository.dart │ │ │ └── todo_manager_repository.dart │ │ └── usecases │ │ │ ├── add_list.dart │ │ │ ├── add_quick_note.dart │ │ │ ├── dashboard_use_cases.dart │ │ │ ├── edit_list.dart │ │ │ ├── edit_list_todo.dart │ │ │ └── edit_quick_note.dart │ │ └── presentation │ │ ├── bloc │ │ ├── add_list_bloc │ │ │ ├── add_list_bloc.dart │ │ │ ├── add_list_event.dart │ │ │ └── add_list_state.dart │ │ ├── add_quick_note_bloc │ │ │ ├── add_quick_note_bloc.dart │ │ │ ├── add_quick_note_event.dart │ │ │ └── add_quick_note_state.dart │ │ ├── auth_bloc │ │ │ ├── auth_bloc.dart │ │ │ ├── auth_event.dart │ │ │ └── auth_state.dart │ │ ├── dashboard_bloc │ │ │ ├── dashboard_bloc.dart │ │ │ ├── dashboard_event.dart │ │ │ └── dashboard_state.dart │ │ └── login_bloc │ │ │ ├── login_bloc.dart │ │ │ ├── login_event.dart │ │ │ └── login_state.dart │ │ ├── pages │ │ ├── Dashboard.dart │ │ ├── Login.dart │ │ ├── add_new_list.dart │ │ └── add_quick_note.dart │ │ └── widgets │ │ ├── all_lists.dart │ │ ├── all_quick_notes.dart │ │ ├── color_picker_button.dart │ │ ├── list_bottom_sheet.dart │ │ ├── list_todo_widget.dart │ │ ├── list_widget.dart │ │ ├── menu_icon.dart │ │ ├── no_widget.dart │ │ ├── quick_note_widget.dart │ │ ├── select_priority_button.dart │ │ ├── slide_animation_provider.dart │ │ ├── small_button.dart │ │ └── suggestion_tile.dart │ └── injection_container.dart ├── pubspec.lock ├── pubspec.yaml ├── screenshots ├── first.png ├── fourth.png ├── second.png └── third.png └── test └── widget_test.dart /.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 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | -------------------------------------------------------------------------------- /.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: 27321ebbad34b0a3fafe99fac037102196d655ff 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Flutter", 9 | "request": "launch", 10 | "type": "dart" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Todo_app 2 | 3 | A todo app built with flutter and firebase 4 | 5 |

6 | 7 | 8 | 9 | 10 |

11 | Design Credit 12 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | def keystoreProperties = new Properties() 29 | def keystorePropertiesFile = rootProject.file('key.properties') 30 | if (keystorePropertiesFile.exists()) { 31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 32 | } 33 | 34 | 35 | 36 | android { 37 | compileSdkVersion 28 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | lintOptions { 44 | disable 'InvalidPackage' 45 | } 46 | 47 | defaultConfig { 48 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 49 | multiDexEnabled true 50 | applicationId "com.example.todo_app" 51 | minSdkVersion 16 52 | targetSdkVersion 28 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 56 | } 57 | 58 | signingConfigs { 59 | release { 60 | keyAlias keystoreProperties['keyAlias'] 61 | keyPassword keystoreProperties['keyPassword'] 62 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 63 | storePassword keystoreProperties['storePassword'] 64 | } 65 | } 66 | buildTypes { 67 | release { 68 | // TODO: Add your own signing config for the release build. 69 | // Signing with the debug keys for now, so `flutter run --release` works. 70 | signingConfig signingConfigs.debug 71 | } 72 | } 73 | } 74 | 75 | flutter { 76 | source '../..' 77 | } 78 | 79 | dependencies { 80 | implementation 'com.android.support:multidex:1.0.3' 81 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 82 | testImplementation 'junit:junit:4.12' 83 | androidTestImplementation 'androidx.test:runner:1.1.1' 84 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 85 | } 86 | 87 | apply plugin: 'com.google.gms.google-services' 88 | 89 | 90 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "1066037249477", 4 | "firebase_url": "https://flutter-todo-app-real.firebaseio.com", 5 | "project_id": "flutter-todo-app-real", 6 | "storage_bucket": "flutter-todo-app-real.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:1066037249477:android:48b1ad5380835b8407f7ac", 12 | "android_client_info": { 13 | "package_name": "com.example.todo_app" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "1066037249477-ubb76cbedftntkpjp42uhb5a8o8lqltm.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.example.todo_app", 22 | "certificate_hash": "f1a6dc46f90cf0858b62995c861d2f6b733144ae" 23 | } 24 | }, 25 | { 26 | "client_id": "1066037249477-j2fa7ulbdrr07o6rr62f73qov2fliioj.apps.googleusercontent.com", 27 | "client_type": 3 28 | } 29 | ], 30 | "api_key": [ 31 | { 32 | "current_key": "AIzaSyCl3YL660d32qqSl13mzz-A9WEv-TkvoAU" 33 | } 34 | ], 35 | "services": { 36 | "appinvite_service": { 37 | "other_platform_oauth_client": [ 38 | { 39 | "client_id": "1066037249477-j2fa7ulbdrr07o6rr62f73qov2fliioj.apps.googleusercontent.com", 40 | "client_type": 3 41 | } 42 | ] 43 | } 44 | } 45 | } 46 | ], 47 | "configuration_version": "1" 48 | } -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 30 | 31 | 34 | 35 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/todo_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.todo_app 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 10 | GeneratedPluginRegistrant.registerWith(flutterEngine); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /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/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/debug.keystore -------------------------------------------------------------------------------- /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/key.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/android/key.jks -------------------------------------------------------------------------------- /android/key.properties: -------------------------------------------------------------------------------- 1 | storePassword=android 2 | keyPassword=android 3 | keyAlias=key 4 | storeFile=C:\\Users\\Faruq Yusuff\\Desktop\\What Should be On My Desktop\\Flutter\\todo_app\\android\\key.jks 5 | 6 | -------------------------------------------------------------------------------- /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/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/assets/logo.png -------------------------------------------------------------------------------- /fonts/Poppins/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/fonts/Poppins/Poppins-Light.ttf -------------------------------------------------------------------------------- /fonts/Poppins/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/fonts/Poppins/Poppins-Medium.ttf -------------------------------------------------------------------------------- /fonts/Poppins/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/fonts/Poppins/Poppins-Regular.ttf -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 18 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 19 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXCopyFilesBuildPhase section */ 23 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 24 | isa = PBXCopyFilesBuildPhase; 25 | buildActionMask = 2147483647; 26 | dstPath = ""; 27 | dstSubfolderSpec = 10; 28 | files = ( 29 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 30 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 31 | ); 32 | name = "Embed Frameworks"; 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 39 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 40 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 41 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 42 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 43 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 44 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 45 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 46 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 47 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 48 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 61 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 9740EEB11CF90186004384FC /* Flutter */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 3B80C3931E831B6300D905FE /* App.framework */, 72 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 73 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 74 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 75 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 76 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 77 | ); 78 | name = Flutter; 79 | sourceTree = ""; 80 | }; 81 | 97C146E51CF9000F007C117D = { 82 | isa = PBXGroup; 83 | children = ( 84 | 9740EEB11CF90186004384FC /* Flutter */, 85 | 97C146F01CF9000F007C117D /* Runner */, 86 | 97C146EF1CF9000F007C117D /* Products */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 97C146EF1CF9000F007C117D /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 97C146EE1CF9000F007C117D /* Runner.app */, 94 | ); 95 | name = Products; 96 | sourceTree = ""; 97 | }; 98 | 97C146F01CF9000F007C117D /* Runner */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 102 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 103 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 104 | 97C147021CF9000F007C117D /* Info.plist */, 105 | 97C146F11CF9000F007C117D /* Supporting Files */, 106 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 107 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 108 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 109 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 110 | ); 111 | path = Runner; 112 | sourceTree = ""; 113 | }; 114 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 97C146ED1CF9000F007C117D /* Runner */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 127 | buildPhases = ( 128 | 9740EEB61CF901F6004384FC /* Run Script */, 129 | 97C146EA1CF9000F007C117D /* Sources */, 130 | 97C146EB1CF9000F007C117D /* Frameworks */, 131 | 97C146EC1CF9000F007C117D /* Resources */, 132 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 133 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = Runner; 140 | productName = Runner; 141 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 97C146E61CF9000F007C117D /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 1020; 151 | ORGANIZATIONNAME = "The Chromium Authors"; 152 | TargetAttributes = { 153 | 97C146ED1CF9000F007C117D = { 154 | CreatedOnToolsVersion = 7.3.1; 155 | LastSwiftMigration = 1100; 156 | }; 157 | }; 158 | }; 159 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 160 | compatibilityVersion = "Xcode 3.2"; 161 | developmentRegion = en; 162 | hasScannedForEncodings = 0; 163 | knownRegions = ( 164 | en, 165 | Base, 166 | ); 167 | mainGroup = 97C146E51CF9000F007C117D; 168 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 169 | projectDirPath = ""; 170 | projectRoot = ""; 171 | targets = ( 172 | 97C146ED1CF9000F007C117D /* Runner */, 173 | ); 174 | }; 175 | /* End PBXProject section */ 176 | 177 | /* Begin PBXResourcesBuildPhase section */ 178 | 97C146EC1CF9000F007C117D /* Resources */ = { 179 | isa = PBXResourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 183 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 184 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 185 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXResourcesBuildPhase section */ 190 | 191 | /* Begin PBXShellScriptBuildPhase section */ 192 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 193 | isa = PBXShellScriptBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | inputPaths = ( 198 | ); 199 | name = "Thin Binary"; 200 | outputPaths = ( 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | shellPath = /bin/sh; 204 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 205 | }; 206 | 9740EEB61CF901F6004384FC /* Run Script */ = { 207 | isa = PBXShellScriptBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | inputPaths = ( 212 | ); 213 | name = "Run Script"; 214 | outputPaths = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 219 | }; 220 | /* End PBXShellScriptBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | 97C146EA1CF9000F007C117D /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 228 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | /* End PBXSourcesBuildPhase section */ 233 | 234 | /* Begin PBXVariantGroup section */ 235 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 236 | isa = PBXVariantGroup; 237 | children = ( 238 | 97C146FB1CF9000F007C117D /* Base */, 239 | ); 240 | name = Main.storyboard; 241 | sourceTree = ""; 242 | }; 243 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 97C147001CF9000F007C117D /* Base */, 247 | ); 248 | name = LaunchScreen.storyboard; 249 | sourceTree = ""; 250 | }; 251 | /* End PBXVariantGroup section */ 252 | 253 | /* Begin XCBuildConfiguration section */ 254 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 255 | isa = XCBuildConfiguration; 256 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_ANALYZER_NONNULL = YES; 260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_ENABLE_MODULES = YES; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 265 | CLANG_WARN_BOOL_CONVERSION = YES; 266 | CLANG_WARN_COMMA = YES; 267 | CLANG_WARN_CONSTANT_CONVERSION = YES; 268 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 279 | CLANG_WARN_STRICT_PROTOTYPES = YES; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_NS_ASSERTIONS = NO; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | SDKROOT = iphoneos; 299 | SUPPORTED_PLATFORMS = iphoneos; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | VALIDATE_PRODUCT = YES; 302 | }; 303 | name = Profile; 304 | }; 305 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 306 | isa = XCBuildConfiguration; 307 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 308 | buildSettings = { 309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 310 | CLANG_ENABLE_MODULES = YES; 311 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 312 | ENABLE_BITCODE = NO; 313 | FRAMEWORK_SEARCH_PATHS = ( 314 | "$(inherited)", 315 | "$(PROJECT_DIR)/Flutter", 316 | ); 317 | INFOPLIST_FILE = Runner/Info.plist; 318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 319 | LIBRARY_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "$(PROJECT_DIR)/Flutter", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todoApp; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 326 | SWIFT_VERSION = 5.0; 327 | VERSIONING_SYSTEM = "apple-generic"; 328 | }; 329 | name = Profile; 330 | }; 331 | 97C147031CF9000F007C117D /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 334 | buildSettings = { 335 | ALWAYS_SEARCH_USER_PATHS = NO; 336 | CLANG_ANALYZER_NONNULL = YES; 337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 338 | CLANG_CXX_LIBRARY = "libc++"; 339 | CLANG_ENABLE_MODULES = YES; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 342 | CLANG_WARN_BOOL_CONVERSION = YES; 343 | CLANG_WARN_COMMA = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 347 | CLANG_WARN_EMPTY_BODY = YES; 348 | CLANG_WARN_ENUM_CONVERSION = YES; 349 | CLANG_WARN_INFINITE_RECURSION = YES; 350 | CLANG_WARN_INT_CONVERSION = YES; 351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 352 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 356 | CLANG_WARN_STRICT_PROTOTYPES = YES; 357 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | DEBUG_INFORMATION_FORMAT = dwarf; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | ENABLE_TESTABILITY = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 375 | GCC_WARN_UNDECLARED_SELECTOR = YES; 376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 377 | GCC_WARN_UNUSED_FUNCTION = YES; 378 | GCC_WARN_UNUSED_VARIABLE = YES; 379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 380 | MTL_ENABLE_DEBUG_INFO = YES; 381 | ONLY_ACTIVE_ARCH = YES; 382 | SDKROOT = iphoneos; 383 | TARGETED_DEVICE_FAMILY = "1,2"; 384 | }; 385 | name = Debug; 386 | }; 387 | 97C147041CF9000F007C117D /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_ANALYZER_NONNULL = YES; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 402 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 409 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 412 | CLANG_WARN_STRICT_PROTOTYPES = YES; 413 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 419 | ENABLE_NS_ASSERTIONS = NO; 420 | ENABLE_STRICT_OBJC_MSGSEND = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu99; 422 | GCC_NO_COMMON_BLOCKS = YES; 423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 425 | GCC_WARN_UNDECLARED_SELECTOR = YES; 426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 427 | GCC_WARN_UNUSED_FUNCTION = YES; 428 | GCC_WARN_UNUSED_VARIABLE = YES; 429 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 430 | MTL_ENABLE_DEBUG_INFO = NO; 431 | SDKROOT = iphoneos; 432 | SUPPORTED_PLATFORMS = iphoneos; 433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 434 | TARGETED_DEVICE_FAMILY = "1,2"; 435 | VALIDATE_PRODUCT = YES; 436 | }; 437 | name = Release; 438 | }; 439 | 97C147061CF9000F007C117D /* Debug */ = { 440 | isa = XCBuildConfiguration; 441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | CLANG_ENABLE_MODULES = YES; 445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 446 | ENABLE_BITCODE = NO; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "$(PROJECT_DIR)/Flutter", 450 | ); 451 | INFOPLIST_FILE = Runner/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | LIBRARY_SEARCH_PATHS = ( 454 | "$(inherited)", 455 | "$(PROJECT_DIR)/Flutter", 456 | ); 457 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todoApp; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 461 | SWIFT_VERSION = 5.0; 462 | VERSIONING_SYSTEM = "apple-generic"; 463 | }; 464 | name = Debug; 465 | }; 466 | 97C147071CF9000F007C117D /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 471 | CLANG_ENABLE_MODULES = YES; 472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 473 | ENABLE_BITCODE = NO; 474 | FRAMEWORK_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | INFOPLIST_FILE = Runner/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 480 | LIBRARY_SEARCH_PATHS = ( 481 | "$(inherited)", 482 | "$(PROJECT_DIR)/Flutter", 483 | ); 484 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todoApp; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 487 | SWIFT_VERSION = 5.0; 488 | VERSIONING_SYSTEM = "apple-generic"; 489 | }; 490 | name = Release; 491 | }; 492 | /* End XCBuildConfiguration section */ 493 | 494 | /* Begin XCConfigurationList section */ 495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 496 | isa = XCConfigurationList; 497 | buildConfigurations = ( 498 | 97C147031CF9000F007C117D /* Debug */, 499 | 97C147041CF9000F007C117D /* Release */, 500 | 249021D3217E4FDB00AE95B9 /* Profile */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 97C147061CF9000F007C117D /* Debug */, 509 | 97C147071CF9000F007C117D /* Release */, 510 | 249021D4217E4FDB00AE95B9 /* Profile */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | /* End XCConfigurationList section */ 516 | }; 517 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 518 | } 519 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/ios/Runner/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /ios/Runner/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"}]} -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | todo_app 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_statusbarcolor/flutter_statusbarcolor.dart'; 5 | 6 | import './src/injection_container.dart' as di; 7 | import 'src/bloc_delegate.dart'; 8 | import 'src/features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_bloc.dart' as addListBloc; 9 | import 'src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_bloc.dart' as addNoteBloc; 10 | import 'src/features/todo_manager_features/presentation/bloc/auth_bloc/auth_bloc.dart'; 11 | import 'src/features/todo_manager_features/presentation/bloc/dashboard_bloc/dashboard_bloc.dart'; 12 | import 'src/features/todo_manager_features/presentation/bloc/login_bloc/login_bloc.dart'; 13 | import 'src/features/todo_manager_features/presentation/pages/Dashboard.dart'; 14 | import 'src/features/todo_manager_features/presentation/pages/Login.dart'; 15 | import 'src/features/todo_manager_features/presentation/pages/add_new_list.dart'; 16 | import 'src/features/todo_manager_features/presentation/pages/add_quick_note.dart'; 17 | 18 | 19 | void main() async{ 20 | WidgetsFlutterBinding.ensureInitialized(); 21 | await di.init(); 22 | BlocSupervisor.delegate = MyBlocDelegate(); 23 | await di.sl.allReady(); 24 | await FlutterStatusbarcolor.setStatusBarColor(Colors.white.withOpacity(0.90)); 25 | FlutterStatusbarcolor.setStatusBarWhiteForeground(false); 26 | runApp(MyApp()); 27 | } 28 | 29 | class MyApp extends StatefulWidget { 30 | @override 31 | _MyAppState createState() => _MyAppState(); 32 | } 33 | 34 | class _MyAppState extends State { 35 | AuthBloc _authBloc; 36 | 37 | @override 38 | void initState() { 39 | super.initState(); 40 | _authBloc = di.sl(); 41 | _authBloc.add(AppStarted()); 42 | } 43 | 44 | @override 45 | void dispose() { 46 | _authBloc.close(); 47 | super.dispose(); 48 | } 49 | 50 | @override 51 | Widget build(BuildContext context){ 52 | 53 | return BlocProvider.value( 54 | value: _authBloc, 55 | child: MaterialApp( 56 | debugShowCheckedModeBanner: false, 57 | title: 'Todo App', 58 | theme: ThemeData( 59 | primaryColor: Color(0xff657AFF), 60 | accentColor: Color(0xff4F5578), 61 | primarySwatch: Colors.blue, 62 | ), 63 | home: BlocBuilder( 64 | bloc: _authBloc, 65 | builder: (BuildContext context, AuthState authState){ 66 | if(authState is Uninitialised){ 67 | return BlocProvider( 68 | create: (context){return di.sl();}, 69 | child: LoginPage() 70 | ); 71 | } 72 | 73 | else if(authState is AuthAuthenticated){ 74 | return FutureBuilder( 75 | future: di.sl.allReady(), 76 | builder: (context, snapshot) { 77 | if(snapshot.hasData){ 78 | return BlocProvider( 79 | create: (context){ 80 | return di.sl(); 81 | }, 82 | child: DashboardScreen(), 83 | ); 84 | } 85 | else{ 86 | return Scaffold( 87 | body: Center( 88 | child: Container( 89 | height: 40, 90 | width: 40, 91 | child: CircularProgressIndicator(), 92 | ), 93 | ), 94 | ); 95 | } 96 | 97 | } 98 | ); 99 | } 100 | else{ 101 | return BlocProvider( 102 | create: (context){return di.sl();}, 103 | child: LoginPage() 104 | ); 105 | } 106 | } 107 | ), 108 | routes: { 109 | "/dashboard": (context) =>BlocProvider( 110 | create: (context){ 111 | return di.sl(); 112 | }, 113 | child: DashboardScreen(), 114 | ), 115 | "/addQuickNote": (context) => BlocProvider( 116 | create: (context){return di.sl();}, 117 | child: AddQuickNote() 118 | ), 119 | "/addList": (context) => BlocProvider( 120 | create: (context){return di.sl();}, 121 | child: AddList() 122 | ), 123 | 124 | }, 125 | ), 126 | 127 | ); 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /lib/src/bloc_delegate.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | class MyBlocDelegate extends BlocDelegate{ 3 | 4 | @override 5 | void onError(Bloc bloc, Object error, StackTrace stackTrace){ 6 | super.onError(bloc, error, stackTrace); 7 | print(error); 8 | } 9 | 10 | @override 11 | void onTransition(Bloc bloc, Transition transition) { 12 | super.onTransition(bloc,transition); 13 | print(transition); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /lib/src/core/constants/Constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const List listOfColorsForColorPicker = [ 4 | Color(0xff878CAC), 5 | Color(0xff4F5578), 6 | Color(0xff657AFF), 7 | Color(0xff3AB9F2), 8 | Color(0xff63D2BF), 9 | Color(0xffEB70B1) 10 | ]; 11 | 12 | Color hexToColor(String code) { 13 | return new Color(int.parse(code.substring(1, 7), radix: 16) + 0xFF000000); 14 | } 15 | 16 | String colorToHex(Color color){ 17 | return "#${color.toString().substring(10,16)}"; 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /lib/src/core/error/exceptions.dart: -------------------------------------------------------------------------------- 1 | 2 | class NoNetworkException implements Exception{} 3 | 4 | class FetchQuickNotesException implements Exception{} 5 | 6 | class FetchListsException implements Exception{} 7 | 8 | class GetListTodosException implements Exception{} -------------------------------------------------------------------------------- /lib/src/core/error/failure.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | 4 | abstract class Failure extends Equatable{ 5 | final List properties; 6 | Failure([this.properties = const[]]); 7 | 8 | @override 9 | List get props => [properties]; 10 | } 11 | 12 | 13 | 14 | class AuthFailure extends Failure{} 15 | 16 | class NoNetworkFailure extends Failure{} 17 | 18 | class FetchQuickNotesFailure extends Failure{} 19 | 20 | class FetchListsFailure extends Failure{} 21 | 22 | class GetListTodosFailure extends Failure{} -------------------------------------------------------------------------------- /lib/src/core/priority/Priority.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | class Priority{ 3 | String importance; 4 | int priorityValue; 5 | Color color; 6 | 7 | Priority.fromPriorityValue(int value){ 8 | if (value == 1){ 9 | this.priorityValue = value; 10 | this.color = Color(0xffFF4A4A); 11 | this.importance = "High"; 12 | } 13 | else if(value == 2){ 14 | this.priorityValue = value; 15 | this.color = Color(0xffF3C018); 16 | this.importance = "Low"; 17 | } 18 | else{ 19 | this.priorityValue = 3; 20 | this.color = Color(0xff878CAC); 21 | this.importance = "None"; 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /lib/src/core/user/user.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_auth/firebase_auth.dart'; 2 | 3 | class User { 4 | String uid; 5 | String displayName; 6 | 7 | User({this.uid, this.displayName}); 8 | 9 | User.fromFirebaseUser(FirebaseUser user) { 10 | if(user == null){ 11 | this.uid = null; 12 | this.displayName = null; 13 | } 14 | this.uid = user.uid; 15 | this.displayName = user.displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/datasources/auth_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:google_sign_in/google_sign_in.dart'; 4 | import 'package:rxdart/rxdart.dart'; 5 | import 'package:todo_app/src/core/user/user.dart'; 6 | 7 | 8 | class AuthService { 9 | final GoogleSignIn _googleSignIn = GoogleSignIn(); 10 | final FirebaseAuth _auth = FirebaseAuth.instance; 11 | final Firestore _db = Firestore.instance; 12 | Stream> profile; 13 | 14 | AuthService() { 15 | profile = _auth.onAuthStateChanged.switchMap((FirebaseUser user) { 16 | if (user != null) { 17 | return _db 18 | .collection("users") 19 | .document(user.uid) 20 | .snapshots() 21 | .map((snap) => snap.data); 22 | } else { 23 | return Stream.empty(); 24 | } 25 | }); 26 | } 27 | 28 | Stream get user{ 29 | return _auth.onAuthStateChanged.map(getUserFromFirebaseUser); 30 | } 31 | 32 | 33 | 34 | User getUserFromFirebaseUser(FirebaseUser user){ 35 | return user != null ? User.fromFirebaseUser(user): null; 36 | } 37 | 38 | Future getCurrentUser() async{ 39 | final user = User.fromFirebaseUser(await _auth.currentUser()); 40 | return user; 41 | } 42 | 43 | Future isSignedIn() async{ 44 | final currentUser = await _auth.currentUser(); 45 | return currentUser != null; 46 | } 47 | 48 | 49 | Future googleSignIn() async { 50 | 51 | GoogleSignInAccount googleUser = await _googleSignIn.signIn(); 52 | GoogleSignInAuthentication googleAuth = await googleUser.authentication; 53 | AuthResult result = await _auth.signInWithCredential(GoogleAuthProvider.getCredential( 54 | idToken: googleAuth.idToken, accessToken: googleAuth.accessToken) 55 | ); 56 | FirebaseUser user = result.user; 57 | updateUserData(user); 58 | 59 | return user; 60 | 61 | 62 | } 63 | 64 | void updateUserData(FirebaseUser user) async { 65 | DocumentReference ref = _db.collection("users").document(user.uid); 66 | 67 | return ref.setData({ 68 | 'uid': user.uid, 69 | 'email': user.uid, 70 | 'photoURL': user.photoUrl, 71 | 'displayName': user.displayName, 72 | 'lastSeen': DateTime.now() 73 | }, merge: true); 74 | } 75 | 76 | Future signOut() async{ 77 | try{ 78 | return await _auth.signOut(); 79 | } 80 | catch(e){ 81 | print(e.toString()); 82 | } 83 | 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/datasources/firestore_interactions.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:todo_app/src/core/error/exceptions.dart'; 4 | 5 | import '../../../../core/constants/Constants.dart'; 6 | import '../../domain/entities/ListTodo.dart'; 7 | 8 | 9 | 10 | class FirestoreInteractions { 11 | Firestore _db = Firestore.instance; 12 | 13 | //Utility stuff 14 | DocumentReference _getSpecificListDocument({@required String uid, @required String listId}){ 15 | return _db.collection("lists").document(uid).collection("userLists").document(listId); 16 | } 17 | 18 | DocumentReference _getSpecificQuickNoteDocument({@required String uid, @required String quickNoteId}){ 19 | return _db.collection("quickNotes").document(uid).collection("userNotes").document(quickNoteId); 20 | } 21 | 22 | DocumentReference _getSpecificListTodoDocument({@required String uid, @required String listId, @required String todoId}){ 23 | return _getSpecificListDocument(uid: uid, listId: listId).collection("todos").document(todoId); 24 | } 25 | //Dashboard stuff 26 | 27 | Stream fetchQuickNotes(String uid) { 28 | try{ 29 | return _db 30 | .collection("quickNotes") 31 | .document(uid) 32 | .collection("userNotes") 33 | .orderBy("priority") 34 | .snapshots(); 35 | } 36 | 37 | on Exception{ 38 | throw FetchQuickNotesException(); 39 | } 40 | 41 | } 42 | 43 | Stream fetchLists(String uid) { 44 | try{ 45 | return _db 46 | .collection("lists") 47 | .document(uid) 48 | .collection("userLists") 49 | .snapshots(); 50 | } 51 | on Exception{ 52 | throw FetchListsException(); 53 | } 54 | 55 | } 56 | 57 | Stream getListTodos({String uid, String listId}) { 58 | try{ 59 | return _db 60 | .collection("lists") 61 | .document(uid) 62 | .collection("userLists") 63 | .document(listId) 64 | .collection("todos") 65 | .orderBy("isDone") 66 | .snapshots(); 67 | } 68 | on Exception{ 69 | throw GetListTodosException(); 70 | } 71 | 72 | } 73 | 74 | void addQuickNote({String uid, Map quickNoteData}) { 75 | _db.collection("quickNotes").document(uid).collection("userNotes").add({ 76 | 'title': quickNoteData['title'], 77 | 'priority': quickNoteData['priority'], 78 | 'isDone': quickNoteData['isDone'] 79 | }); 80 | } 81 | 82 | Future addList({String uid, String listTitle, List listOfTodos, 83 | String listBackgroundColor}) async { 84 | 85 | return _db.collection("lists").document(uid).collection("userLists").add({ 86 | "title": listTitle, 87 | "backgroundColor": listBackgroundColor.toString() 88 | }).then((DocumentReference doc) { 89 | listOfTodos.forEach((ListTodo todo) { 90 | doc.collection("todos").add({ 91 | "isDone": todo.isDone, 92 | "title": todo.title, 93 | "details": todo.details 94 | }); 95 | }); 96 | }); 97 | } 98 | 99 | 100 | //Quick Note stuff 101 | 102 | void setQuickNoteIsDone({String uid, String quickNoteId, bool isDone}){ 103 | _getSpecificQuickNoteDocument(uid: uid, quickNoteId: quickNoteId).updateData({ 104 | 'isDone': isDone 105 | }); 106 | } 107 | 108 | void setQuickNoteTitle({String uid, String quickNoteId, String newTitle}){ 109 | _getSpecificQuickNoteDocument(uid: uid, quickNoteId: quickNoteId).updateData({ 110 | 'title': newTitle 111 | }); 112 | } 113 | 114 | void deleteQuickNote({String uid, String quickNoteId}){ 115 | _getSpecificQuickNoteDocument(uid: uid, quickNoteId: quickNoteId).delete(); 116 | } 117 | 118 | //List stuff 119 | void setBackgroundColor({String uid, String listId, Color newColor}){ 120 | _getSpecificListDocument(uid: uid, listId: listId).updateData({ 121 | "backgroundColor": colorToHex(newColor) 122 | }); 123 | } 124 | 125 | void updateListTitle({String uid, String listId, String newTitle}){ 126 | _getSpecificListDocument(uid: uid, listId: listId).updateData({ 127 | "title": newTitle 128 | }); 129 | } 130 | 131 | void addNewTodo({String uid, String listId, String todoTitle}){ 132 | _getSpecificListDocument(uid: uid, listId: listId).collection("todos").add({ 133 | "title": todoTitle, "isDone": false, "details": "" 134 | }); 135 | } 136 | 137 | void deleteList({String uid, String listId}){ 138 | _getSpecificListDocument(uid: uid, listId: listId).delete(); 139 | } 140 | 141 | //list-todo stuff 142 | void setListTodoIsDone({String uid, String listId, String todoId, bool isDone}){ 143 | _getSpecificListTodoDocument(uid: uid, listId: listId, todoId: todoId).updateData({ 144 | "isDone": isDone 145 | }); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/models/ListModel.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:cloud_firestore/cloud_firestore.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:todo_app/src/core/constants/Constants.dart'; 5 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/List.dart'; 6 | 7 | 8 | class ListModel extends ListEntity { 9 | 10 | ListModel({ 11 | @required backgroundColor, 12 | @required listTitle, 13 | @required listId, 14 | @required listOfTodosStream 15 | }): super(backgroundColor: backgroundColor, listTitle:listTitle, listOfTodosStream:listOfTodosStream, listId: listId); 16 | 17 | factory ListModel.fromFirestoreDoc(DocumentSnapshot doc){ 18 | return ListModel( 19 | backgroundColor: hexToColor(doc["backgroundColor"]) , 20 | listTitle: doc["title"], 21 | listId: doc.documentID, 22 | listOfTodosStream: doc.reference.collection("todos").orderBy("isDone").snapshots().asBroadcastStream() 23 | ); 24 | } 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/models/ListTodoModel.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/ListTodo.dart'; 4 | 5 | class ListTodoModel extends ListTodo{ 6 | 7 | ListTodoModel({ 8 | @required isDone, 9 | @required title, 10 | details, 11 | @required todoId, 12 | @required listId 13 | }) : super( 14 | isDone: isDone, 15 | title: title, 16 | details: details, 17 | todoId: todoId, 18 | listId: listId 19 | ); 20 | 21 | factory ListTodoModel.fromFirestoreInfo({String listId, DocumentSnapshot todoDoc}){ 22 | return ListTodoModel( 23 | isDone: todoDoc['isDone'], 24 | title: todoDoc['title'], 25 | details: todoDoc['details'], 26 | todoId: todoDoc.documentID, 27 | listId: listId 28 | ); 29 | } 30 | 31 | 32 | 33 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/models/QuickNoteModel.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:todo_app/src/core/priority/Priority.dart'; 4 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/QuickNote.dart'; 5 | 6 | 7 | class QuickNoteModel extends QuickNote{ 8 | QuickNoteModel({ 9 | @required priority, 10 | @required isDone, 11 | @required title, 12 | @required quickNoteId 13 | }): super( 14 | priority: priority, 15 | isDone: isDone, 16 | title: title, 17 | quickNoteId: quickNoteId 18 | ); 19 | 20 | 21 | factory QuickNoteModel.fromFirestoreDoc(DocumentSnapshot doc){ 22 | return QuickNoteModel( 23 | priority: Priority.fromPriorityValue(doc['priority']), 24 | isDone: doc['isDone'], 25 | title: doc['title'], 26 | quickNoteId: doc.documentID 27 | ); 28 | } 29 | 30 | 31 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/repositories/auth_repository_impl.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:todo_app/src/core/error/exceptions.dart'; 5 | import 'package:todo_app/src/core/user/user.dart'; 6 | import 'package:todo_app/src/features/todo_manager_features/data/datasources/auth_service.dart'; 7 | 8 | import '../../../../core/error/failure.dart'; 9 | import '../../domain/repositories/auth_repository.dart'; 10 | 11 | class AuthRepositoryImpl implements AuthRepository{ 12 | final AuthService authService; 13 | 14 | AuthRepositoryImpl(this.authService); 15 | @override 16 | Future> signInWithGoogle() async{ 17 | try{ 18 | final user = await authService.googleSignIn(); 19 | return Right(user); 20 | } 21 | on PlatformException catch(e){ 22 | if(e.code == 'sign_in_failed'){ 23 | return Left(AuthFailure()); 24 | } 25 | else if(e.code == 'network_error'){ 26 | return Left(NoNetworkFailure()); 27 | } 28 | else{ 29 | print(e); 30 | } 31 | } 32 | 33 | } 34 | 35 | @override 36 | Future signOut() async{ 37 | await authService.signOut(); 38 | } 39 | 40 | @override 41 | Future getUser() async{ 42 | return authService.getCurrentUser(); 43 | } 44 | 45 | @override 46 | Future isSignedIn() { 47 | return authService.isSignedIn(); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/data/repositories/todo_manager_repository_impl.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:cloud_firestore/cloud_firestore.dart'; 4 | import 'package:meta/meta.dart'; 5 | 6 | 7 | import '../../domain/entities/ListTodo.dart'; 8 | import '../../domain/repositories/todo_manager_repository.dart'; 9 | import '../datasources/firestore_interactions.dart'; 10 | 11 | class TodoManagerRepositoryImpl implements TodoManagerRepository { 12 | final FirestoreInteractions firestoreInteractions; 13 | 14 | TodoManagerRepositoryImpl(this.firestoreInteractions); 15 | @override 16 | Future addList( 17 | {@required String uid, 18 | @required String listTitle, 19 | @required List listOfTodos, 20 | String listBackgroundColor}) async { 21 | await firestoreInteractions.addList( 22 | uid: uid, 23 | listTitle: listTitle, 24 | listBackgroundColor: listBackgroundColor, 25 | listOfTodos: listOfTodos); 26 | } 27 | 28 | @override 29 | void addNewTodo({String uid, String listId, String todoTitle}) { 30 | firestoreInteractions.addNewTodo( 31 | uid: uid, listId: listId, todoTitle: todoTitle); 32 | } 33 | 34 | @override 35 | void addQuickNote({String uid, Map quickNoteData}) { 36 | firestoreInteractions.addQuickNote(uid: uid, quickNoteData: quickNoteData); 37 | } 38 | 39 | @override 40 | void deleteList({String uid, String listId}) { 41 | firestoreInteractions.deleteList(uid: uid, listId: listId); 42 | } 43 | 44 | @override 45 | void deleteQuickNote({String uid, String quickNoteId}) { 46 | firestoreInteractions.deleteQuickNote(uid: uid, quickNoteId: quickNoteId); 47 | } 48 | 49 | @override 50 | Stream fetchLists(String uid) { 51 | return firestoreInteractions.fetchLists(uid); 52 | } 53 | 54 | @override 55 | Stream fetchQuickNotes(String uid) { 56 | return firestoreInteractions.fetchQuickNotes(uid); 57 | } 58 | 59 | @override 60 | Stream getListTodos({String uid, String listId}) { 61 | return firestoreInteractions.getListTodos(uid: uid, listId: listId); 62 | } 63 | 64 | @override 65 | void setBackgroundColor({String uid, String listId, Color newColor}) { 66 | firestoreInteractions.setBackgroundColor( 67 | uid: uid, listId: listId, newColor: newColor); 68 | } 69 | 70 | @override 71 | void setListTodoIsDone( 72 | {String uid, String listId, String todoId, bool isDone}) { 73 | firestoreInteractions.setListTodoIsDone( 74 | uid: uid, listId: listId, isDone: isDone, todoId: todoId); 75 | } 76 | 77 | @override 78 | void setQuickNoteIsDone({String uid, String quickNoteId, bool isDone}) { 79 | firestoreInteractions.setQuickNoteIsDone( 80 | uid: uid, isDone: isDone, quickNoteId: quickNoteId); 81 | print("worked"); 82 | } 83 | 84 | @override 85 | void setQuickNoteTitle({String uid, String quickNoteId, String newTitle}) { 86 | firestoreInteractions.setQuickNoteTitle( 87 | uid: uid, quickNoteId: quickNoteId, newTitle: newTitle); 88 | } 89 | 90 | @override 91 | void updateListTitle({String uid, String listId, String newTitle}) { 92 | firestoreInteractions.updateListTitle(uid: uid, listId: listId, newTitle: newTitle); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/entities/List.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | 4 | 5 | class ListEntity { 6 | Color backgroundColor; 7 | String listTitle; 8 | String listId; 9 | Stream listOfTodosStream; 10 | 11 | 12 | 13 | ListEntity({ 14 | @required this.backgroundColor, 15 | @required this.listTitle, 16 | @required this.listId, 17 | @required this.listOfTodosStream 18 | }); 19 | 20 | 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/entities/ListTodo.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | class ListTodo{ 3 | bool isDone; 4 | String title; 5 | String details; 6 | String todoId; 7 | String listId; 8 | 9 | 10 | 11 | ListTodo({ 12 | @required this.isDone, 13 | @required this.title, 14 | this.details, 15 | this.todoId, 16 | this.listId 17 | }); 18 | 19 | 20 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/entities/QuickNote.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../../core/priority/Priority.dart'; 4 | 5 | class QuickNote{ 6 | String quickNoteId; 7 | Priority priority; 8 | bool isDone; 9 | String title; 10 | 11 | 12 | QuickNote({ 13 | @required this.priority, 14 | @required this.isDone, 15 | @required this.title, 16 | @required this.quickNoteId 17 | }); 18 | 19 | 20 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/repositories/auth_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:todo_app/src/core/error/failure.dart'; 4 | import 'package:todo_app/src/core/user/user.dart'; 5 | 6 | abstract class AuthRepository{ 7 | Future> signInWithGoogle(); 8 | Future signOut(); 9 | Future isSignedIn(); 10 | Future getUser(); 11 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/ListTodo.dart'; 4 | 5 | abstract class TodoManagerRepository { 6 | Stream fetchQuickNotes(String uid); 7 | 8 | Stream fetchLists(String uid); 9 | 10 | Stream getListTodos({String uid, String listId}); 11 | 12 | void addQuickNote({String uid, Map quickNoteData}); 13 | 14 | Future addList({String uid, String listTitle, List listOfTodos, String listBackgroundColor}); 15 | void setQuickNoteIsDone({String uid, String quickNoteId, bool isDone}); 16 | 17 | void setQuickNoteTitle({String uid, String quickNoteId, String newTitle}); 18 | 19 | void deleteQuickNote({String uid, String quickNoteId}); 20 | 21 | void setBackgroundColor({String uid, String listId, Color newColor}); 22 | 23 | void updateListTitle({String uid, String listId, String newTitle}); 24 | 25 | void addNewTodo({String uid, String listId, String todoTitle}); 26 | 27 | void deleteList({String uid, String listId}); 28 | 29 | void setListTodoIsDone({String uid, String listId, String todoId, bool isDone}); 30 | 31 | 32 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/add_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/ListTodo.dart'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 4 | 5 | class AddList{ 6 | final TodoManagerRepository repository; 7 | 8 | AddList(this.repository); 9 | 10 | Future call({@required String uid, @required String listTitle, @required List listOfTodos, @required String listBackgroundColor}) async{ 11 | await repository.addList( 12 | uid: uid, 13 | listBackgroundColor: listBackgroundColor, 14 | listOfTodos: listOfTodos, 15 | listTitle: listTitle 16 | ); 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/add_quick_note.dart: -------------------------------------------------------------------------------- 1 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 2 | import 'package:meta/meta.dart'; 3 | 4 | class AddQuickNote{ 5 | final TodoManagerRepository repository; 6 | 7 | AddQuickNote(this.repository); 8 | 9 | void call({@required String uid, @required Map quickNoteData}){ 10 | repository.addQuickNote( 11 | uid: uid, 12 | quickNoteData: quickNoteData 13 | ); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/dashboard_use_cases.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 3 | import 'package:meta/meta.dart'; 4 | class FetchListTodos{ 5 | final TodoManagerRepository repository; 6 | 7 | FetchListTodos(this.repository); 8 | 9 | Stream call({@required String uid, @required String listId}){ 10 | return repository.getListTodos( 11 | uid: uid, 12 | listId: listId 13 | ); 14 | } 15 | 16 | 17 | } 18 | class FetchQuickNotes{ 19 | final TodoManagerRepository repository; 20 | 21 | FetchQuickNotes(this.repository); 22 | 23 | Stream call({@required String uid}){ 24 | return repository.fetchQuickNotes(uid); 25 | } 26 | 27 | 28 | } 29 | 30 | class FetchLists{ 31 | final TodoManagerRepository repository; 32 | 33 | FetchLists(this.repository); 34 | 35 | Stream call({@required String uid}){ 36 | return repository.fetchLists(uid); 37 | } 38 | 39 | 40 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/edit_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 3 | import 'package:meta/meta.dart'; 4 | 5 | class EditListTitle { 6 | final TodoManagerRepository repository; 7 | 8 | EditListTitle(this.repository); 9 | 10 | void call({@required String uid,@required String listId,@required String newTitle}){ 11 | repository.updateListTitle( 12 | uid: uid, 13 | listId: listId, 14 | newTitle: newTitle 15 | ); 16 | } 17 | } 18 | 19 | class DeleteList { 20 | final TodoManagerRepository repository; 21 | 22 | DeleteList(this.repository); 23 | 24 | void call({@required String uid,@required String listId}){ 25 | repository.deleteList( 26 | uid: uid, 27 | listId: listId, 28 | ); 29 | } 30 | } 31 | 32 | class AddListTodo { 33 | final TodoManagerRepository repository; 34 | 35 | AddListTodo(this.repository); 36 | 37 | void call({@required String uid,@required String listId,@required String todoTitle}){ 38 | repository.addNewTodo( 39 | uid: uid, 40 | listId: listId, 41 | todoTitle: todoTitle 42 | ); 43 | } 44 | } 45 | 46 | class EditBackgroundColor { 47 | final TodoManagerRepository repository; 48 | 49 | EditBackgroundColor(this.repository); 50 | 51 | void call({@required String uid,@required String listId,@required Color newColor}){ 52 | repository.setBackgroundColor( 53 | uid: uid, 54 | listId: listId, 55 | newColor: newColor 56 | ); 57 | } 58 | } 59 | 60 | class ReorderListTodo {} 61 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/edit_list_todo.dart: -------------------------------------------------------------------------------- 1 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 2 | import 'package:meta/meta.dart'; 3 | class SetListTodoIsDone{ 4 | final TodoManagerRepository repository; 5 | 6 | SetListTodoIsDone(this.repository); 7 | 8 | void call({@required String uid,@required String listId,@required String todoId,@required bool isDone}){ 9 | repository.setListTodoIsDone( 10 | uid: uid, 11 | isDone: isDone, 12 | listId: listId, 13 | todoId: todoId 14 | ); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/domain/usecases/edit_quick_note.dart: -------------------------------------------------------------------------------- 1 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 2 | import 'package:meta/meta.dart'; 3 | class EditQuickNoteTitle { 4 | final TodoManagerRepository repository; 5 | 6 | EditQuickNoteTitle(this.repository); 7 | 8 | void call({@required String uid,@required String quickNoteId,@required String newTitle}){ 9 | repository.setQuickNoteTitle( 10 | uid: uid, 11 | quickNoteId: quickNoteId, 12 | newTitle: newTitle 13 | ); 14 | } 15 | } 16 | 17 | class DeleteQuickNote { 18 | final TodoManagerRepository repository; 19 | 20 | DeleteQuickNote(this.repository); 21 | 22 | void call({@required String uid,@required String quickNoteId}){ 23 | repository.deleteQuickNote( 24 | uid: uid, 25 | quickNoteId: quickNoteId, 26 | ); 27 | } 28 | } 29 | 30 | class SetQuickNoteIsDone { 31 | final TodoManagerRepository repository; 32 | 33 | SetQuickNoteIsDone(this.repository); 34 | 35 | void call({@required String uid,@required String quickNoteId,@required bool isDone}){ 36 | repository.setQuickNoteIsDone( 37 | uid: uid, 38 | quickNoteId: quickNoteId, 39 | isDone: isDone 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:todo_app/src/core/user/user.dart'; 6 | import 'package:todo_app/src/features/todo_manager_features/domain/usecases/add_list.dart' 7 | as usecase; 8 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/ListTodo.dart'; 9 | 10 | part 'add_list_event.dart'; 11 | part 'add_list_state.dart'; 12 | 13 | class AddListBloc extends Bloc { 14 | final usecase.AddList _addList; 15 | final User _user; 16 | 17 | AddListBloc({@required usecase.AddList addList, @required User user}) 18 | : assert(addList != null), 19 | _addList = addList, 20 | assert(user != null), 21 | _user = user; 22 | @override 23 | AddListState get initialState => AddListInitial(); 24 | 25 | @override 26 | Stream mapEventToState( 27 | AddListEvent event, 28 | ) async* { 29 | if (event is AddList){ 30 | yield AddingList(); 31 | await _addList( 32 | uid: _user.uid, 33 | listTitle: event.listTitle, 34 | listOfTodos: event.listOfTodos, 35 | listBackgroundColor: event.listBackgroundColor 36 | ); 37 | yield ListAdded(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_event.dart: -------------------------------------------------------------------------------- 1 | part of 'add_list_bloc.dart'; 2 | 3 | abstract class AddListEvent extends Equatable { 4 | final List properties; 5 | const AddListEvent([this.properties = const []]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | class AddList extends AddListEvent { 12 | final String listTitle; 13 | final List listOfTodos; 14 | final String listBackgroundColor; 15 | AddList({ 16 | @required this.listTitle, 17 | @required this.listOfTodos, 18 | @required this.listBackgroundColor 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_state.dart: -------------------------------------------------------------------------------- 1 | part of 'add_list_bloc.dart'; 2 | 3 | 4 | abstract class AddListState extends Equatable { 5 | final List properties; 6 | const AddListState([this.properties = const[]]); 7 | 8 | @override 9 | List get props => [properties]; 10 | } 11 | 12 | class AddListInitial extends AddListState { 13 | 14 | } 15 | class AddingList extends AddListState{ 16 | 17 | } 18 | class ListAdded extends AddListState{ 19 | 20 | } 21 | 22 | class Error extends AddListState{ 23 | final String message; 24 | 25 | Error(this.message); 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:todo_app/src/core/user/user.dart'; 6 | import 'package:todo_app/src/features/todo_manager_features/domain/usecases/add_quick_note.dart' as usecase; 7 | 8 | 9 | part 'add_quick_note_event.dart'; 10 | part 'add_quick_note_state.dart'; 11 | 12 | class AddQuickNoteBloc extends Bloc { 13 | final usecase.AddQuickNote _addQuickNote; 14 | final User _user; 15 | 16 | AddQuickNoteBloc({ 17 | @required User user, 18 | @required usecase.AddQuickNote addQuickNote 19 | }): assert(user != null), _user = user, 20 | assert(addQuickNote != null), _addQuickNote = addQuickNote; 21 | 22 | @override 23 | AddQuickNoteState get initialState => AddQuickNoteInitial(); 24 | 25 | @override 26 | Stream mapEventToState( 27 | AddQuickNoteEvent event, 28 | ) async* { 29 | try{ 30 | if(event is AddQuickNote){ 31 | _addQuickNote(uid: _user.uid, quickNoteData: event.quickNoteData); 32 | yield QuickNoteAdded(); 33 | yield AddQuickNoteInitial(); 34 | } 35 | } 36 | catch(e){ 37 | yield Error("Error adding Quick Notes"); 38 | print(e); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_event.dart: -------------------------------------------------------------------------------- 1 | part of 'add_quick_note_bloc.dart'; 2 | 3 | abstract class AddQuickNoteEvent extends Equatable { 4 | final List properties; 5 | const AddQuickNoteEvent([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | 10 | } 11 | 12 | 13 | class AddQuickNote extends AddQuickNoteEvent{ 14 | final Map quickNoteData; 15 | 16 | AddQuickNote(this.quickNoteData); 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_state.dart: -------------------------------------------------------------------------------- 1 | part of 'add_quick_note_bloc.dart'; 2 | 3 | abstract class AddQuickNoteState extends Equatable { 4 | final List properties; 5 | const AddQuickNoteState([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | class AddQuickNoteInitial extends AddQuickNoteState { 12 | 13 | } 14 | 15 | class QuickNoteAdded extends AddQuickNoteState{ 16 | 17 | } 18 | 19 | class Error extends AddQuickNoteState{ 20 | final String message; 21 | 22 | Error(this.message); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/auth_bloc/auth_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:meta/meta.dart'; 6 | 7 | import '../../../../../core/user/user.dart'; 8 | import '../../../domain/repositories/auth_repository.dart'; 9 | 10 | part 'auth_event.dart'; 11 | part 'auth_state.dart'; 12 | 13 | class AuthBloc extends Bloc { 14 | final AuthRepository _authRepository; 15 | 16 | AuthBloc({ 17 | @required AuthRepository authRepository 18 | }): assert(authRepository != null), _authRepository = authRepository; 19 | 20 | @override 21 | AuthState get initialState => Uninitialised(); 22 | 23 | @override 24 | Stream mapEventToState( 25 | AuthEvent event, 26 | ) async* { 27 | if(event is AppStarted){ 28 | yield* _mapAppStartedToState(); 29 | } 30 | else if (event is LoggedIn){ 31 | yield AuthAuthenticated(await _authRepository.getUser()); 32 | } 33 | else if (event is LoggedOut){ 34 | await _authRepository.signOut(); 35 | yield AuthUnauthenticated(); 36 | } 37 | } 38 | 39 | Stream _mapAppStartedToState() async*{ 40 | try{ 41 | final isSignedIn = await _authRepository.isSignedIn(); 42 | if(isSignedIn || await _authRepository.getUser() == null){ 43 | final user = await _authRepository.getUser(); 44 | yield AuthAuthenticated(user); 45 | } 46 | else{ 47 | yield AuthUnauthenticated(); 48 | } 49 | } 50 | catch(_){ 51 | yield AuthUnauthenticated(); 52 | } 53 | } 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/auth_bloc/auth_event.dart: -------------------------------------------------------------------------------- 1 | part of 'auth_bloc.dart'; 2 | 3 | abstract class AuthEvent extends Equatable { 4 | final List properties; 5 | const AuthEvent([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | class AppStarted extends AuthEvent{} 12 | 13 | class LoggedIn extends AuthEvent{} 14 | 15 | class LoggedOut extends AuthEvent{} 16 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/auth_bloc/auth_state.dart: -------------------------------------------------------------------------------- 1 | part of 'auth_bloc.dart'; 2 | 3 | abstract class AuthState extends Equatable { 4 | final List properties; 5 | const AuthState([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | class Uninitialised extends AuthState { 12 | } 13 | 14 | 15 | class AuthAuthenticated extends AuthState{ 16 | final User user; 17 | 18 | AuthAuthenticated(this.user): super([user]); 19 | 20 | } 21 | 22 | class AuthUnauthenticated extends AuthState{ 23 | 24 | } 25 | 26 | class AuthError extends AuthState{ 27 | final String message; 28 | 29 | AuthError(this.message) : super([message]); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/dashboard_bloc/dashboard_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:cloud_firestore/cloud_firestore.dart'; 4 | import 'package:meta/meta.dart'; 5 | import 'package:bloc/bloc.dart'; 6 | import 'package:equatable/equatable.dart'; 7 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/List.dart'; 8 | part 'dashboard_event.dart'; 9 | part 'dashboard_state.dart'; 10 | 11 | class DashboardBloc extends Bloc { 12 | 13 | 14 | @override 15 | DashboardState get initialState => DashboardInitial(); 16 | 17 | @override 18 | Stream mapEventToState( 19 | DashboardEvent event, 20 | ) async* { 21 | 22 | if(event is OpenList){ 23 | yield ListIsOpened(event.listEntity); 24 | } 25 | else if(event is CloseList){ 26 | yield ListIsClosed(); 27 | } 28 | 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/dashboard_bloc/dashboard_event.dart: -------------------------------------------------------------------------------- 1 | part of 'dashboard_bloc.dart'; 2 | 3 | abstract class DashboardEvent extends Equatable { 4 | final List properties; 5 | const DashboardEvent([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | 10 | } 11 | 12 | class FetchUserData extends DashboardEvent{} 13 | 14 | 15 | 16 | class OpenList extends DashboardEvent{ 17 | final ListEntity listEntity; 18 | 19 | OpenList(this.listEntity): super([listEntity]); 20 | } 21 | 22 | class CloseList extends DashboardEvent{} -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/dashboard_bloc/dashboard_state.dart: -------------------------------------------------------------------------------- 1 | part of 'dashboard_bloc.dart'; 2 | 3 | abstract class DashboardState extends Equatable { 4 | final List properties; 5 | const DashboardState([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | class DashboardInitial extends DashboardState { 12 | @override 13 | List get props => []; 14 | } 15 | 16 | 17 | class Error extends DashboardState{ 18 | final String message; 19 | 20 | Error(this.message); 21 | } 22 | 23 | class UserDataLoaded extends DashboardState{ 24 | final Stream quickNotesStream; 25 | final Stream listsStream; 26 | final String userName; 27 | 28 | UserDataLoaded({ 29 | @required this.quickNotesStream, 30 | @required this.listsStream, 31 | @required this.userName 32 | }); 33 | } 34 | 35 | 36 | 37 | 38 | class ListIsOpened extends DashboardState{ 39 | final ListEntity list; 40 | 41 | ListIsOpened(this.list): super([list]); 42 | 43 | } 44 | 45 | class ListIsClosed extends DashboardState{ 46 | 47 | } 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/login_bloc/login_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:dartz/dartz.dart'; 3 | import 'package:meta/meta.dart'; 4 | 5 | import 'package:bloc/bloc.dart'; 6 | import 'package:equatable/equatable.dart'; 7 | import 'package:todo_app/src/core/error/exceptions.dart'; 8 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/auth_repository.dart'; 9 | 10 | part 'login_event.dart'; 11 | part 'login_state.dart'; 12 | 13 | class LoginBloc extends Bloc { 14 | AuthRepository _authRepository; 15 | 16 | LoginBloc({ 17 | @required AuthRepository authRepository, 18 | }) : assert(authRepository != null), 19 | _authRepository = authRepository; 20 | @override 21 | LoginState get initialState => LoginState.empty(); 22 | 23 | @override 24 | Stream mapEventToState( 25 | LoginEvent event, 26 | ) async* { 27 | if (event is LoginWithGooglePressed) { 28 | yield LoginState.loading(); 29 | final result = await _authRepository.signInWithGoogle(); 30 | yield result.fold( 31 | (failure) => LoginState.failure(), (user) => LoginState.success()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/login_bloc/login_event.dart: -------------------------------------------------------------------------------- 1 | part of 'login_bloc.dart'; 2 | 3 | abstract class LoginEvent extends Equatable { 4 | final List properties; 5 | const LoginEvent([this.properties = const[]]); 6 | 7 | @override 8 | List get props => [properties]; 9 | } 10 | 11 | 12 | class LoginWithGooglePressed extends LoginEvent{ 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/bloc/login_bloc/login_state.dart: -------------------------------------------------------------------------------- 1 | part of 'login_bloc.dart'; 2 | 3 | @immutable 4 | class LoginState{ 5 | final bool isSuccess; 6 | final bool isFailure; 7 | final bool isSubmitting; 8 | final String errorMessage; 9 | 10 | LoginState({ 11 | @required this.isSuccess, 12 | @required this.isFailure, 13 | @required this.isSubmitting, 14 | this.errorMessage 15 | }); 16 | 17 | factory LoginState.empty(){ 18 | return LoginState( 19 | isFailure: false, 20 | isSubmitting: false, 21 | isSuccess: false 22 | ); 23 | } 24 | 25 | factory LoginState.loading(){ 26 | return LoginState( 27 | isFailure: false, 28 | isSubmitting: true, 29 | isSuccess: false 30 | ); 31 | } 32 | 33 | factory LoginState.failure(){ 34 | return LoginState( 35 | isFailure: true, 36 | isSubmitting: false, 37 | isSuccess: false, 38 | //errorMessage: message 39 | ); 40 | } 41 | 42 | factory LoginState.success(){ 43 | return LoginState( 44 | isFailure: false, 45 | isSubmitting: false, 46 | isSuccess: true 47 | ); 48 | } 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/pages/Dashboard.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/presentation/widgets/no_widget.dart'; 4 | 5 | import '../../../../core/user/user.dart'; 6 | import '../../../../injection_container.dart'; 7 | import '../../domain/entities/List.dart'; 8 | import '../../domain/usecases/dashboard_use_cases.dart'; 9 | import '../bloc/auth_bloc/auth_bloc.dart'; 10 | import '../bloc/dashboard_bloc/dashboard_bloc.dart'; 11 | import '../widgets/all_lists.dart'; 12 | import '../widgets/all_quick_notes.dart'; 13 | import '../widgets/list_bottom_sheet.dart'; 14 | import '../widgets/menu_icon.dart'; 15 | import '../widgets/small_button.dart'; 16 | 17 | class DashboardScreen extends StatelessWidget { 18 | final GlobalKey _scaffoldKey = GlobalKey(); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | 23 | return SafeArea( 24 | child: Scaffold( 25 | backgroundColor: Colors.white, 26 | resizeToAvoidBottomPadding: false, 27 | key: _scaffoldKey, 28 | 29 | body: Dashboard( 30 | bloc: BlocProvider.of(context), 31 | scaffoldKey: _scaffoldKey), 32 | endDrawer: Container( 33 | padding: 34 | EdgeInsets.only(left: 20.0, right: 20.0, top: 40.0, bottom: 20.0), 35 | width: MediaQuery.of(context).size.width, 36 | color: Colors.white, 37 | child: Drawer( 38 | elevation: 0.0, 39 | child: Container( 40 | color: Colors.white, 41 | width: double.infinity, 42 | height: double.infinity, 43 | child: Row( 44 | mainAxisAlignment: MainAxisAlignment.end, 45 | children: [ 46 | Column( 47 | crossAxisAlignment: CrossAxisAlignment.end, 48 | children: [ 49 | SmallButton( 50 | color: Color(0xff878CAC), 51 | icon: Icon( 52 | Icons.clear, 53 | color: Colors.white, 54 | ), 55 | onPressed: () { 56 | Navigator.pop(context); 57 | }, 58 | ), 59 | SizedBox(height: 30.0), 60 | Row( 61 | children: [ 62 | Text( 63 | "+ Add a quick note", 64 | style: TextStyle( 65 | color: Theme.of(context).accentColor, 66 | fontFamily: "Poppins", 67 | fontSize: 20, 68 | fontWeight: FontWeight.bold), 69 | ), 70 | SizedBox(width: 30.0), 71 | SmallButton( 72 | icon: Transform.rotate( 73 | angle: 45.0, 74 | child: Icon( 75 | Icons.attach_file, 76 | color: Colors.white, 77 | ), 78 | ), 79 | onPressed: () async { 80 | print(Navigator); 81 | //Navigator.pop(context); 82 | await Navigator.popAndPushNamed( 83 | context, "/addQuickNote"); 84 | }, 85 | ) 86 | ], 87 | ), 88 | SizedBox(height: 30.0), 89 | Row( 90 | children: [ 91 | Text( 92 | "+ Add a list", 93 | style: TextStyle( 94 | color: Theme.of(context).accentColor, 95 | fontFamily: "Poppins", 96 | fontSize: 20, 97 | fontWeight: FontWeight.bold), 98 | ), 99 | SizedBox(width: 30.0), 100 | SmallButton( 101 | icon: Icon( 102 | Icons.insert_drive_file, 103 | color: Colors.white, 104 | ), 105 | onPressed: () async { 106 | await Navigator.popAndPushNamed( 107 | context, "/addList"); 108 | }, 109 | ) 110 | ], 111 | ), 112 | SizedBox(height: 30.0), 113 | Row( 114 | children: [ 115 | Text( 116 | "Sign out", 117 | style: TextStyle( 118 | color: Theme.of(context).accentColor, 119 | fontFamily: "Poppins", 120 | fontSize: 20, 121 | fontWeight: FontWeight.bold), 122 | ), 123 | SizedBox(width: 30.0), 124 | SmallButton( 125 | color: Color(0xff878CAC), 126 | icon: Icon( 127 | Icons.exit_to_app, 128 | color: Colors.white, 129 | ), 130 | onPressed: () async { 131 | BlocProvider.of(context) 132 | .add(LoggedOut()); 133 | Navigator.of(context).pop(); 134 | }, 135 | ) 136 | ], 137 | ) 138 | ], 139 | ), 140 | ], 141 | ), 142 | ), 143 | ), 144 | ), 145 | ), 146 | ); 147 | } 148 | } 149 | 150 | class Dashboard extends StatefulWidget { 151 | final GlobalKey scaffoldKey; 152 | final DashboardBloc bloc; 153 | Dashboard({ 154 | this.bloc, 155 | this.scaffoldKey, 156 | }); 157 | 158 | @override 159 | _DashboardState createState() => _DashboardState(); 160 | } 161 | 162 | class _DashboardState extends State { 163 | PersistentBottomSheetController _controller; 164 | 165 | @override 166 | void initState() { 167 | super.initState(); 168 | } 169 | 170 | @override 171 | void didChangeDependencies() { 172 | super.didChangeDependencies(); 173 | } 174 | 175 | @override 176 | void dispose() { 177 | super.dispose(); 178 | } 179 | 180 | void _showBottomSheet(ListEntity list) { 181 | 182 | 183 | _controller = 184 | this.widget.scaffoldKey.currentState.showBottomSheet((context) { 185 | return AnimatedPadding( 186 | padding: MediaQuery.of(context).viewInsets, 187 | duration: const Duration(milliseconds: 100), 188 | curve: Curves.decelerate, 189 | child: ListBottomSheet( 190 | controller: _controller, 191 | todoList: list, 192 | closeBottomSheet: () { 193 | _closeBottomSheet(); 194 | }, 195 | ), 196 | ); 197 | }, 198 | shape: RoundedRectangleBorder( 199 | borderRadius: BorderRadius.only(topRight: Radius.circular(50)) 200 | ) 201 | ); 202 | 203 | } 204 | 205 | void _closeBottomSheet() { 206 | _controller.close(); 207 | } 208 | 209 | @override 210 | Widget build(BuildContext context) { 211 | return ListView( 212 | padding: 213 | EdgeInsets.only(left: 30.0, right: 30.0, top: 40.0, bottom: 20.0), 214 | shrinkWrap: true, 215 | children: [ 216 | AppBar( 217 | leading: MenuIcon(), 218 | actions: [NoWidget()], 219 | elevation: 0.0, 220 | backgroundColor: Colors.transparent, 221 | 222 | ), 223 | Row( 224 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 225 | children: [ 226 | Text( 227 | 'Hello ${sl().displayName.toString().split(" ")[0]}', 228 | style: TextStyle( 229 | fontSize: 32.0, 230 | fontFamily: "Poppins", 231 | fontWeight: FontWeight.w200, 232 | color: Theme.of(context).accentColor), 233 | ), 234 | SmallButton( 235 | icon: Icon( 236 | Icons.add, 237 | color: Colors.white, 238 | ), 239 | onPressed: () { 240 | this.widget.scaffoldKey.currentState.openEndDrawer(); 241 | }, 242 | ) 243 | ], 244 | ), 245 | SizedBox(height: 40.0), 246 | Row( 247 | mainAxisAlignment: MainAxisAlignment.start, 248 | children: [ 249 | Text( 250 | "Quick notes", 251 | style: TextStyle( 252 | fontSize: 22.0, 253 | fontWeight: FontWeight.bold, 254 | fontFamily: "Poppins", 255 | color: Theme.of(context).accentColor), 256 | ) 257 | ], 258 | ), 259 | SizedBox(height: 20.0), 260 | AllQuickNotes( 261 | allQuickNotesStream: 262 | sl().call(uid: sl().uid)), 263 | SizedBox(height: 70.0), 264 | Row( 265 | mainAxisAlignment: MainAxisAlignment.start, 266 | children: [ 267 | Text( 268 | "Lists", 269 | style: TextStyle( 270 | fontSize: 22.0, 271 | fontWeight: FontWeight.bold, 272 | fontFamily: "Poppins", 273 | color: Theme.of(context).accentColor), 274 | ), 275 | ], 276 | ), 277 | SizedBox(height: 30.0), 278 | AllLists( 279 | allListsStream: sl().call(uid: sl().uid), 280 | show: this._showBottomSheet) 281 | ], 282 | ); 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/pages/Login.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:todo_app/src/core/user/user.dart'; 5 | import 'package:todo_app/src/features/todo_manager_features/data/datasources/auth_service.dart'; 6 | import 'package:todo_app/src/features/todo_manager_features/presentation/bloc/auth_bloc/auth_bloc.dart'; 7 | import 'package:todo_app/src/features/todo_manager_features/presentation/bloc/login_bloc/login_bloc.dart'; 8 | import 'package:todo_app/src/features/todo_manager_features/presentation/widgets/slide_animation_provider.dart'; 9 | 10 | import '../../../../injection_container.dart'; 11 | 12 | 13 | 14 | 15 | class LoginPage extends StatefulWidget { 16 | @override 17 | _LoginPageState createState() => _LoginPageState(); 18 | } 19 | 20 | class _LoginPageState extends State { 21 | 22 | 23 | 24 | Widget _buildProgressIndicator (BuildContext context){ 25 | 26 | return BlocBuilder( 27 | bloc: BlocProvider.of(context), 28 | builder: (context, LoginState state){ 29 | if(state.isSubmitting){ 30 | return CircularProgressIndicator(); 31 | } 32 | else if(state.isFailure){ 33 | return Text( 34 | "Try again!", 35 | style: TextStyle( 36 | fontFamily: "Poppins", 37 | fontSize: 19, 38 | color: Colors.red 39 | ), 40 | ); 41 | } 42 | 43 | else{ 44 | return SizedBox(height:0); 45 | } 46 | } 47 | ); 48 | 49 | } 50 | 51 | @override 52 | void dispose() { 53 | 54 | super.dispose(); 55 | } 56 | 57 | @override 58 | Widget build(BuildContext context) { 59 | 60 | return Scaffold( 61 | backgroundColor: Colors.white, 62 | body: BlocListener( 63 | bloc: BlocProvider.of(context), 64 | listener: (context, LoginState state) async{ 65 | if (state.isSuccess) { 66 | await sl.allReady(); 67 | BlocProvider.of(context).add(LoggedIn()); 68 | } 69 | else if(state.isFailure){ 70 | Scaffold.of(context).showSnackBar( 71 | SnackBar( 72 | content: Row( 73 | mainAxisAlignment: MainAxisAlignment.center, 74 | children: [ 75 | Text( 76 | "Error Logging in", 77 | style: TextStyle( 78 | color: Colors.red[500], 79 | fontFamily: "Poppins", 80 | fontSize: 20 81 | ), 82 | ), 83 | ], 84 | ) 85 | ) 86 | ); 87 | } 88 | }, 89 | child: Center( 90 | child: Padding( 91 | padding: const EdgeInsets.all(20.0), 92 | child: Column( 93 | mainAxisAlignment: MainAxisAlignment.center, 94 | children: [ 95 | 96 | SlideAnimationWrapper( 97 | fadeDuration: Duration(milliseconds: 1000), 98 | slideDuration: Duration(milliseconds: 1500), 99 | child: Text( 100 | "Hello!", 101 | style: TextStyle( 102 | fontFamily: "Poppins", 103 | fontWeight: FontWeight.normal, 104 | fontSize: 50.0, 105 | color: Theme.of(context).accentColor 106 | ), 107 | ), 108 | ), 109 | SlideAnimationWrapper( 110 | fadeDuration: Duration(milliseconds: 1200), 111 | slideDuration: Duration(milliseconds: 1700), 112 | child: Text( 113 | "Seems you aren't signed in", 114 | style: TextStyle( 115 | fontFamily: "Poppins", 116 | fontWeight: FontWeight.w200, 117 | fontSize: 20.0, 118 | color: Theme.of(context).accentColor 119 | ), 120 | ), 121 | ), 122 | SizedBox(height: 40), 123 | SlideAnimationWrapper( 124 | fadeDuration: Duration(milliseconds: 1500), 125 | slideDuration: Duration(milliseconds: 1900), 126 | child: Text( 127 | "Please sign in with your Google\naccount", 128 | textAlign: TextAlign.center, 129 | style: TextStyle( 130 | fontFamily: "Poppins", 131 | fontWeight: FontWeight.w200, 132 | fontSize: 20.0, 133 | color: Theme.of(context).accentColor 134 | ), 135 | ), 136 | ), 137 | SizedBox(height: 40), 138 | SlideAnimationWrapper( 139 | fadeDuration: Duration(milliseconds: 1600), 140 | slideDuration: Duration(milliseconds: 2000), 141 | child: RaisedButton( 142 | color: Theme.of(context).primaryColor, 143 | 144 | shape: RoundedRectangleBorder( 145 | borderRadius: BorderRadius.circular(10.0), 146 | ), 147 | padding: EdgeInsets.symmetric(vertical: 15, horizontal: 25), 148 | onPressed: (){ 149 | BlocProvider.of(context).add(LoginWithGooglePressed()); 150 | }, 151 | child: Text( 152 | "Sign in with Google", 153 | style: TextStyle( 154 | fontFamily: "Poppins", 155 | color: Colors.white, 156 | fontSize: 20.0 157 | ), 158 | ) 159 | ), 160 | ), 161 | SizedBox(height: 20.0), 162 | 163 | _buildProgressIndicator(context) 164 | 165 | ], 166 | ), 167 | ), 168 | ), 169 | ), 170 | 171 | ); 172 | } 173 | } 174 | 175 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/pages/add_new_list.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:todo_app/src/features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_bloc.dart' 5 | as event; 6 | 7 | import '../../../../core/constants/Constants.dart'; 8 | import '../../domain/entities/ListTodo.dart'; 9 | import '../bloc/add_list_bloc/add_list_bloc.dart'; 10 | import '../widgets/small_button.dart'; 11 | 12 | class AddList extends StatefulWidget { 13 | 14 | @override 15 | _AddListState createState() => _AddListState(); 16 | } 17 | 18 | class _AddListState extends State { 19 | Color _selectedColor = listOfColorsForColorPicker[2]; 20 | List _listOfTodos = []; 21 | 22 | final TextEditingController _newTodoController = new TextEditingController(); 23 | final TextEditingController _titleController = new TextEditingController(); 24 | final GlobalKey _formKey = new GlobalKey(); 25 | 26 | @override 27 | void dispose() { 28 | 29 | super.dispose(); 30 | } 31 | @override 32 | Widget build(BuildContext context) { 33 | 34 | return BlocListener( 35 | listener: (context, state) { 36 | if (state is AddingList) { 37 | if (_formKey.currentState.validate()) { 38 | _formKey.currentState.save(); 39 | showDialog( 40 | context: context, 41 | builder: (context) { 42 | return AlertDialog( 43 | content: Row( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | children: [ 46 | Container( 47 | width: 40, 48 | height: 40, 49 | child: CircularProgressIndicator()), 50 | ], 51 | ), 52 | ); 53 | }); 54 | } 55 | } else if (state is ListAdded) { 56 | Navigator.pop(context); 57 | showDialog( 58 | context: context, 59 | builder: (context) { 60 | return AlertDialog( 61 | title: Text("New List added"), 62 | ); 63 | }); 64 | setState(() { 65 | _titleController.text = ""; 66 | _listOfTodos.clear(); 67 | }); 68 | } 69 | }, 70 | child: Scaffold( 71 | backgroundColor: Colors.white, 72 | body: ListView(children: [ 73 | Padding( 74 | padding: 75 | const EdgeInsets.only(top: 20.0, left: 10.0, right: 20.0), 76 | child: AppBar( 77 | elevation: 0.0, 78 | backgroundColor: Colors.transparent, 79 | leading: Row( 80 | mainAxisAlignment: MainAxisAlignment.start, 81 | children: [ 82 | IconButton( 83 | color: Colors.yellow, 84 | padding: EdgeInsets.all(0.0), 85 | onPressed: () { 86 | Navigator.pop(context); 87 | }, 88 | icon: Icon(Icons.clear, 89 | size: 26.0, color: Color(0xff616B77)), 90 | ), 91 | ], 92 | ), 93 | ), 94 | ), 95 | Padding( 96 | padding: EdgeInsets.only( 97 | left: 25.0, right: 25.0, top: 10.0, bottom: 20.0), 98 | child: Column(children: [ 99 | Form( 100 | key: _formKey, 101 | child: Row( 102 | children: [ 103 | Expanded( 104 | child: TextFormField( 105 | controller: _titleController, 106 | validator: (val){ 107 | if (val.isEmpty) { 108 | return 'Please enter some text'; 109 | } 110 | return null; 111 | }, 112 | 113 | style: TextStyle( 114 | fontSize: 27.0, 115 | fontFamily: "Poppins", 116 | color: Theme.of(context).accentColor), 117 | decoration: InputDecoration( 118 | hintText: "Title of new list...", 119 | border: UnderlineInputBorder( 120 | borderSide: BorderSide.none)), 121 | ), 122 | ), 123 | SizedBox(width: 20.0), 124 | SmallButton( 125 | icon: Icon( 126 | Icons.check, 127 | color: Colors.white, 128 | ), 129 | onPressed: () async { 130 | if(_formKey.currentState.validate()){ 131 | BlocProvider.of(context).add(event.AddList( 132 | listBackgroundColor: 133 | "#${_selectedColor.toString().substring(10, 16)}", 134 | listOfTodos: _listOfTodos, 135 | listTitle: _titleController.text)); 136 | } 137 | 138 | }) 139 | ], 140 | ), 141 | ), 142 | SizedBox(height: 30.0), 143 | Row( 144 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 145 | children: listOfColorsForColorPicker.map((Color color) { 146 | return GestureDetector( 147 | onTap: () { 148 | setState(() { 149 | _selectedColor = color; 150 | }); 151 | }, 152 | child: Container( 153 | height: 30, 154 | width: 30, 155 | decoration: BoxDecoration( 156 | borderRadius: BorderRadius.circular(30.0), 157 | color: color, 158 | border: color == Color(0xffFFFFFF) 159 | ? Border.all( 160 | width: 1, 161 | color: Theme.of(context).accentColor) 162 | : Border.all(width: 0, color: color), 163 | ), 164 | child: Center( 165 | child: _selectedColor == color 166 | ? Container( 167 | height: 10, 168 | width: 10, 169 | decoration: BoxDecoration( 170 | color: Colors.white, 171 | borderRadius: 172 | BorderRadius.circular(10)), 173 | ) 174 | : SizedBox(width: 0, height: 0), 175 | ), 176 | ), 177 | ); 178 | }).toList(), 179 | ), 180 | SizedBox(height: 50.0), 181 | Row( 182 | mainAxisAlignment: MainAxisAlignment.start, 183 | children: [ 184 | Text( 185 | "List items", 186 | style: TextStyle( 187 | fontFamily: "Poppins", 188 | fontWeight: FontWeight.bold, 189 | fontSize: 21, 190 | color: Theme.of(context).accentColor), 191 | ) 192 | ], 193 | ), 194 | SizedBox(height: 10), 195 | _listOfTodos.length >= 1 196 | ? Column( 197 | children: _listOfTodos.map((ListTodo todo) { 198 | return Container( 199 | margin: EdgeInsets.only(bottom: 30.0), 200 | child: Row( 201 | children: [ 202 | Container( 203 | height: 7, 204 | width: 7, 205 | decoration: BoxDecoration( 206 | borderRadius: 207 | BorderRadius.circular(15.0), 208 | color: _selectedColor), 209 | ), 210 | SizedBox(width: 40.0), 211 | Container( 212 | width: MediaQuery.of(context).size.width * 0.8 > 300 ? 300: MediaQuery.of(context).size.width, 213 | child: Text( 214 | todo.title, 215 | style: TextStyle( 216 | fontSize: 20.0, 217 | fontFamily: "Poppins", 218 | color: Theme.of(context).accentColor), 219 | ), 220 | ) 221 | ], 222 | ), 223 | ); 224 | }).toList(), 225 | ) 226 | : SizedBox(height: 0, width: 0), 227 | SizedBox(height: 10.0), 228 | Row( 229 | children: [ 230 | GestureDetector( 231 | onTap: () { 232 | setState(() { 233 | _listOfTodos.add(new ListTodo( 234 | isDone: false, 235 | title: _newTodoController.text, 236 | details: "")); 237 | print(_listOfTodos[0].title); 238 | _newTodoController.text = ""; 239 | }); 240 | }, 241 | child: Container( 242 | height: 25, 243 | width: 25, 244 | decoration: BoxDecoration( 245 | borderRadius: BorderRadius.circular(5.0), 246 | color: Theme.of(context).primaryColor), 247 | child: Center( 248 | child: Icon( 249 | Icons.add, 250 | color: Colors.white, 251 | ), 252 | ), 253 | ), 254 | ), 255 | SizedBox(width: 40.0), 256 | Expanded( 257 | child: TextField( 258 | controller: _newTodoController, 259 | style: TextStyle( 260 | fontSize: 20.0, 261 | fontFamily: "Poppins", 262 | color: Theme.of(context).accentColor), 263 | decoration: InputDecoration( 264 | hintText: "Add new note", 265 | border: UnderlineInputBorder( 266 | borderSide: BorderSide.none)), 267 | ), 268 | ), 269 | ], 270 | ) 271 | ])), 272 | ])), 273 | ); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/pages/add_quick_note.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:random_words/random_words.dart'; 6 | import 'package:todo_app/src/core/priority/Priority.dart'; 7 | import 'package:todo_app/src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_bloc.dart' 8 | as bloc; 9 | import 'package:todo_app/src/features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_bloc.dart'; 10 | import 'package:todo_app/src/features/todo_manager_features/presentation/widgets/select_priority_button.dart'; 11 | import 'package:todo_app/src/features/todo_manager_features/presentation/widgets/small_button.dart'; 12 | import 'package:todo_app/src/features/todo_manager_features/presentation/widgets/suggestion_tile.dart'; 13 | 14 | class AddQuickNote extends StatefulWidget { 15 | @override 16 | _AddQuickNoteState createState() => _AddQuickNoteState(); 17 | } 18 | 19 | class _AddQuickNoteState extends State { 20 | String _quickNoteTitle; 21 | StreamController _suggestionsTextController = 22 | new StreamController(); 23 | Priority _quickNotePriority = Priority.fromPriorityValue(3); 24 | final List _priorityValues = [1, 2, 3]; 25 | int _selectedPriorityValue = 3; 26 | 27 | final TextEditingController _textController = new TextEditingController(); 28 | 29 | final Iterable _suggestions = [ 30 | ...adjectives.take(5), 31 | ...nouns.take(10) 32 | ]; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | _suggestionsTextController.stream.listen((String suggestion) { 38 | _textController.value = _textController.value 39 | .copyWith(text: _textController.text + suggestion + " "); 40 | _textController.selection = TextSelection.fromPosition( 41 | TextPosition(offset: _textController.text.length)); 42 | }); 43 | } 44 | 45 | @override 46 | void dispose() { 47 | _suggestionsTextController.close(); 48 | _textController.dispose(); 49 | 50 | super.dispose(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | FocusNode _textInputFocusNode = new FocusNode(); 56 | 57 | _textController.addListener(() { 58 | _quickNoteTitle = _textController.text; 59 | }); 60 | return BlocListener( 61 | listener: (context, state) { 62 | if (state is bloc.QuickNoteAdded) { 63 | showDialog( 64 | context: context, 65 | builder: (context) { 66 | return AlertDialog( 67 | title: Text("New Quick note added"), 68 | ); 69 | }); 70 | 71 | //reset default values 72 | _suggestionsTextController.sink.add(""); 73 | _quickNoteTitle = ""; 74 | _textController.text = ""; 75 | setState(() { 76 | _selectedPriorityValue = 3; 77 | }); 78 | _quickNotePriority = Priority.fromPriorityValue(3); 79 | 80 | Future.delayed(Duration(milliseconds: 500), () { 81 | Navigator.pop(context); 82 | }); 83 | } 84 | }, 85 | child: Scaffold( 86 | backgroundColor: Colors.white, 87 | body: ListView( 88 | children: [ 89 | Padding( 90 | padding: 91 | const EdgeInsets.only(top: 20.0, left: 10.0, right: 20.0), 92 | child: AppBar( 93 | elevation: 0.0, 94 | backgroundColor: Colors.transparent, 95 | leading: Row( 96 | mainAxisAlignment: MainAxisAlignment.start, 97 | children: [ 98 | IconButton( 99 | color: Colors.yellow, 100 | padding: EdgeInsets.all(0.0), 101 | onPressed: () { 102 | Navigator.of(context).pop(); 103 | }, 104 | icon: Icon(Icons.clear, 105 | size: 26.0, color: Color(0xff616B77)), 106 | ), 107 | ], 108 | ), 109 | ), 110 | ), 111 | Padding( 112 | padding: EdgeInsets.only( 113 | left: 25.0, right: 25.0, top: 10.0, bottom: 20.0), 114 | child: Column( 115 | children: [ 116 | Row( 117 | children: [ 118 | Expanded( 119 | child: TextField( 120 | focusNode: _textInputFocusNode, 121 | controller: _textController, 122 | style: TextStyle( 123 | fontSize: 27.0, 124 | fontFamily: "Poppins", 125 | color: Theme.of(context).accentColor), 126 | decoration: InputDecoration( 127 | hintText: "Write your quick note", 128 | border: InputBorder.none, 129 | ), 130 | ), 131 | ), 132 | SizedBox(width: 20.0), 133 | SmallButton( 134 | icon: Icon( 135 | Icons.check, 136 | color: Colors.white, 137 | ), 138 | onPressed: () { 139 | BlocProvider.of(context) 140 | .add(bloc.AddQuickNote({ 141 | "priority": _quickNotePriority.priorityValue, 142 | "title": _quickNoteTitle, 143 | "isDone": false 144 | })); 145 | }, 146 | ) 147 | ], 148 | ), 149 | SizedBox(height: 30.0), 150 | Row( 151 | children: [ 152 | Text( 153 | "Suggestions", 154 | style: TextStyle( 155 | fontSize: 20.0, 156 | color: Theme.of(context).accentColor), 157 | ) 158 | ], 159 | ), 160 | SizedBox(height: 20.0), 161 | Container( 162 | child: Wrap( 163 | crossAxisAlignment: WrapCrossAlignment.start, 164 | children: _suggestions.map((word) { 165 | return SuggestionTile( 166 | title: word.toString(), 167 | onTap: () { 168 | _suggestionsTextController.sink.add(word); 169 | }, 170 | ); 171 | }).toList(), 172 | ), 173 | ), 174 | SizedBox(height: 30.0), 175 | Row( 176 | children: [ 177 | Text( 178 | "Priority", 179 | style: TextStyle( 180 | fontSize: 20.0, 181 | color: Theme.of(context).accentColor), 182 | ) 183 | ], 184 | ), 185 | SizedBox(height: 15.0), 186 | Row( 187 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 188 | children: _priorityValues.map((priority) { 189 | return SelectPriorityButton( 190 | priority: Priority.fromPriorityValue(priority), 191 | onPressed: () { 192 | setState(() { 193 | _quickNotePriority = 194 | Priority.fromPriorityValue(priority); 195 | 196 | _selectedPriorityValue = priority; 197 | }); 198 | }, 199 | isSelected: _selectedPriorityValue == priority); 200 | }).toList(), 201 | ) 202 | ], 203 | ), 204 | ) 205 | ], 206 | ), 207 | ), 208 | ); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/all_lists.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../data/models/ListModel.dart'; 5 | import '../../domain/entities/List.dart'; 6 | import 'list_widget.dart'; 7 | 8 | class AllLists extends StatelessWidget { 9 | final Stream allListsStream; 10 | final Function(ListEntity) show; 11 | 12 | AllLists({@required this.allListsStream, @required this.show}); 13 | @override 14 | Widget build(BuildContext context) { 15 | return StreamBuilder( 16 | stream: allListsStream, 17 | builder: (context, snapshot) { 18 | if (snapshot.hasData) { 19 | if (snapshot.data.documents.length == 0) { 20 | return (Row( 21 | children: [ 22 | Text( 23 | "No Lists available", 24 | style: TextStyle( 25 | fontFamily: "Poppins", 26 | fontSize: 18.0, 27 | color: Theme.of(context).accentColor), 28 | ) 29 | ], 30 | )); 31 | } 32 | return Container( 33 | width: MediaQuery.of(context).size.width - 40, 34 | height: 450, 35 | child: ListView( 36 | shrinkWrap: true, 37 | scrollDirection: Axis.horizontal, 38 | children: [ 39 | Row( 40 | children: snapshot.data.documents 41 | .map((DocumentSnapshot lists) { 42 | ListEntity _newTodoList = 43 | ListModel.fromFirestoreDoc(lists); 44 | 45 | return ListWidget( 46 | key: UniqueKey(), 47 | todoList: _newTodoList, 48 | onTap: () { 49 | print("tap list"); 50 | print(_newTodoList.backgroundColor.toString()); 51 | print(_newTodoList.listTitle); 52 | print(_newTodoList.listId); 53 | show(_newTodoList); 54 | //BlocProvider.of(context).add(OpenList(_newTodoList)); 55 | }, 56 | ); 57 | }).toList()) 58 | ]), 59 | ); 60 | } 61 | if (snapshot.connectionState == ConnectionState.waiting) { 62 | return Row( 63 | mainAxisAlignment: MainAxisAlignment.center, 64 | children: [ 65 | Container( 66 | height: 40, width: 40, child: CircularProgressIndicator()), 67 | ], 68 | ); 69 | } 70 | }); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/all_quick_notes.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/data/models/QuickNoteModel.dart'; 4 | 5 | 6 | import 'no_widget.dart'; 7 | import 'quick_note_widget.dart'; 8 | 9 | class AllQuickNotes extends StatelessWidget { 10 | final Stream allQuickNotesStream; 11 | 12 | AllQuickNotes({@required this.allQuickNotesStream}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return StreamBuilder( 17 | stream: allQuickNotesStream, 18 | builder: (context, snapshot) { 19 | if (snapshot.hasData) { 20 | if (snapshot.data.documents.length == 0) { 21 | return Text( 22 | "No Quick Notes available", 23 | style: TextStyle( 24 | fontFamily: "Poppins", 25 | fontSize: 18.0, 26 | color: Theme.of(context).accentColor), 27 | ); 28 | } 29 | return Column( 30 | children: [ 31 | ConstrainedBox( 32 | constraints: BoxConstraints( 33 | minHeight: 100, 34 | maxHeight: MediaQuery.of(context).size.height * 0.4, 35 | ), 36 | child: (ListView( 37 | shrinkWrap: true, 38 | padding: EdgeInsets.all(0), 39 | children: snapshot.data.documents 40 | .map((DocumentSnapshot document) { 41 | return QuickNoteWidget(key: UniqueKey(), quickNoteInfo: QuickNoteModel.fromFirestoreDoc(document)); 42 | }).toList())), 43 | ), 44 | SizedBox(height: 30.0), 45 | ], 46 | ); 47 | } 48 | if (snapshot.connectionState == ConnectionState.waiting) { 49 | return Row( 50 | mainAxisAlignment: MainAxisAlignment.center, 51 | children: [ 52 | (CircularProgressIndicator()), 53 | ], 54 | ); 55 | } 56 | return NoWidget(); 57 | }, 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/color_picker_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ColorPickerButton extends StatelessWidget { 4 | final VoidCallback onTap; 5 | final Color color; 6 | final bool isSelectedColor; 7 | 8 | ColorPickerButton({ 9 | this.onTap, 10 | this.color, 11 | this.isSelectedColor 12 | }); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | height:20, 18 | width: 20, 19 | margin: EdgeInsets.only(right: 10.0), 20 | decoration: BoxDecoration( 21 | color: this.color, 22 | border: this.isSelectedColor? Border.all( 23 | width: 5, 24 | color: Colors.white 25 | ): Border.all(width:0, color: this.color), 26 | borderRadius: BorderRadius.circular(15.0) 27 | ), 28 | child: InkWell( 29 | onTap: onTap, 30 | splashColor: Colors.red, 31 | ), 32 | ); 33 | } 34 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/list_bottom_sheet.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 4 | 5 | import '../../../../core/constants/Constants.dart'; 6 | import '../../../../core/user/user.dart'; 7 | import '../../../../injection_container.dart'; 8 | import '../../data/models/ListTodoModel.dart'; 9 | import '../../domain/entities/List.dart'; 10 | import '../../domain/usecases/dashboard_use_cases.dart'; 11 | import '../../domain/usecases/edit_list.dart'; 12 | import 'color_picker_button.dart'; 13 | import 'list_todo_widget.dart'; 14 | 15 | class ListBottomSheet extends StatefulWidget { 16 | final ListEntity todoList; 17 | final VoidCallback closeBottomSheet; 18 | final PersistentBottomSheetController controller; 19 | 20 | ListBottomSheet({ 21 | this.todoList, 22 | this.closeBottomSheet, 23 | this.controller 24 | }); 25 | 26 | @override 27 | _ListBottomSheetState createState() => _ListBottomSheetState(); 28 | } 29 | 30 | class _ListBottomSheetState extends State { 31 | bool _inEditingMode = false; 32 | final TextEditingController _todoTitleController = new TextEditingController(); 33 | final TextEditingController _newTodoController = new TextEditingController(); 34 | 35 | Color _temporaryColor; 36 | 37 | @override 38 | void initState() { 39 | super.initState(); 40 | _temporaryColor = widget.todoList.backgroundColor; 41 | 42 | _todoTitleController.text = widget.todoList.listTitle; 43 | } 44 | 45 | @override 46 | void didChangeDependencies() { 47 | super.didChangeDependencies(); 48 | } 49 | 50 | @override 51 | void dispose() { 52 | _todoTitleController.dispose(); 53 | _newTodoController.dispose(); 54 | 55 | super.dispose(); 56 | } 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return Container( 61 | padding: EdgeInsets.only(left: 40, right: 40, top: 15, bottom: 30), 62 | height: MediaQuery.of(context).size.height * 0.7, 63 | width: double.infinity, 64 | decoration: BoxDecoration( 65 | color: _temporaryColor, 66 | borderRadius: BorderRadius.only(topRight: Radius.circular(50))), 67 | child: Column( 68 | children: [ 69 | Row( 70 | mainAxisAlignment: MainAxisAlignment.center, 71 | children: [ 72 | IconButton( 73 | icon: Icon( 74 | Icons.keyboard_arrow_down, 75 | color: Colors.white, 76 | size: 25, 77 | ), 78 | onPressed: () { 79 | //Navigator.pop(context); 80 | widget.closeBottomSheet(); 81 | } 82 | ) 83 | ], 84 | ), 85 | Expanded( 86 | child: ListView( 87 | children: [ 88 | SizedBox( 89 | height: 20.0, 90 | ), 91 | Container( 92 | decoration: BoxDecoration( 93 | border: Border( 94 | bottom: BorderSide( 95 | color: _inEditingMode == true 96 | ? Colors.blue[400] 97 | : Color(0x80FFFFFF)))), 98 | child: Row( 99 | children: [ 100 | Expanded( 101 | child: TextField( 102 | autofocus: true, 103 | enabled: _inEditingMode, 104 | style: TextStyle( 105 | fontFamily: "Poppins", 106 | color: Colors.white, 107 | fontSize: 25.0), 108 | controller: _todoTitleController, 109 | decoration: InputDecoration( 110 | border: InputBorder.none, 111 | hintText: "List title", 112 | hintStyle: TextStyle(color: Color(0x80ffffff))), 113 | ), 114 | ), 115 | SizedBox(width: 20.0), 116 | IconButton( 117 | icon: Icon( 118 | _inEditingMode ? Icons.check : Icons.edit, 119 | color: Colors.white, 120 | ), 121 | onPressed: () { 122 | 123 | widget.controller.setState(() { 124 | _inEditingMode = !_inEditingMode; 125 | }); 126 | if (_inEditingMode == false) { 127 | print("Not in editing mode"); 128 | sl().call( 129 | uid: sl().uid, 130 | listId: widget.todoList.listId, 131 | newTitle: _todoTitleController.text); 132 | sl()( 133 | uid: sl().uid, 134 | listId: widget.todoList.listId, 135 | newColor: _temporaryColor); 136 | } 137 | }, 138 | ) 139 | ], 140 | ), 141 | ), 142 | SizedBox(height: 20.0), 143 | _inEditingMode 144 | ? Column( 145 | children: [ 146 | Row( 147 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 148 | children: [ 149 | Row( 150 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 151 | children: listOfColorsForColorPicker.map((color) { 152 | return ColorPickerButton( 153 | isSelectedColor: _temporaryColor == color, 154 | color: color, 155 | onTap: () { 156 | widget.controller.setState(() { 157 | _temporaryColor = color; 158 | }); 159 | }, 160 | ); 161 | }).toList(), 162 | ), 163 | IconButton( 164 | icon: Icon( 165 | Icons.delete, 166 | color: Colors.white, 167 | ), 168 | onPressed: () { 169 | showDialog( 170 | context: context, 171 | builder: (BuildContext context) { 172 | return AlertDialog( 173 | title: Text("Delete this list"), 174 | content: Text( 175 | "Are you sure you want to delete this list?"), 176 | actions: [ 177 | FlatButton( 178 | child: Text("YES"), 179 | onPressed: () { 180 | Navigator.pop(context); 181 | 182 | widget.closeBottomSheet(); 183 | 184 | sl().call( 185 | uid: sl().uid, 186 | listId: 187 | widget.todoList.listId); 188 | }, 189 | ), 190 | FlatButton( 191 | child: Text("NO"), 192 | onPressed: () { 193 | Navigator.of(context).pop(); 194 | }, 195 | ), 196 | ], 197 | ); 198 | }); 199 | }, 200 | ) 201 | ], 202 | ), 203 | Container( 204 | width: double.infinity, 205 | height: 1, 206 | color: Color(0x80ffffff)) 207 | ], 208 | ) 209 | : SizedBox(height: 0.0), 210 | SizedBox(height: 20.0), 211 | StreamBuilder( 212 | stream: sl().call( 213 | uid: sl().uid, listId: widget.todoList.listId), 214 | builder: (context, snapshot) { 215 | if (snapshot.connectionState == ConnectionState.waiting) { 216 | return Row( 217 | mainAxisAlignment: MainAxisAlignment.center, 218 | children: [ 219 | Container( 220 | width: 50, 221 | height: 50, 222 | child: CircularProgressIndicator()), 223 | ], 224 | ); 225 | } 226 | if (snapshot.hasData) { 227 | return Container( 228 | child: Column( 229 | crossAxisAlignment: CrossAxisAlignment.start, 230 | children: 231 | snapshot.data.documents.map((todo) { 232 | return Container( 233 | margin: EdgeInsets.only(bottom: 5.0), 234 | width: double.infinity, 235 | child: ListTodoWidget( 236 | enableAddingDetails: _inEditingMode, 237 | checkboxAndTextSpace: 30.0, 238 | todo: ListTodoModel.fromFirestoreInfo( 239 | listId: widget.todoList.listId, 240 | todoDoc: todo), 241 | showDetails: true), 242 | ); 243 | }).toList()), 244 | ); 245 | } 246 | }), 247 | /* */ 248 | Row( 249 | children: [ 250 | GestureDetector( 251 | onTap: () { 252 | sl()( 253 | uid: sl().uid, 254 | todoTitle: _newTodoController.text, 255 | listId: widget.todoList.listId); 256 | _newTodoController.text = ""; 257 | }, 258 | child: Container( 259 | height: 20, 260 | width: 20, 261 | decoration: BoxDecoration( 262 | borderRadius: BorderRadius.circular(5.0), 263 | color: Colors.white, 264 | ), 265 | child: Center( 266 | child: Icon( 267 | Icons.add, 268 | size: 16, 269 | color: _temporaryColor, 270 | ), 271 | ), 272 | ), 273 | ), 274 | SizedBox(width: 30.0), 275 | Expanded( 276 | child: TextField( 277 | controller: _newTodoController, 278 | style: TextStyle( 279 | fontSize: 16.0, 280 | fontFamily: "Poppins", 281 | color: Colors.white), 282 | decoration: InputDecoration( 283 | border: InputBorder.none, hintText: "Add a new todo"), 284 | ), 285 | ), 286 | ], 287 | ) 288 | ], 289 | ), 290 | ), 291 | ], 292 | ), 293 | ); 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/list_todo_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../../core/user/user.dart'; 4 | import '../../../../injection_container.dart'; 5 | import '../../domain/entities/ListTodo.dart'; 6 | import '../../domain/usecases/edit_list_todo.dart'; 7 | import 'no_widget.dart'; 8 | 9 | class ListTodoWidget extends StatefulWidget { 10 | final ListTodo todo; 11 | final bool showDetails; 12 | final double checkboxAndTextSpace; 13 | final bool enableAddingDetails; 14 | 15 | ListTodoWidget({ 16 | this.todo, 17 | this.showDetails, 18 | this.checkboxAndTextSpace, 19 | this.enableAddingDetails = false 20 | }); 21 | @override 22 | _ListTodoWidgetState createState() => _ListTodoWidgetState(); 23 | } 24 | 25 | class _ListTodoWidgetState extends State { 26 | @override 27 | Widget build(BuildContext context) { 28 | final ListTodo _listTodoPassed = widget.todo; 29 | return Container( 30 | margin: EdgeInsets.only(bottom: 20), 31 | child: Row( 32 | crossAxisAlignment: CrossAxisAlignment.start, 33 | children: [ 34 | Container( 35 | width: 20.0, 36 | height: 20.0, 37 | child: Checkbox( 38 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, 39 | value: _listTodoPassed.isDone, 40 | activeColor: Color(0x80ffffff), 41 | 42 | 43 | onChanged: (bool newValue) async{ 44 | setState(() { 45 | _listTodoPassed.isDone = newValue; 46 | }); 47 | await Future.delayed(Duration(milliseconds: 250)); 48 | sl().call( 49 | uid:sl().uid, 50 | todoId: widget.todo.todoId, 51 | listId: widget.todo.listId, 52 | isDone: newValue 53 | ); 54 | }, 55 | ), 56 | ), 57 | SizedBox( 58 | width: widget.checkboxAndTextSpace != null ? widget.checkboxAndTextSpace : 20.0, 59 | ), 60 | Expanded( 61 | child: Column( 62 | crossAxisAlignment: CrossAxisAlignment.start, 63 | children: [ 64 | Column( 65 | children: [ 66 | RichText( 67 | maxLines: widget.showDetails? null: 1, 68 | overflow: widget.showDetails ? TextOverflow.visible :TextOverflow.ellipsis, 69 | text: TextSpan( 70 | text: _listTodoPassed.title, 71 | 72 | style: TextStyle( 73 | fontFamily: "Poppins", 74 | fontSize: 16, 75 | 76 | decoration: _listTodoPassed.isDone ? TextDecoration.lineThrough :TextDecoration.none, 77 | color: _listTodoPassed.isDone ? Color(0x80ffffff):Colors.white 78 | ), 79 | 80 | ), 81 | 82 | ), 83 | /*Text( 84 | _listTodoPassed.title, 85 | maxLines: widget.enableAddingDetails? null: 3, 86 | softWrap: true, 87 | 88 | style: TextStyle( 89 | fontFamily: "Poppins", 90 | fontSize: 16, 91 | 92 | decoration: _listTodoPassed.isDone ? TextDecoration.lineThrough :TextDecoration.none, 93 | color: _listTodoPassed.isDone ? Color(0x80ffffff):Colors.white 94 | ), 95 | ),*/ 96 | ], 97 | ), 98 | widget.showDetails && widget.todo.details != "" ? SizedBox(height: 20.0): SizedBox(height: 0.0), 99 | widget.showDetails && widget.todo.details != "" ? Container( 100 | width: MediaQuery.of(context).size.width * 0.7 - 40, 101 | child: Text( 102 | widget.todo.details, 103 | 104 | softWrap: true, 105 | style: TextStyle( 106 | color: Color(0x80ffffff), 107 | fontSize: 15.0, 108 | fontFamily: "Poppins", 109 | fontWeight: FontWeight.w200 110 | ), 111 | ), 112 | ): NoWidget() 113 | 114 | ], 115 | ), 116 | ), 117 | ], 118 | ), 119 | ); 120 | } 121 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/list_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:todo_app/src/core/user/user.dart'; 4 | import 'package:todo_app/src/features/todo_manager_features/data/models/ListTodoModel.dart'; 5 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/List.dart'; 6 | import 'package:todo_app/src/features/todo_manager_features/domain/usecases/edit_list.dart'; 7 | 8 | import '../../../../injection_container.dart'; 9 | import 'list_todo_widget.dart'; 10 | 11 | class ListWidget extends StatelessWidget { 12 | final Key key; 13 | final ListEntity todoList; 14 | final VoidCallback onTap; 15 | 16 | ListWidget( 17 | {@required this.key, @required this.todoList, @required this.onTap}) 18 | : super(key: key); 19 | 20 | Widget build(BuildContext context) { 21 | return Stack( 22 | children: [ 23 | GestureDetector( 24 | onTap: onTap, 25 | child: Container( 26 | margin: EdgeInsets.fromLTRB(0.0, 0.0, 40.0, 0.0), 27 | height: 450, 28 | width: 250.0, 29 | decoration: BoxDecoration( 30 | color: todoList.backgroundColor, 31 | boxShadow: [ 32 | BoxShadow( 33 | color: todoList.backgroundColor, 34 | offset: Offset(0, 0), 35 | blurRadius: 3, 36 | spreadRadius: 0) 37 | ], 38 | borderRadius: BorderRadius.only( 39 | topRight: Radius.circular(35.0), 40 | bottomLeft: Radius.circular(35.0), 41 | bottomRight: Radius.circular(35.0))), 42 | child: Container( 43 | child: Column( 44 | mainAxisSize: MainAxisSize.max, 45 | crossAxisAlignment: CrossAxisAlignment.start, 46 | children: [ 47 | Padding( 48 | padding: const EdgeInsets.only( 49 | left: 30.0, right: 30.0, top: 20.0, bottom: 20.0), 50 | child: Row( 51 | mainAxisAlignment: MainAxisAlignment.start, 52 | children: [ 53 | Container( 54 | width: 190.0, 55 | //color: Colors.red, 56 | child: Text( 57 | todoList.listTitle, 58 | style: TextStyle( 59 | fontFamily: "Poppins", 60 | fontSize: 20, 61 | fontWeight: FontWeight.bold, 62 | color: Colors.white), 63 | ), 64 | ), 65 | ], 66 | ), 67 | ), 68 | Container( 69 | height: 1, 70 | width: 250, 71 | color: Color(0x33ffffff), 72 | ), 73 | Expanded( 74 | child: Padding( 75 | padding: const EdgeInsets.only( 76 | left: 25.0, right: 25.0, top: 10.0, bottom: 20.0), 77 | child: StreamBuilder( 78 | stream: todoList.listOfTodosStream, 79 | builder: (context, snapshot) { 80 | if (snapshot.hasData) { 81 | int _length = snapshot.data.documents.length; 82 | return Column( 83 | children: [ 84 | Column( 85 | crossAxisAlignment: 86 | CrossAxisAlignment.start, 87 | children: snapshot.data.documents 88 | .take(6) 89 | .map((todo) { 90 | return ListTodoWidget( 91 | todo: ListTodoModel.fromFirestoreInfo( 92 | listId: todoList.listId, 93 | todoDoc: todo), 94 | showDetails: false, 95 | ); 96 | }).toList(), 97 | ), 98 | _length > 4 99 | ? Row( 100 | mainAxisAlignment: 101 | MainAxisAlignment.start, 102 | children: [ 103 | Text( 104 | "...", 105 | style: TextStyle( 106 | color: Colors.white, 107 | fontSize: 30.0, 108 | fontFamily: "Poppins", 109 | letterSpacing: 10), 110 | ), 111 | ], 112 | ) 113 | : SizedBox(height: 0) 114 | ], 115 | ); 116 | } 117 | if (snapshot.connectionState == 118 | ConnectionState.waiting) { 119 | return Row( 120 | mainAxisAlignment: MainAxisAlignment.center, 121 | children: [ 122 | Container( 123 | width: 40, 124 | height: 40, 125 | child: CircularProgressIndicator() 126 | ), 127 | ], 128 | ); 129 | } 130 | return SizedBox(height: 0); 131 | }), 132 | /**/ 133 | ), 134 | ) 135 | ], 136 | ), 137 | ), 138 | ), 139 | ), 140 | /*Positioned( 141 | child: Material( 142 | color: Colors.transparent, 143 | child: InkWell( 144 | borderRadius: BorderRadius.only( 145 | topRight: Radius.circular(20.0), 146 | bottomLeft: Radius.circular(20.0), 147 | bottomRight: Radius.circular(20.0)), 148 | onTap: onTap, 149 | onLongPress: () { 150 | showDialog( 151 | context: context, 152 | builder: (BuildContext context) { 153 | return AlertDialog( 154 | title: Text("Delete this list"), 155 | content: 156 | Text("Are you sure you want to delete this list?"), 157 | actions: [ 158 | FlatButton( 159 | child: Text("YES"), 160 | onPressed: () { 161 | Navigator.pop(context); 162 | 163 | sl().call( 164 | uid: sl().uid, listId: todoList.listId); 165 | }, 166 | ), 167 | FlatButton( 168 | child: Text("NO"), 169 | onPressed: () { 170 | Navigator.of(context).pop(); 171 | }, 172 | ), 173 | ], 174 | ); 175 | }); 176 | }, 177 | child: Container( 178 | height: 600, 179 | width: 250.0, 180 | //color: Colors.purple, 181 | ), 182 | ), 183 | ), 184 | ),*/ 185 | ], 186 | ); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/menu_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class MenuIcon extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Container( 7 | 8 | child: Column( 9 | 10 | crossAxisAlignment: CrossAxisAlignment.start, 11 | children: [ 12 | Container( 13 | height: 3.0, 14 | width: 20.0, 15 | 16 | decoration: BoxDecoration( 17 | color: Color(0xff616B77), 18 | borderRadius: BorderRadius.circular(5) 19 | ), 20 | ), 21 | SizedBox(height: 7.0), 22 | Container( 23 | height: 3.0, 24 | width: 10.0, 25 | decoration: BoxDecoration( 26 | color: Color(0xff616B77), 27 | borderRadius: BorderRadius.circular(5) 28 | ), 29 | ), 30 | ] 31 | ), 32 | ); 33 | } 34 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/no_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class NoWidget extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return SizedBox( 7 | height: 0, 8 | width: 0, 9 | ); 10 | } 11 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/quick_note_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:todo_app/src/core/user/user.dart'; 3 | import 'package:todo_app/src/features/todo_manager_features/domain/entities/QuickNote.dart'; 4 | import 'package:todo_app/src/features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 5 | import 'package:todo_app/src/features/todo_manager_features/domain/usecases/edit_quick_note.dart'; 6 | import 'package:todo_app/src/injection_container.dart'; 7 | 8 | import 'small_button.dart'; 9 | 10 | class QuickNoteWidget extends StatefulWidget { 11 | final QuickNote quickNoteInfo; 12 | final Key key; 13 | 14 | QuickNoteWidget({@required this.key, this.quickNoteInfo}) : super(key: key); 15 | @override 16 | _QuickNoteWidgetState createState() => _QuickNoteWidgetState(); 17 | } 18 | 19 | class _QuickNoteWidgetState extends State { 20 | TextEditingController _quickNoteTitleController = new TextEditingController(); 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | } 26 | 27 | @override 28 | void dispose() { 29 | //_quickNoteTitleController.dispose(); 30 | super.dispose(); 31 | } 32 | 33 | void _showModalToEditTitle() { 34 | _quickNoteTitleController = 35 | TextEditingController(text: widget.quickNoteInfo.title); 36 | showDialog( 37 | context: context, 38 | builder: (context) { 39 | return Dialog( 40 | backgroundColor: Colors.red, 41 | shape: 42 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)), 43 | child: Container( 44 | height: 200, 45 | padding: EdgeInsets.symmetric(horizontal: 30), 46 | color: Colors.white, 47 | child: Column( 48 | mainAxisAlignment: MainAxisAlignment.center, 49 | children: [ 50 | Row( 51 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 52 | children: [ 53 | Expanded( 54 | child: Container( 55 | child: TextField( 56 | controller: _quickNoteTitleController, 57 | style: TextStyle( 58 | fontSize: 18.0, 59 | color: Color(0xff878CAC), 60 | fontFamily: "Poppins"), 61 | ), 62 | ), 63 | ), 64 | SizedBox(width: 20), 65 | SmallButton( 66 | color: Colors.blue, 67 | icon: Icon( 68 | Icons.check, 69 | color: Colors.white, 70 | ), 71 | onPressed: () { 72 | EditQuickNoteTitle(sl()).call( 73 | uid: sl().uid, 74 | quickNoteId: widget.quickNoteInfo.quickNoteId, 75 | newTitle: _quickNoteTitleController.text); 76 | Navigator.of(context).pop(); 77 | }, 78 | ) 79 | ], 80 | ) 81 | ], 82 | ), 83 | ), 84 | ); 85 | }); 86 | } 87 | 88 | @override 89 | Widget build(BuildContext context) { 90 | return InkWell( 91 | onLongPress: () { 92 | _showModalToEditTitle(); 93 | }, 94 | child: Container( 95 | padding: EdgeInsets.symmetric(vertical: 10), 96 | child: Row( 97 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 98 | children: [ 99 | Row( 100 | crossAxisAlignment: CrossAxisAlignment.start, 101 | children: [ 102 | Container( 103 | width: 18, 104 | height: 18, 105 | child: Checkbox( 106 | value: widget.quickNoteInfo.isDone, 107 | activeColor: Color(0x80878CAC), 108 | checkColor: Colors.white, 109 | onChanged: (bool isChecked) async{ 110 | setState(() { 111 | widget.quickNoteInfo.isDone = isChecked; 112 | }); 113 | await Future.delayed(Duration(milliseconds: 250)); 114 | sl().call( 115 | uid: sl().uid, 116 | quickNoteId: widget.quickNoteInfo.quickNoteId, 117 | isDone: isChecked); 118 | }, 119 | ), 120 | ), 121 | SizedBox(width: 30.0), 122 | Container( 123 | width: MediaQuery.of(context).size.width * 0.65, 124 | child: Text( 125 | widget.quickNoteInfo.title, 126 | 127 | style: TextStyle( 128 | fontSize: 18.0, 129 | decoration: widget.quickNoteInfo.isDone 130 | ? TextDecoration.lineThrough 131 | : TextDecoration.none, 132 | color: widget.quickNoteInfo.isDone 133 | ? Color(0x4D878CAC) 134 | : Color(0xff878CAC), 135 | fontFamily: "Poppins"), 136 | ), 137 | ), 138 | ], 139 | ), 140 | widget.quickNoteInfo.isDone 141 | ? Container( 142 | child: InkWell( 143 | borderRadius: BorderRadius.circular(30.0), 144 | onTap: () { 145 | _quickNoteTitleController.dispose(); 146 | sl().call( 147 | uid: sl().uid, 148 | quickNoteId: widget.quickNoteInfo.quickNoteId); 149 | 150 | }, 151 | child: Icon( 152 | Icons.clear, 153 | color: Theme.of(context).accentColor, 154 | size: 20, 155 | ), 156 | ), 157 | ) 158 | : Container( 159 | height: 7.0, 160 | width: 7.0, 161 | decoration: BoxDecoration( 162 | color: widget.quickNoteInfo.priority.color, 163 | borderRadius: BorderRadius.circular(10.0)), 164 | ) 165 | ], 166 | ), 167 | ), 168 | ); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/select_priority_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:todo_app/src/core/priority/Priority.dart'; 3 | 4 | class SelectPriorityButton extends StatelessWidget { 5 | final VoidCallback onPressed; 6 | final Priority priority; 7 | final bool isSelected; 8 | 9 | SelectPriorityButton({ 10 | this.onPressed, 11 | this.priority, 12 | this.isSelected 13 | }); 14 | @override 15 | Widget build(BuildContext context) { 16 | return FlatButton( 17 | color: isSelected ? Theme.of(context).primaryColor: Color(0xffEFF1F9), 18 | 19 | shape: RoundedRectangleBorder( 20 | borderRadius: BorderRadius.circular(10.0) 21 | ), 22 | padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), 23 | onPressed: onPressed, 24 | child: Row( 25 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 26 | children: [ 27 | Container( 28 | height: 5, 29 | width: 5, 30 | 31 | decoration: BoxDecoration( 32 | borderRadius: BorderRadius.circular(5.0), 33 | color: priority.color, 34 | ), 35 | ), 36 | SizedBox(width: 20), 37 | Text( 38 | priority.importance, 39 | style: TextStyle( 40 | fontFamily: "Poppins", 41 | fontSize: 17.0, 42 | color: isSelected? Colors.white : Theme.of(context).accentColor 43 | 44 | ), 45 | ) 46 | ], 47 | ), 48 | ); 49 | } 50 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/slide_animation_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/single_child_widget.dart'; 3 | 4 | class SlideAnimationWrapper extends StatefulWidget { 5 | final Duration slideDuration; 6 | final Duration fadeDuration; 7 | final Widget child; 8 | SlideAnimationWrapper({ 9 | @required this.slideDuration, 10 | @required this.fadeDuration, 11 | @required this.child 12 | }); 13 | 14 | @override 15 | _SlideAnimationWrapperState createState() => _SlideAnimationWrapperState(); 16 | } 17 | 18 | class _SlideAnimationWrapperState extends State with TickerProviderStateMixin{ 19 | 20 | 21 | AnimationController _slideController; 22 | AnimationController _fadeController; 23 | Animation _offset; 24 | Animation _opacity; 25 | 26 | 27 | @override 28 | void initState() { 29 | _slideController = AnimationController( 30 | duration: widget.slideDuration, 31 | vsync: this 32 | )..forward(); 33 | 34 | _fadeController = AnimationController( 35 | duration: widget.fadeDuration, 36 | vsync: this 37 | )..forward(); 38 | 39 | _offset = Tween( 40 | begin: Offset(-1.5, 0), 41 | end: Offset(0,0) 42 | ).animate( 43 | CurvedAnimation( 44 | parent: _slideController, 45 | curve: Curves.easeOutBack 46 | 47 | ) 48 | ); 49 | 50 | _opacity = Tween( 51 | begin: 0.0, 52 | end: 1.0 53 | ).animate( 54 | CurvedAnimation(parent: _fadeController, curve: Curves.ease) 55 | ); 56 | 57 | super.initState(); 58 | } 59 | 60 | @override 61 | void dispose() { 62 | _fadeController.dispose(); 63 | _slideController.dispose(); 64 | super.dispose(); 65 | } 66 | 67 | 68 | @override 69 | Widget build(BuildContext context) { 70 | return SlideTransition( 71 | position: _offset, 72 | child: FadeTransition( 73 | opacity: _opacity, 74 | child: widget.child, 75 | ), 76 | ); 77 | } 78 | } -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/small_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SmallButton extends StatelessWidget { 4 | final Color color; 5 | final Widget icon; 6 | final VoidCallback onPressed; 7 | SmallButton({this.icon, this.onPressed, this.color}); 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | width: 45.0, 12 | child: RaisedButton( 13 | onPressed: onPressed, 14 | child: icon, 15 | shape: 16 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)), 17 | color: this.color != null ? this.color : Theme.of(context).primaryColor, 18 | padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 10.0), 19 | ), 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/features/todo_manager_features/presentation/widgets/suggestion_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SuggestionTile extends StatelessWidget { 4 | 5 | final String title; 6 | final VoidCallback onTap; 7 | SuggestionTile({ 8 | 9 | this.title, 10 | this.onTap 11 | }); 12 | @override 13 | Widget build(BuildContext context) { 14 | return Container( 15 | 16 | margin: EdgeInsets.only(right:10, bottom: 10), 17 | decoration: BoxDecoration( 18 | color: this.title.length > 5 ? Color(0x4D12B3C5) : Color(0x4D657AFF), 19 | borderRadius: BorderRadius.circular(10) 20 | ), 21 | child: InkWell( 22 | 23 | //splashColor: Colors.red, 24 | onTap: onTap, 25 | child: Padding( 26 | padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), 27 | child: Text( 28 | this.title, 29 | style: TextStyle( 30 | fontFamily: "Poppins", 31 | fontSize: 15.0, 32 | color: Theme.of(context).accentColor 33 | ), 34 | ), 35 | ), 36 | ), 37 | ); 38 | } 39 | } -------------------------------------------------------------------------------- /lib/src/injection_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | 3 | import './features/todo_manager_features/domain/usecases/add_list.dart' as addListUseCase; 4 | import './features/todo_manager_features/domain/usecases/add_quick_note.dart' as addQuickNoteUseCase; 5 | import './features/todo_manager_features/domain/usecases/dashboard_use_cases.dart' as dashboardUseCase; 6 | import './features/todo_manager_features/domain/usecases/edit_quick_note.dart' as editNoteUseCase; 7 | import './features/todo_manager_features/domain/usecases/edit_list.dart' as editListUseCase; 8 | import './features/todo_manager_features/domain/usecases/edit_list_todo.dart' as editListTodoUseCase; 9 | import 'core/user/user.dart'; 10 | import 'features/todo_manager_features/data/datasources/auth_service.dart'; 11 | import 'features/todo_manager_features/data/datasources/firestore_interactions.dart'; 12 | import 'features/todo_manager_features/data/repositories/auth_repository_impl.dart'; 13 | import 'features/todo_manager_features/data/repositories/todo_manager_repository_impl.dart'; 14 | import 'features/todo_manager_features/domain/repositories/auth_repository.dart'; 15 | import 'features/todo_manager_features/domain/repositories/todo_manager_repository.dart'; 16 | import 'features/todo_manager_features/presentation/bloc/add_list_bloc/add_list_bloc.dart'; 17 | import 'features/todo_manager_features/presentation/bloc/add_quick_note_bloc/add_quick_note_bloc.dart'; 18 | import 'features/todo_manager_features/presentation/bloc/auth_bloc/auth_bloc.dart'; 19 | import 'features/todo_manager_features/presentation/bloc/dashboard_bloc/dashboard_bloc.dart'; 20 | import 'features/todo_manager_features/presentation/bloc/login_bloc/login_bloc.dart'; 21 | 22 | final sl = GetIt.instance; 23 | 24 | 25 | Future init() async{ 26 | sl.allowReassignment = true; 27 | //bloc 28 | sl.registerFactory( 29 | () => AuthBloc(authRepository: sl()) 30 | ); 31 | sl.registerFactory( 32 | () => LoginBloc(authRepository: sl()) 33 | ); 34 | sl.registerFactory( 35 | () => DashboardBloc() 36 | ); 37 | sl.registerFactory( 38 | () => AddQuickNoteBloc(user: sl(), addQuickNote: sl()) 39 | ); 40 | sl.registerFactory( 41 | () => AddListBloc(addList: sl(), user: sl()) 42 | ); 43 | 44 | //usecases 45 | sl.registerLazySingleton(() => dashboardUseCase.FetchListTodos(sl())); 46 | sl.registerLazySingleton(() => dashboardUseCase.FetchQuickNotes(sl())); 47 | sl.registerLazySingleton(() => dashboardUseCase.FetchLists(sl())); 48 | 49 | sl.registerLazySingleton(() => addListUseCase.AddList(sl())); 50 | sl.registerLazySingleton(() => addQuickNoteUseCase.AddQuickNote(sl())); 51 | 52 | sl.registerLazySingleton(() => editNoteUseCase.DeleteQuickNote(sl())); 53 | sl.registerLazySingleton(() => editNoteUseCase.EditQuickNoteTitle(sl())); 54 | sl.registerLazySingleton(() => editNoteUseCase.SetQuickNoteIsDone(sl())); 55 | 56 | sl.registerLazySingleton(() => editListUseCase.AddListTodo(sl())); 57 | sl.registerLazySingleton(() => editListUseCase.DeleteList(sl())); 58 | sl.registerLazySingleton(() => editListUseCase.EditBackgroundColor(sl())); 59 | sl.registerLazySingleton(() => editListUseCase.EditListTitle(sl())); 60 | 61 | sl.registerLazySingleton(() => editListTodoUseCase.SetListTodoIsDone(sl())); 62 | 63 | 64 | 65 | 66 | 67 | // repository 68 | sl.registerLazySingleton( 69 | () => AuthRepositoryImpl(sl()) 70 | ); 71 | sl.registerLazySingleton( 72 | () => TodoManagerRepositoryImpl(sl()) 73 | ); 74 | 75 | // data sources 76 | sl.registerLazySingleton(() => FirestoreInteractions()); 77 | sl.registerLazySingleton(() => AuthService()); 78 | 79 | //core 80 | 81 | 82 | sl().user.listen((user){ 83 | sl.registerSingleton(user); 84 | }); 85 | 86 | 87 | 88 | 89 | 90 | //external 91 | } 92 | 93 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.13" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.6.0" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.4.1" 25 | bloc: 26 | dependency: transitive 27 | description: 28 | name: bloc 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "4.0.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.0.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.3" 46 | cloud_firestore: 47 | dependency: "direct main" 48 | description: 49 | name: cloud_firestore 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.13.5" 53 | cloud_firestore_platform_interface: 54 | dependency: transitive 55 | description: 56 | name: cloud_firestore_platform_interface 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.1.0" 60 | cloud_firestore_web: 61 | dependency: transitive 62 | description: 63 | name: cloud_firestore_web 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.1.1+2" 67 | collection: 68 | dependency: transitive 69 | description: 70 | name: collection 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.14.12" 74 | convert: 75 | dependency: transitive 76 | description: 77 | name: convert 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "2.1.1" 81 | crypto: 82 | dependency: transitive 83 | description: 84 | name: crypto 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "2.1.4" 88 | dartz: 89 | dependency: "direct main" 90 | description: 91 | name: dartz 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "0.9.1" 95 | equatable: 96 | dependency: "direct main" 97 | description: 98 | name: equatable 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.1.1" 102 | firebase: 103 | dependency: transitive 104 | description: 105 | name: firebase 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "7.3.0" 109 | firebase_auth: 110 | dependency: "direct main" 111 | description: 112 | name: firebase_auth 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "0.16.0" 116 | firebase_auth_platform_interface: 117 | dependency: transitive 118 | description: 119 | name: firebase_auth_platform_interface 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.1.7" 123 | firebase_auth_web: 124 | dependency: transitive 125 | description: 126 | name: firebase_auth_web 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "0.1.2" 130 | firebase_core: 131 | dependency: "direct main" 132 | description: 133 | name: firebase_core 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "0.4.4+3" 137 | firebase_core_platform_interface: 138 | dependency: transitive 139 | description: 140 | name: firebase_core_platform_interface 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "1.0.4" 144 | firebase_core_web: 145 | dependency: transitive 146 | description: 147 | name: firebase_core_web 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "0.1.1+2" 151 | flutter: 152 | dependency: "direct main" 153 | description: flutter 154 | source: sdk 155 | version: "0.0.0" 156 | flutter_bloc: 157 | dependency: "direct main" 158 | description: 159 | name: flutter_bloc 160 | url: "https://pub.dartlang.org" 161 | source: hosted 162 | version: "4.0.0" 163 | flutter_statusbarcolor: 164 | dependency: "direct main" 165 | description: 166 | name: flutter_statusbarcolor 167 | url: "https://pub.dartlang.org" 168 | source: hosted 169 | version: "0.2.3" 170 | flutter_test: 171 | dependency: "direct dev" 172 | description: flutter 173 | source: sdk 174 | version: "0.0.0" 175 | flutter_web_plugins: 176 | dependency: transitive 177 | description: flutter 178 | source: sdk 179 | version: "0.0.0" 180 | get_it: 181 | dependency: "direct main" 182 | description: 183 | name: get_it 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "4.0.2" 187 | google_sign_in: 188 | dependency: "direct main" 189 | description: 190 | name: google_sign_in 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "4.5.1" 194 | google_sign_in_platform_interface: 195 | dependency: transitive 196 | description: 197 | name: google_sign_in_platform_interface 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "1.1.2" 201 | google_sign_in_web: 202 | dependency: transitive 203 | description: 204 | name: google_sign_in_web 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "0.9.1+1" 208 | http: 209 | dependency: transitive 210 | description: 211 | name: http 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "0.12.0+4" 215 | http_parser: 216 | dependency: transitive 217 | description: 218 | name: http_parser 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "3.1.4" 222 | image: 223 | dependency: transitive 224 | description: 225 | name: image 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "2.1.12" 229 | js: 230 | dependency: transitive 231 | description: 232 | name: js 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "0.6.1+1" 236 | matcher: 237 | dependency: transitive 238 | description: 239 | name: matcher 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "0.12.6" 243 | meta: 244 | dependency: transitive 245 | description: 246 | name: meta 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "1.1.8" 250 | nested: 251 | dependency: transitive 252 | description: 253 | name: nested 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "0.0.4" 257 | path: 258 | dependency: transitive 259 | description: 260 | name: path 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "1.6.4" 264 | pedantic: 265 | dependency: transitive 266 | description: 267 | name: pedantic 268 | url: "https://pub.dartlang.org" 269 | source: hosted 270 | version: "1.8.0+1" 271 | petitparser: 272 | dependency: transitive 273 | description: 274 | name: petitparser 275 | url: "https://pub.dartlang.org" 276 | source: hosted 277 | version: "2.4.0" 278 | plugin_platform_interface: 279 | dependency: transitive 280 | description: 281 | name: plugin_platform_interface 282 | url: "https://pub.dartlang.org" 283 | source: hosted 284 | version: "1.0.2" 285 | provider: 286 | dependency: "direct main" 287 | description: 288 | name: provider 289 | url: "https://pub.dartlang.org" 290 | source: hosted 291 | version: "4.1.2" 292 | quiver: 293 | dependency: transitive 294 | description: 295 | name: quiver 296 | url: "https://pub.dartlang.org" 297 | source: hosted 298 | version: "2.1.3" 299 | random_words: 300 | dependency: "direct main" 301 | description: 302 | name: random_words 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "1.0.2" 306 | rxdart: 307 | dependency: "direct main" 308 | description: 309 | name: rxdart 310 | url: "https://pub.dartlang.org" 311 | source: hosted 312 | version: "0.24.1" 313 | sky_engine: 314 | dependency: transitive 315 | description: flutter 316 | source: sdk 317 | version: "0.0.99" 318 | source_span: 319 | dependency: transitive 320 | description: 321 | name: source_span 322 | url: "https://pub.dartlang.org" 323 | source: hosted 324 | version: "1.7.0" 325 | stack_trace: 326 | dependency: transitive 327 | description: 328 | name: stack_trace 329 | url: "https://pub.dartlang.org" 330 | source: hosted 331 | version: "1.9.3" 332 | stream_channel: 333 | dependency: transitive 334 | description: 335 | name: stream_channel 336 | url: "https://pub.dartlang.org" 337 | source: hosted 338 | version: "2.0.0" 339 | string_scanner: 340 | dependency: transitive 341 | description: 342 | name: string_scanner 343 | url: "https://pub.dartlang.org" 344 | source: hosted 345 | version: "1.0.5" 346 | term_glyph: 347 | dependency: transitive 348 | description: 349 | name: term_glyph 350 | url: "https://pub.dartlang.org" 351 | source: hosted 352 | version: "1.1.0" 353 | test_api: 354 | dependency: transitive 355 | description: 356 | name: test_api 357 | url: "https://pub.dartlang.org" 358 | source: hosted 359 | version: "0.2.15" 360 | typed_data: 361 | dependency: transitive 362 | description: 363 | name: typed_data 364 | url: "https://pub.dartlang.org" 365 | source: hosted 366 | version: "1.1.6" 367 | vector_math: 368 | dependency: transitive 369 | description: 370 | name: vector_math 371 | url: "https://pub.dartlang.org" 372 | source: hosted 373 | version: "2.0.8" 374 | xml: 375 | dependency: transitive 376 | description: 377 | name: xml 378 | url: "https://pub.dartlang.org" 379 | source: hosted 380 | version: "3.6.1" 381 | sdks: 382 | dart: ">=2.7.0 <3.0.0" 383 | flutter: ">=1.16.0 <2.0.0" 384 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: todo_app 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.2.2 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | 26 | firebase_core: ^0.4.4+3 27 | firebase_auth: ^0.16.0 28 | google_sign_in: ^4.5.1 29 | cloud_firestore: ^0.13.5 30 | rxdart: ^0.24.1 31 | provider: ^4.1.2 32 | random_words: ^1.0.2 33 | flutter_bloc: ^4.0.0 34 | equatable: ^1.1.1 35 | get_it: ^4.0.2 36 | dartz: ^0.9.1 37 | flutter_statusbarcolor: ^0.2.3 38 | 39 | 40 | dev_dependencies: 41 | flutter_test: 42 | sdk: flutter 43 | 44 | 45 | # For information on the generic Dart part of this file, see the 46 | # following page: https://dart.dev/tools/pub/pubspec 47 | 48 | # The following section is specific to Flutter. 49 | flutter: 50 | 51 | # The following line ensures that the Material Icons font is 52 | # included with your application, so that you can use the icons in 53 | # the material Icons class. 54 | uses-material-design: true 55 | 56 | # To add assets to your application, add an assets section, like this: 57 | assets: 58 | - assets/ 59 | 60 | 61 | # An image asset can refer to one or more resolution-specific "variants", see 62 | # https://flutter.dev/assets-and-images/#resolution-aware. 63 | 64 | # For details regarding adding assets from package dependencies, see 65 | # https://flutter.dev/assets-and-images/#from-packages 66 | 67 | # To add custom fonts to your application, add a fonts section here, 68 | # in this "flutter" section. Each entry in this list should have a 69 | # "family" key with the font family name, and a "fonts" key with a 70 | # list giving the asset and other descriptors for the font. For 71 | # example: 72 | fonts: 73 | - family: Poppins 74 | fonts: 75 | - asset: fonts/Poppins/Poppins-Light.ttf 76 | weight: 100 77 | - asset: fonts/Poppins/Poppins-Regular.ttf 78 | - asset: fonts/Poppins/Poppins-Medium.ttf 79 | weight: 700 80 | # - family: Trajan Pro 81 | # fonts: 82 | # - asset: fonts/TrajanPro.ttf 83 | # - asset: fonts/TrajanPro_Bold.ttf 84 | # weight: 700 85 | # 86 | # For details regarding fonts from package dependencies, 87 | # see https://flutter.dev/custom-fonts/#from-packages 88 | -------------------------------------------------------------------------------- /screenshots/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/screenshots/first.png -------------------------------------------------------------------------------- /screenshots/fourth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/screenshots/fourth.png -------------------------------------------------------------------------------- /screenshots/second.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/screenshots/second.png -------------------------------------------------------------------------------- /screenshots/third.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoZaddy/Flutter-Todo-App/1982024b788b2bea3e74aa3a3612f98e613df738/screenshots/third.png -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:todo_app/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------