├── .gitignore ├── .metadata ├── README.md ├── android ├── .project ├── .settings │ └── org.eclipse.buildship.core.prefs ├── app │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── todo │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable │ │ └── launch_background.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── todo_icon.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── todo_icon.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── todo_icon.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── todo_icon.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── todo_icon.png │ │ └── values │ │ └── styles.xml ├── build.gradle ├── debug.keystore ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── flutter_export_environment.sh ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── Runner-Bridging-Header.h │ └── main.m ├── lib ├── component │ ├── colorpicker │ │ └── color_picker_builder.dart │ ├── iconpicker │ │ ├── icon_picker.dart │ │ └── icon_picker_builder.dart │ └── todo_badge.dart ├── db │ └── db_provider.dart ├── diamond_border.dart ├── gradient_background.dart ├── main.dart ├── model │ ├── data │ │ └── choice_card.dart │ ├── hero_id_model.dart │ ├── task_model.dart │ ├── task_model.g.dart │ ├── todo_model.dart │ └── todo_model.g.dart ├── page │ ├── add_task_screen.dart │ ├── add_todo_screen.dart │ ├── detail_screen.dart │ ├── edit_task_screen.dart │ └── privacy_policy.dart ├── route │ └── scale_route.dart ├── scopedmodel │ └── todo_list_model.dart ├── shadow_image.dart ├── task_progress_indicator.dart └── utils │ ├── color_utils.dart │ ├── datetime_utils.dart │ └── uuid.dart ├── pubspec.yaml ├── screenshots ├── screen01.png ├── screen02.png ├── screen03.png └── screen04.png └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /.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. 5 | 6 | version: 7 | revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 17 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 18 | - platform: android 19 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 20 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 21 | - platform: ios 22 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 23 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 24 | - platform: linux 25 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 26 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 27 | - platform: macos 28 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 29 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 30 | - platform: web 31 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 32 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 33 | - platform: windows 34 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 35 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Codemagic build status](https://api.codemagic.io/apps/5d0f190099fdb70008475b03/5d0f190099fdb70008475b02/status_badge.svg)](https://codemagic.io/apps/5d0f190099fdb70008475b03/5d0f190099fdb70008475b02/latest_build) 2 | 3 |

4 |
5 | Todo 6 |
7 | Todo - Simple & Beautiful 8 |
9 |

10 | 11 |

A minimal Todo mobile app made using Flutter.

12 | 13 |

14 | Key Features • 15 | How To Use • 16 | Download • 17 | Credits • 18 |

19 | 20 |

21 | 22 | 23 | 24 | 25 |

26 | 27 | ## Key Features 28 | 29 | * Easily add and remove tasks 30 | * Organize tasks under categories. editing. 31 | * Personalize task category using color and icon. 32 | 33 | ## How To Use 34 | 35 | To clone and run this application, you'll need [Git](https://git-scm.com) and [Flutter](https://flutter.dev/docs/get-started/install) installed on your computer. From your command line: 36 | 37 | ```bash 38 | # Clone this repository 39 | $ git clone https://github.com/sabinbajracharya/fluttery-todo.git 40 | 41 | # Go into the repository 42 | $ cd fluttery-todo 43 | 44 | # Install dependencies 45 | $ flutter packages get 46 | 47 | # Run the app 48 | $ flutter run 49 | ``` 50 | 51 | ## Download 52 | 53 | You can [download](https://play.google.com/store/apps/details?id=com.queenstech.todo) the latest installable version of Todo for Android. 54 | 55 | 56 | 57 | 58 | 59 | ## Credits 60 | - [Design Inspiration](https://goo.gl/Y5rd7L) 61 | 62 | ## License 63 | 64 | MIT 65 | 66 | --- 67 | 68 | > GitHub [@sabinbajracharya](https://github.com/sabinbajracharya)  ·  69 | > Instagram [@er_sabin](https://www.instagram.com/er_sabin/) 70 | 71 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /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 = '3' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0.2' 22 | } 23 | 24 | def keystoreProperties = new Properties() 25 | def keystorePropertiesFile = rootProject.file('key.properties') 26 | if (keystorePropertiesFile.exists()) { 27 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 28 | } 29 | 30 | apply plugin: 'com.android.application' 31 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 32 | 33 | android { 34 | compileSdkVersion 31 35 | 36 | lintOptions { 37 | disable 'InvalidPackage' 38 | } 39 | 40 | defaultConfig { 41 | applicationId "com.queenstech.todo" 42 | minSdkVersion 16 43 | targetSdkVersion 31 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | signingConfigs { 50 | release { 51 | if (System.getenv()["CI"]) { // CI=true is exported by Codemagic 52 | keyAlias keystoreProperties['keyAlias'] 53 | keyPassword keystoreProperties['keyPassword'] 54 | storeFile file(keystoreProperties['storeFile']) 55 | storePassword keystoreProperties['storePassword'] 56 | } else { 57 | // TODO: Replace with your own signing config for the release build. 58 | // Signing with the debug keys for now, so `flutter run --release` works. 59 | storeFile file('../debug.keystore') 60 | keyAlias "androiddebugkey" 61 | keyPassword "android" 62 | storePassword "android" 63 | } 64 | } 65 | } 66 | 67 | buildTypes { 68 | release { 69 | signingConfig signingConfigs.release 70 | minifyEnabled true 71 | useProguard true 72 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 73 | } 74 | 75 | debug { 76 | signingConfig signingConfigs.debug 77 | minifyEnabled false 78 | useProguard false 79 | } 80 | } 81 | } 82 | 83 | flutter { 84 | source '../..' 85 | } 86 | 87 | dependencies { 88 | testImplementation 'junit:junit:4.12' 89 | androidTestImplementation 'androidx.test:runner:1.1.0' 90 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 91 | } 92 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #Flutter Wrapper 2 | -keep class io.flutter.app.** { *; } 3 | -keep class io.flutter.plugin.** { *; } 4 | -keep class io.flutter.util.** { *; } 5 | -keep class io.flutter.view.** { *; } 6 | -keep class io.flutter.** { *; } 7 | -keep class io.flutter.plugins.** { *; } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 27 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/todo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.todo; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /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/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/todo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-hdpi/todo_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/todo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-mdpi/todo_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/todo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xhdpi/todo_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/todo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xxhdpi/todo_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/todo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/app/src/main/res/mipmap-xxxhdpi/todo_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.4.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/android/debug.keystore -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Jun 23 21:45:27 NPT 2019 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.1.1-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/home/hellojukay/dev/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/home/hellojukay/github/fluttery-todo" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_TARGET=lib/main.dart" 7 | export "FLUTTER_BUILD_DIR=build" 8 | export "FLUTTER_BUILD_NAME=1.1.1" 9 | export "FLUTTER_BUILD_NUMBER=20191101" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=true" 12 | export "TREE_SHAKE_ICONS=false" 13 | export "PACKAGE_CONFIG=.dart_tool/package_config.json" 14 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /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 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 13 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 14 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 18 | D141452D868D527CC693F39D /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 54F3733F6E14C00EFBA422DF /* libPods-Runner.a */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXCopyFilesBuildPhase section */ 22 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 23 | isa = PBXCopyFilesBuildPhase; 24 | buildActionMask = 2147483647; 25 | dstPath = ""; 26 | dstSubfolderSpec = 10; 27 | files = ( 28 | ); 29 | name = "Embed Frameworks"; 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXCopyFilesBuildPhase section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 36 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 37 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 38 | 54F3733F6E14C00EFBA422DF /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 40 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 43 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 44 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | CED73B26C33C593F1C74498D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 51 | D9DE1C44A481F3BE827A9C1B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 52 | EC472703C62012B5390546D9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | D141452D868D527CC693F39D /* libPods-Runner.a in Frameworks */, 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 05D85A74FFAF90F9CB2F0C1E /* Pods */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | D9DE1C44A481F3BE827A9C1B /* Pods-Runner.debug.xcconfig */, 71 | CED73B26C33C593F1C74498D /* Pods-Runner.release.xcconfig */, 72 | EC472703C62012B5390546D9 /* Pods-Runner.profile.xcconfig */, 73 | ); 74 | name = Pods; 75 | sourceTree = ""; 76 | }; 77 | 0F70B91065607A526AA2FE55 /* Frameworks */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 54F3733F6E14C00EFBA422DF /* libPods-Runner.a */, 81 | ); 82 | name = Frameworks; 83 | sourceTree = ""; 84 | }; 85 | 9740EEB11CF90186004384FC /* Flutter */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 89 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 90 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 91 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 92 | ); 93 | name = Flutter; 94 | sourceTree = ""; 95 | }; 96 | 97C146E51CF9000F007C117D = { 97 | isa = PBXGroup; 98 | children = ( 99 | 9740EEB11CF90186004384FC /* Flutter */, 100 | 97C146F01CF9000F007C117D /* Runner */, 101 | 97C146EF1CF9000F007C117D /* Products */, 102 | 05D85A74FFAF90F9CB2F0C1E /* Pods */, 103 | 0F70B91065607A526AA2FE55 /* Frameworks */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 97C146EF1CF9000F007C117D /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 97C146EE1CF9000F007C117D /* Runner.app */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | 97C146F01CF9000F007C117D /* Runner */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 119 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 120 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 121 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 122 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 123 | 97C147021CF9000F007C117D /* Info.plist */, 124 | 97C146F11CF9000F007C117D /* Supporting Files */, 125 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 126 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 127 | ); 128 | path = Runner; 129 | sourceTree = ""; 130 | }; 131 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 97C146F21CF9000F007C117D /* main.m */, 135 | ); 136 | name = "Supporting Files"; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 97C146ED1CF9000F007C117D /* Runner */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 145 | buildPhases = ( 146 | 6E5C8F5757CC7DC321B122A0 /* [CP] Check Pods Manifest.lock */, 147 | 9740EEB61CF901F6004384FC /* Run Script */, 148 | 97C146EA1CF9000F007C117D /* Sources */, 149 | 97C146EB1CF9000F007C117D /* Frameworks */, 150 | 97C146EC1CF9000F007C117D /* Resources */, 151 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 152 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 153 | ); 154 | buildRules = ( 155 | ); 156 | dependencies = ( 157 | ); 158 | name = Runner; 159 | productName = Runner; 160 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 161 | productType = "com.apple.product-type.application"; 162 | }; 163 | /* End PBXNativeTarget section */ 164 | 165 | /* Begin PBXProject section */ 166 | 97C146E61CF9000F007C117D /* Project object */ = { 167 | isa = PBXProject; 168 | attributes = { 169 | LastUpgradeCheck = 0910; 170 | ORGANIZATIONNAME = "The Chromium Authors"; 171 | TargetAttributes = { 172 | 97C146ED1CF9000F007C117D = { 173 | CreatedOnToolsVersion = 7.3.1; 174 | DevelopmentTeam = RLK6MZB6PQ; 175 | }; 176 | }; 177 | }; 178 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 179 | compatibilityVersion = "Xcode 3.2"; 180 | developmentRegion = English; 181 | hasScannedForEncodings = 0; 182 | knownRegions = ( 183 | English, 184 | en, 185 | Base, 186 | ); 187 | mainGroup = 97C146E51CF9000F007C117D; 188 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 97C146ED1CF9000F007C117D /* Runner */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | 97C146EC1CF9000F007C117D /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 203 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 204 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 205 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 206 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXResourcesBuildPhase section */ 211 | 212 | /* Begin PBXShellScriptBuildPhase section */ 213 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 214 | isa = PBXShellScriptBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | ); 218 | inputPaths = ( 219 | ); 220 | name = "Thin Binary"; 221 | outputPaths = ( 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | shellPath = /bin/sh; 225 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 226 | }; 227 | 6E5C8F5757CC7DC321B122A0 /* [CP] Check Pods Manifest.lock */ = { 228 | isa = PBXShellScriptBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | ); 232 | inputPaths = ( 233 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 234 | "${PODS_ROOT}/Manifest.lock", 235 | ); 236 | name = "[CP] Check Pods Manifest.lock"; 237 | outputPaths = ( 238 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | shellPath = /bin/sh; 242 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 243 | showEnvVarsInLog = 0; 244 | }; 245 | 9740EEB61CF901F6004384FC /* Run Script */ = { 246 | isa = PBXShellScriptBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | ); 250 | inputPaths = ( 251 | ); 252 | name = "Run Script"; 253 | outputPaths = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | shellPath = /bin/sh; 257 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 258 | }; 259 | /* End PBXShellScriptBuildPhase section */ 260 | 261 | /* Begin PBXSourcesBuildPhase section */ 262 | 97C146EA1CF9000F007C117D /* Sources */ = { 263 | isa = PBXSourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 267 | 97C146F31CF9000F007C117D /* main.m in Sources */, 268 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | /* End PBXSourcesBuildPhase section */ 273 | 274 | /* Begin PBXVariantGroup section */ 275 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 276 | isa = PBXVariantGroup; 277 | children = ( 278 | 97C146FB1CF9000F007C117D /* Base */, 279 | ); 280 | name = Main.storyboard; 281 | sourceTree = ""; 282 | }; 283 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 284 | isa = PBXVariantGroup; 285 | children = ( 286 | 97C147001CF9000F007C117D /* Base */, 287 | ); 288 | name = LaunchScreen.storyboard; 289 | sourceTree = ""; 290 | }; 291 | /* End PBXVariantGroup section */ 292 | 293 | /* Begin XCBuildConfiguration section */ 294 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_ANALYZER_NONNULL = YES; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 304 | CLANG_WARN_BOOL_CONVERSION = YES; 305 | CLANG_WARN_COMMA = YES; 306 | CLANG_WARN_CONSTANT_CONVERSION = YES; 307 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 308 | CLANG_WARN_EMPTY_BODY = YES; 309 | CLANG_WARN_ENUM_CONVERSION = YES; 310 | CLANG_WARN_INFINITE_RECURSION = YES; 311 | CLANG_WARN_INT_CONVERSION = YES; 312 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 313 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 314 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 315 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 316 | CLANG_WARN_STRICT_PROTOTYPES = YES; 317 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 321 | COPY_PHASE_STRIP = NO; 322 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 323 | ENABLE_NS_ASSERTIONS = NO; 324 | ENABLE_STRICT_OBJC_MSGSEND = YES; 325 | GCC_C_LANGUAGE_STANDARD = gnu99; 326 | GCC_NO_COMMON_BLOCKS = YES; 327 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 328 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 329 | GCC_WARN_UNDECLARED_SELECTOR = YES; 330 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 331 | GCC_WARN_UNUSED_FUNCTION = YES; 332 | GCC_WARN_UNUSED_VARIABLE = YES; 333 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 334 | MTL_ENABLE_DEBUG_INFO = NO; 335 | SDKROOT = iphoneos; 336 | TARGETED_DEVICE_FAMILY = "1,2"; 337 | VALIDATE_PRODUCT = YES; 338 | }; 339 | name = Profile; 340 | }; 341 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 342 | isa = XCBuildConfiguration; 343 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 344 | buildSettings = { 345 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 346 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 347 | DEVELOPMENT_TEAM = S8QB4VV633; 348 | ENABLE_BITCODE = NO; 349 | FRAMEWORK_SEARCH_PATHS = ( 350 | "$(inherited)", 351 | "$(PROJECT_DIR)/Flutter", 352 | ); 353 | INFOPLIST_FILE = Runner/Info.plist; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 355 | LIBRARY_SEARCH_PATHS = ( 356 | "$(inherited)", 357 | "$(PROJECT_DIR)/Flutter", 358 | ); 359 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todo; 360 | PRODUCT_NAME = "$(TARGET_NAME)"; 361 | VERSIONING_SYSTEM = "apple-generic"; 362 | }; 363 | name = Profile; 364 | }; 365 | 97C147031CF9000F007C117D /* Debug */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_ANALYZER_NONNULL = YES; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_COMMA = YES; 377 | CLANG_WARN_CONSTANT_CONVERSION = YES; 378 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 379 | CLANG_WARN_EMPTY_BODY = YES; 380 | CLANG_WARN_ENUM_CONVERSION = YES; 381 | CLANG_WARN_INFINITE_RECURSION = YES; 382 | CLANG_WARN_INT_CONVERSION = YES; 383 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 384 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 385 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 386 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 387 | CLANG_WARN_STRICT_PROTOTYPES = YES; 388 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 389 | CLANG_WARN_UNREACHABLE_CODE = YES; 390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 391 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 392 | COPY_PHASE_STRIP = NO; 393 | DEBUG_INFORMATION_FORMAT = dwarf; 394 | ENABLE_STRICT_OBJC_MSGSEND = YES; 395 | ENABLE_TESTABILITY = YES; 396 | GCC_C_LANGUAGE_STANDARD = gnu99; 397 | GCC_DYNAMIC_NO_PIC = NO; 398 | GCC_NO_COMMON_BLOCKS = YES; 399 | GCC_OPTIMIZATION_LEVEL = 0; 400 | GCC_PREPROCESSOR_DEFINITIONS = ( 401 | "DEBUG=1", 402 | "$(inherited)", 403 | ); 404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 406 | GCC_WARN_UNDECLARED_SELECTOR = YES; 407 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 408 | GCC_WARN_UNUSED_FUNCTION = YES; 409 | GCC_WARN_UNUSED_VARIABLE = YES; 410 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 411 | MTL_ENABLE_DEBUG_INFO = YES; 412 | ONLY_ACTIVE_ARCH = YES; 413 | SDKROOT = iphoneos; 414 | TARGETED_DEVICE_FAMILY = "1,2"; 415 | }; 416 | name = Debug; 417 | }; 418 | 97C147041CF9000F007C117D /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CLANG_ANALYZER_NONNULL = YES; 423 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 424 | CLANG_CXX_LIBRARY = "libc++"; 425 | CLANG_ENABLE_MODULES = YES; 426 | CLANG_ENABLE_OBJC_ARC = YES; 427 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 428 | CLANG_WARN_BOOL_CONVERSION = YES; 429 | CLANG_WARN_COMMA = YES; 430 | CLANG_WARN_CONSTANT_CONVERSION = YES; 431 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 432 | CLANG_WARN_EMPTY_BODY = YES; 433 | CLANG_WARN_ENUM_CONVERSION = YES; 434 | CLANG_WARN_INFINITE_RECURSION = YES; 435 | CLANG_WARN_INT_CONVERSION = YES; 436 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 440 | CLANG_WARN_STRICT_PROTOTYPES = YES; 441 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 442 | CLANG_WARN_UNREACHABLE_CODE = YES; 443 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 445 | COPY_PHASE_STRIP = NO; 446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 447 | ENABLE_NS_ASSERTIONS = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | GCC_C_LANGUAGE_STANDARD = gnu99; 450 | GCC_NO_COMMON_BLOCKS = YES; 451 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 452 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 453 | GCC_WARN_UNDECLARED_SELECTOR = YES; 454 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 455 | GCC_WARN_UNUSED_FUNCTION = YES; 456 | GCC_WARN_UNUSED_VARIABLE = YES; 457 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 458 | MTL_ENABLE_DEBUG_INFO = NO; 459 | SDKROOT = iphoneos; 460 | TARGETED_DEVICE_FAMILY = "1,2"; 461 | VALIDATE_PRODUCT = YES; 462 | }; 463 | name = Release; 464 | }; 465 | 97C147061CF9000F007C117D /* Debug */ = { 466 | isa = XCBuildConfiguration; 467 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 468 | buildSettings = { 469 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 470 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 471 | DEVELOPMENT_TEAM = RLK6MZB6PQ; 472 | ENABLE_BITCODE = NO; 473 | FRAMEWORK_SEARCH_PATHS = ( 474 | "$(inherited)", 475 | "$(PROJECT_DIR)/Flutter", 476 | ); 477 | INFOPLIST_FILE = Runner/Info.plist; 478 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 479 | LIBRARY_SEARCH_PATHS = ( 480 | "$(inherited)", 481 | "$(PROJECT_DIR)/Flutter", 482 | ); 483 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todo; 484 | PRODUCT_NAME = "$(TARGET_NAME)"; 485 | VERSIONING_SYSTEM = "apple-generic"; 486 | }; 487 | name = Debug; 488 | }; 489 | 97C147071CF9000F007C117D /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 492 | buildSettings = { 493 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 494 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 495 | DEVELOPMENT_TEAM = 7KZCF372N7; 496 | ENABLE_BITCODE = NO; 497 | FRAMEWORK_SEARCH_PATHS = ( 498 | "$(inherited)", 499 | "$(PROJECT_DIR)/Flutter", 500 | ); 501 | INFOPLIST_FILE = Runner/Info.plist; 502 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 503 | LIBRARY_SEARCH_PATHS = ( 504 | "$(inherited)", 505 | "$(PROJECT_DIR)/Flutter", 506 | ); 507 | PRODUCT_BUNDLE_IDENTIFIER = com.example.todo; 508 | PRODUCT_NAME = "$(TARGET_NAME)"; 509 | VERSIONING_SYSTEM = "apple-generic"; 510 | }; 511 | name = Release; 512 | }; 513 | /* End XCBuildConfiguration section */ 514 | 515 | /* Begin XCConfigurationList section */ 516 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 517 | isa = XCConfigurationList; 518 | buildConfigurations = ( 519 | 97C147031CF9000F007C117D /* Debug */, 520 | 97C147041CF9000F007C117D /* Release */, 521 | 249021D3217E4FDB00AE95B9 /* Profile */, 522 | ); 523 | defaultConfigurationIsVisible = 0; 524 | defaultConfigurationName = Release; 525 | }; 526 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 527 | isa = XCConfigurationList; 528 | buildConfigurations = ( 529 | 97C147061CF9000F007C117D /* Debug */, 530 | 97C147071CF9000F007C117D /* Release */, 531 | 249021D4217E4FDB00AE95B9 /* Profile */, 532 | ); 533 | defaultConfigurationIsVisible = 0; 534 | defaultConfigurationName = Release; 535 | }; 536 | /* End XCConfigurationList section */ 537 | }; 538 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 539 | } 540 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | todo 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" 2 | -------------------------------------------------------------------------------- /ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/component/colorpicker/color_picker_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_colorpicker/flutter_colorpicker.dart'; 3 | 4 | import 'package:todo/utils/color_utils.dart'; 5 | 6 | class ColorPickerBuilder extends StatelessWidget { 7 | final Color color; 8 | final ValueChanged onColorChanged; 9 | 10 | ColorPickerBuilder({required this.color, required this.onColorChanged}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | //https://stackoverflow.com/questions/45424621/inkwell-not-showing-ripple-effect 15 | return ClipOval( 16 | child: Container( 17 | height: 32.0, 18 | width: 32.0, 19 | child: Material( 20 | color: color, 21 | child: InkWell( 22 | borderRadius: BorderRadius.circular(50.0), 23 | onTap: () { 24 | showDialog( 25 | context: context, 26 | builder: (BuildContext context) { 27 | return AlertDialog( 28 | title: Text('Select a color'), 29 | content: SingleChildScrollView( 30 | child: BlockPicker( 31 | availableColors: ColorUtils.defaultColors, 32 | pickerColor: color, 33 | onColorChanged: onColorChanged, 34 | ), 35 | ), 36 | ); 37 | }, 38 | ); 39 | }, 40 | ), 41 | ), 42 | ), 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/component/iconpicker/icon_picker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:todo/component/todo_badge.dart'; 3 | 4 | class IconPicker extends StatefulWidget { 5 | final ValueChanged onIconChanged; 6 | final IconData currentIconData; 7 | final Color highlightColor, unHighlightColor; 8 | 9 | final List icons = [ 10 | Icons.threesixty, 11 | Icons.threed_rotation, 12 | Icons.four_k, 13 | Icons.ac_unit, 14 | Icons.access_alarm, 15 | Icons.access_alarms, 16 | Icons.access_time, 17 | Icons.accessibility, 18 | Icons.accessibility_new, 19 | Icons.accessible, 20 | Icons.accessible_forward, 21 | Icons.account_balance, 22 | Icons.account_balance_wallet, 23 | Icons.account_box, 24 | Icons.account_circle, 25 | Icons.adb, 26 | Icons.add, 27 | Icons.add_a_photo, 28 | Icons.add_alarm, 29 | Icons.add_alert, 30 | Icons.add_box, 31 | Icons.add_call, 32 | Icons.add_circle, 33 | Icons.add_circle_outline, 34 | Icons.add_comment, 35 | Icons.add_location, 36 | Icons.add_photo_alternate, 37 | Icons.add_shopping_cart, 38 | Icons.add_to_home_screen, 39 | Icons.add_to_photos, 40 | Icons.add_to_queue, 41 | Icons.adjust, 42 | Icons.airline_seat_flat, 43 | Icons.airline_seat_flat_angled, 44 | Icons.airline_seat_individual_suite, 45 | Icons.airline_seat_legroom_extra, 46 | Icons.airline_seat_legroom_normal, 47 | Icons.airline_seat_legroom_reduced, 48 | Icons.airline_seat_recline_extra, 49 | Icons.airline_seat_recline_normal, 50 | Icons.airplanemode_active, 51 | Icons.airplanemode_inactive, 52 | Icons.airplay, 53 | Icons.airport_shuttle, 54 | Icons.alarm, 55 | Icons.alarm_add, 56 | Icons.alarm_off, 57 | Icons.alarm_on, 58 | Icons.album, 59 | Icons.all_inclusive, 60 | Icons.all_out, 61 | Icons.alternate_email, 62 | Icons.android, 63 | Icons.announcement, 64 | Icons.apps, 65 | Icons.archive, 66 | Icons.arrow_back, 67 | Icons.arrow_back_ios, 68 | Icons.arrow_downward, 69 | Icons.arrow_drop_down, 70 | Icons.arrow_drop_down_circle, 71 | Icons.arrow_drop_up, 72 | Icons.arrow_forward, 73 | Icons.arrow_forward_ios, 74 | Icons.arrow_left, 75 | Icons.arrow_right, 76 | Icons.arrow_upward, 77 | Icons.art_track, 78 | Icons.aspect_ratio, 79 | Icons.assessment, 80 | Icons.assignment, 81 | Icons.assignment_ind, 82 | Icons.assignment_late, 83 | Icons.assignment_return, 84 | Icons.assignment_returned, 85 | Icons.assignment_turned_in, 86 | Icons.assistant, 87 | Icons.assistant_photo, 88 | Icons.atm, 89 | Icons.attach_file, 90 | Icons.attach_money, 91 | Icons.attachment, 92 | Icons.audiotrack, 93 | Icons.autorenew, 94 | Icons.av_timer, 95 | Icons.backspace, 96 | Icons.backup, 97 | Icons.battery_alert, 98 | Icons.battery_charging_full, 99 | Icons.battery_full, 100 | Icons.battery_std, 101 | Icons.battery_unknown, 102 | Icons.beach_access, 103 | Icons.beenhere, 104 | Icons.block, 105 | Icons.bluetooth, 106 | Icons.bluetooth_audio, 107 | Icons.bluetooth_connected, 108 | Icons.bluetooth_disabled, 109 | Icons.bluetooth_searching, 110 | Icons.blur_circular, 111 | Icons.blur_linear, 112 | Icons.blur_off, 113 | Icons.blur_on, 114 | Icons.book, 115 | Icons.bookmark, 116 | Icons.bookmark_border, 117 | Icons.border_all, 118 | Icons.border_bottom, 119 | Icons.border_clear, 120 | Icons.border_color, 121 | Icons.border_horizontal, 122 | Icons.border_inner, 123 | Icons.border_left, 124 | Icons.border_outer, 125 | Icons.border_right, 126 | Icons.border_style, 127 | Icons.border_top, 128 | Icons.border_vertical, 129 | Icons.branding_watermark, 130 | Icons.brightness_1, 131 | Icons.brightness_2, 132 | Icons.brightness_3, 133 | Icons.brightness_4, 134 | Icons.brightness_5, 135 | Icons.brightness_6, 136 | Icons.brightness_7, 137 | Icons.brightness_auto, 138 | Icons.brightness_high, 139 | Icons.brightness_low, 140 | Icons.brightness_medium, 141 | Icons.broken_image, 142 | Icons.brush, 143 | Icons.bubble_chart, 144 | Icons.bug_report, 145 | Icons.build, 146 | Icons.burst_mode, 147 | Icons.business, 148 | Icons.business_center, 149 | Icons.cached, 150 | Icons.cake, 151 | Icons.calendar_today, 152 | Icons.calendar_view_day, 153 | Icons.call, 154 | Icons.call_end, 155 | Icons.call_made, 156 | Icons.call_merge, 157 | Icons.call_missed, 158 | Icons.call_missed_outgoing, 159 | Icons.call_received, 160 | Icons.call_split, 161 | Icons.call_to_action, 162 | Icons.camera, 163 | Icons.camera_alt, 164 | Icons.camera_enhance, 165 | Icons.camera_front, 166 | Icons.camera_rear, 167 | Icons.camera_roll, 168 | Icons.cancel, 169 | Icons.card_giftcard, 170 | Icons.card_membership, 171 | Icons.card_travel, 172 | Icons.casino, 173 | Icons.cast, 174 | Icons.cast_connected, 175 | Icons.category, 176 | Icons.center_focus_strong, 177 | Icons.center_focus_weak, 178 | Icons.change_history, 179 | Icons.chat, 180 | Icons.chat_bubble, 181 | Icons.chat_bubble_outline, 182 | Icons.check, 183 | Icons.check_box, 184 | Icons.check_box_outline_blank, 185 | Icons.check_circle, 186 | Icons.check_circle_outline, 187 | Icons.chevron_left, 188 | Icons.chevron_right, 189 | Icons.child_care, 190 | Icons.child_friendly, 191 | Icons.chrome_reader_mode, 192 | Icons.class_, 193 | Icons.clear, 194 | Icons.clear_all, 195 | Icons.close, 196 | Icons.closed_caption, 197 | Icons.cloud, 198 | Icons.cloud_circle, 199 | Icons.cloud_done, 200 | Icons.cloud_download, 201 | Icons.cloud_off, 202 | Icons.cloud_queue, 203 | Icons.cloud_upload, 204 | Icons.code, 205 | Icons.collections, 206 | Icons.collections_bookmark, 207 | Icons.color_lens, 208 | Icons.colorize, 209 | Icons.comment, 210 | Icons.compare, 211 | Icons.compare_arrows, 212 | Icons.computer, 213 | Icons.confirmation_number, 214 | Icons.contact_mail, 215 | Icons.contact_phone, 216 | Icons.contacts, 217 | Icons.content_copy, 218 | Icons.content_cut, 219 | Icons.content_paste, 220 | Icons.control_point, 221 | Icons.control_point_duplicate, 222 | Icons.copyright, 223 | Icons.create, 224 | Icons.create_new_folder, 225 | Icons.credit_card, 226 | Icons.crop, 227 | Icons.crop_16_9, 228 | Icons.crop_3_2, 229 | Icons.crop_5_4, 230 | Icons.crop_7_5, 231 | Icons.crop_din, 232 | Icons.crop_free, 233 | Icons.crop_landscape, 234 | Icons.crop_original, 235 | Icons.crop_portrait, 236 | Icons.crop_rotate, 237 | Icons.crop_square, 238 | Icons.dashboard, 239 | Icons.data_usage, 240 | Icons.date_range, 241 | Icons.dehaze, 242 | Icons.delete, 243 | Icons.delete_forever, 244 | Icons.delete_outline, 245 | Icons.delete_sweep, 246 | Icons.departure_board, 247 | Icons.description, 248 | Icons.desktop_mac, 249 | Icons.desktop_windows, 250 | Icons.details, 251 | Icons.developer_board, 252 | Icons.developer_mode, 253 | Icons.device_hub, 254 | Icons.device_unknown, 255 | Icons.devices, 256 | Icons.devices_other, 257 | Icons.dialer_sip, 258 | Icons.dialpad, 259 | Icons.directions, 260 | Icons.directions_bike, 261 | Icons.directions_boat, 262 | Icons.directions_bus, 263 | Icons.directions_car, 264 | Icons.directions_railway, 265 | Icons.directions_run, 266 | Icons.directions_subway, 267 | Icons.directions_transit, 268 | Icons.directions_walk, 269 | Icons.disc_full, 270 | Icons.dns, 271 | Icons.do_not_disturb, 272 | Icons.do_not_disturb_alt, 273 | Icons.do_not_disturb_off, 274 | Icons.do_not_disturb_on, 275 | Icons.dock, 276 | Icons.domain, 277 | Icons.done, 278 | Icons.done_all, 279 | Icons.done_outline, 280 | Icons.donut_large, 281 | Icons.donut_small, 282 | Icons.drafts, 283 | Icons.drag_handle, 284 | Icons.drive_eta, 285 | Icons.dvr, 286 | Icons.edit, 287 | Icons.edit_attributes, 288 | Icons.edit_location, 289 | Icons.eject, 290 | Icons.email, 291 | Icons.enhanced_encryption, 292 | Icons.equalizer, 293 | Icons.error, 294 | Icons.error_outline, 295 | Icons.euro_symbol, 296 | Icons.ev_station, 297 | Icons.event, 298 | Icons.event_available, 299 | Icons.event_busy, 300 | Icons.event_note, 301 | Icons.event_seat, 302 | Icons.exit_to_app, 303 | Icons.expand_less, 304 | Icons.expand_more, 305 | Icons.explicit, 306 | Icons.explore, 307 | Icons.exposure, 308 | Icons.exposure_neg_1, 309 | Icons.exposure_neg_2, 310 | Icons.exposure_plus_1, 311 | Icons.exposure_plus_2, 312 | Icons.exposure_zero, 313 | Icons.extension, 314 | Icons.face, 315 | Icons.fast_forward, 316 | Icons.fast_rewind, 317 | Icons.fastfood, 318 | Icons.favorite, 319 | Icons.favorite_border, 320 | Icons.featured_play_list, 321 | Icons.featured_video, 322 | Icons.feedback, 323 | Icons.fiber_dvr, 324 | Icons.fiber_manual_record, 325 | Icons.fiber_new, 326 | Icons.fiber_pin, 327 | Icons.fiber_smart_record, 328 | Icons.file_download, 329 | Icons.file_upload, 330 | Icons.filter, 331 | Icons.filter_1, 332 | Icons.filter_2, 333 | Icons.filter_3, 334 | Icons.filter_4, 335 | Icons.filter_5, 336 | Icons.filter_6, 337 | Icons.filter_7, 338 | Icons.filter_8, 339 | Icons.filter_9, 340 | Icons.filter_9_plus, 341 | Icons.filter_b_and_w, 342 | Icons.filter_center_focus, 343 | Icons.filter_drama, 344 | Icons.filter_frames, 345 | Icons.filter_hdr, 346 | Icons.filter_list, 347 | Icons.filter_none, 348 | Icons.filter_tilt_shift, 349 | Icons.filter_vintage, 350 | Icons.find_in_page, 351 | Icons.find_replace, 352 | Icons.fingerprint, 353 | Icons.first_page, 354 | Icons.fitness_center, 355 | Icons.flag, 356 | Icons.flare, 357 | Icons.flash_auto, 358 | Icons.flash_off, 359 | Icons.flash_on, 360 | Icons.flight, 361 | Icons.flight_land, 362 | Icons.flight_takeoff, 363 | Icons.flip, 364 | Icons.flip_to_back, 365 | Icons.flip_to_front, 366 | Icons.folder, 367 | Icons.folder_open, 368 | Icons.folder_shared, 369 | Icons.folder_special, 370 | Icons.font_download, 371 | Icons.format_align_center, 372 | Icons.format_align_justify, 373 | Icons.format_align_left, 374 | Icons.format_align_right, 375 | Icons.format_bold, 376 | Icons.format_clear, 377 | Icons.format_color_fill, 378 | Icons.format_color_reset, 379 | Icons.format_color_text, 380 | Icons.format_indent_decrease, 381 | Icons.format_indent_increase, 382 | Icons.format_italic, 383 | Icons.format_line_spacing, 384 | Icons.format_list_bulleted, 385 | Icons.format_list_numbered, 386 | Icons.format_list_numbered_rtl, 387 | Icons.format_paint, 388 | Icons.format_quote, 389 | Icons.format_shapes, 390 | Icons.format_size, 391 | Icons.format_strikethrough, 392 | Icons.format_textdirection_l_to_r, 393 | Icons.format_textdirection_r_to_l, 394 | Icons.format_underlined, 395 | Icons.forum, 396 | Icons.forward, 397 | Icons.forward_10, 398 | Icons.forward_30, 399 | Icons.forward_5, 400 | Icons.free_breakfast, 401 | Icons.fullscreen, 402 | Icons.fullscreen_exit, 403 | Icons.functions, 404 | Icons.g_translate, 405 | Icons.gamepad, 406 | Icons.games, 407 | Icons.gavel, 408 | Icons.gesture, 409 | Icons.get_app, 410 | Icons.gif, 411 | Icons.golf_course, 412 | Icons.gps_fixed, 413 | Icons.gps_not_fixed, 414 | Icons.gps_off, 415 | Icons.grade, 416 | Icons.gradient, 417 | Icons.grain, 418 | Icons.graphic_eq, 419 | Icons.grid_off, 420 | Icons.grid_on, 421 | Icons.group, 422 | Icons.group_add, 423 | Icons.group_work, 424 | Icons.hd, 425 | Icons.hdr_off, 426 | Icons.hdr_on, 427 | Icons.hdr_strong, 428 | Icons.hdr_weak, 429 | Icons.headset, 430 | Icons.headset_mic, 431 | Icons.headset_off, 432 | Icons.healing, 433 | Icons.hearing, 434 | Icons.help, 435 | Icons.help_outline, 436 | Icons.high_quality, 437 | Icons.highlight, 438 | Icons.highlight_off, 439 | Icons.history, 440 | Icons.home, 441 | Icons.hot_tub, 442 | Icons.hotel, 443 | Icons.hourglass_empty, 444 | Icons.hourglass_full, 445 | Icons.http, 446 | Icons.https, 447 | Icons.image, 448 | Icons.image_aspect_ratio, 449 | Icons.import_contacts, 450 | Icons.import_export, 451 | Icons.important_devices, 452 | Icons.inbox, 453 | Icons.indeterminate_check_box, 454 | Icons.info, 455 | Icons.info_outline, 456 | Icons.input, 457 | Icons.insert_chart, 458 | Icons.insert_comment, 459 | Icons.insert_drive_file, 460 | Icons.insert_emoticon, 461 | Icons.insert_invitation, 462 | Icons.insert_link, 463 | Icons.insert_photo, 464 | Icons.invert_colors, 465 | Icons.invert_colors_off, 466 | Icons.iso, 467 | Icons.keyboard, 468 | Icons.keyboard_arrow_down, 469 | Icons.keyboard_arrow_left, 470 | Icons.keyboard_arrow_right, 471 | Icons.keyboard_arrow_up, 472 | Icons.keyboard_backspace, 473 | Icons.keyboard_capslock, 474 | Icons.keyboard_hide, 475 | Icons.keyboard_return, 476 | Icons.keyboard_tab, 477 | Icons.keyboard_voice, 478 | Icons.kitchen, 479 | Icons.label, 480 | Icons.label_important, 481 | Icons.label_outline, 482 | Icons.landscape, 483 | Icons.language, 484 | Icons.laptop, 485 | Icons.laptop_chromebook, 486 | Icons.laptop_mac, 487 | Icons.laptop_windows, 488 | Icons.last_page, 489 | Icons.launch, 490 | Icons.layers, 491 | Icons.layers_clear, 492 | Icons.leak_add, 493 | Icons.leak_remove, 494 | Icons.lens, 495 | Icons.library_add, 496 | Icons.library_books, 497 | Icons.library_music, 498 | Icons.lightbulb_outline, 499 | Icons.line_style, 500 | Icons.line_weight, 501 | Icons.linear_scale, 502 | Icons.link, 503 | Icons.link_off, 504 | Icons.linked_camera, 505 | Icons.list, 506 | Icons.live_help, 507 | Icons.live_tv, 508 | Icons.local_activity, 509 | Icons.local_airport, 510 | Icons.local_atm, 511 | Icons.local_bar, 512 | Icons.local_cafe, 513 | Icons.local_car_wash, 514 | Icons.local_convenience_store, 515 | Icons.local_dining, 516 | Icons.local_drink, 517 | Icons.local_florist, 518 | Icons.local_gas_station, 519 | Icons.local_grocery_store, 520 | Icons.local_hospital, 521 | Icons.local_hotel, 522 | Icons.local_laundry_service, 523 | Icons.local_library, 524 | Icons.local_mall, 525 | Icons.local_movies, 526 | Icons.local_offer, 527 | Icons.local_parking, 528 | Icons.local_pharmacy, 529 | Icons.local_phone, 530 | Icons.local_pizza, 531 | Icons.local_play, 532 | Icons.local_post_office, 533 | Icons.local_printshop, 534 | Icons.local_see, 535 | Icons.local_shipping, 536 | Icons.local_taxi, 537 | Icons.location_city, 538 | Icons.location_disabled, 539 | Icons.location_off, 540 | Icons.location_on, 541 | Icons.location_searching, 542 | Icons.lock, 543 | Icons.lock_open, 544 | Icons.lock_outline, 545 | Icons.looks, 546 | Icons.looks_3, 547 | Icons.looks_4, 548 | Icons.looks_5, 549 | Icons.looks_6, 550 | Icons.looks_one, 551 | Icons.looks_two, 552 | Icons.loop, 553 | Icons.loupe, 554 | Icons.low_priority, 555 | Icons.loyalty, 556 | Icons.mail, 557 | Icons.mail_outline, 558 | Icons.map, 559 | Icons.markunread, 560 | Icons.markunread_mailbox, 561 | Icons.maximize, 562 | Icons.memory, 563 | Icons.menu, 564 | Icons.merge_type, 565 | Icons.message, 566 | Icons.mic, 567 | Icons.mic_none, 568 | Icons.mic_off, 569 | Icons.minimize, 570 | Icons.missed_video_call, 571 | Icons.mms, 572 | Icons.mobile_screen_share, 573 | Icons.mode_comment, 574 | Icons.mode_edit, 575 | Icons.monetization_on, 576 | Icons.money_off, 577 | Icons.monochrome_photos, 578 | Icons.mood, 579 | Icons.mood_bad, 580 | Icons.more, 581 | Icons.more_horiz, 582 | Icons.more_vert, 583 | Icons.motorcycle, 584 | Icons.mouse, 585 | Icons.move_to_inbox, 586 | Icons.movie, 587 | Icons.movie_creation, 588 | Icons.movie_filter, 589 | Icons.multiline_chart, 590 | Icons.music_note, 591 | Icons.music_video, 592 | Icons.my_location, 593 | Icons.nature, 594 | Icons.nature_people, 595 | Icons.navigate_before, 596 | Icons.navigate_next, 597 | Icons.navigation, 598 | Icons.near_me, 599 | Icons.network_cell, 600 | Icons.network_check, 601 | Icons.network_locked, 602 | Icons.network_wifi, 603 | Icons.new_releases, 604 | Icons.next_week, 605 | Icons.nfc, 606 | Icons.no_encryption, 607 | Icons.no_sim, 608 | Icons.not_interested, 609 | Icons.not_listed_location, 610 | Icons.note, 611 | Icons.note_add, 612 | Icons.notification_important, 613 | Icons.notifications, 614 | Icons.notifications_active, 615 | Icons.notifications_none, 616 | Icons.notifications_off, 617 | Icons.notifications_paused, 618 | Icons.offline_bolt, 619 | Icons.offline_pin, 620 | Icons.ondemand_video, 621 | Icons.opacity, 622 | Icons.open_in_browser, 623 | Icons.open_in_new, 624 | Icons.open_with, 625 | Icons.outlined_flag, 626 | Icons.pages, 627 | Icons.pageview, 628 | Icons.palette, 629 | Icons.pan_tool, 630 | Icons.panorama, 631 | Icons.panorama_fish_eye, 632 | Icons.panorama_horizontal, 633 | Icons.panorama_vertical, 634 | Icons.panorama_wide_angle, 635 | Icons.party_mode, 636 | Icons.pause, 637 | Icons.pause_circle_filled, 638 | Icons.pause_circle_outline, 639 | Icons.payment, 640 | Icons.people, 641 | Icons.people_outline, 642 | Icons.perm_camera_mic, 643 | Icons.perm_contact_calendar, 644 | Icons.perm_data_setting, 645 | Icons.perm_device_information, 646 | Icons.perm_identity, 647 | Icons.perm_media, 648 | Icons.perm_phone_msg, 649 | Icons.perm_scan_wifi, 650 | Icons.person, 651 | Icons.person_add, 652 | Icons.person_outline, 653 | Icons.person_pin, 654 | Icons.person_pin_circle, 655 | Icons.personal_video, 656 | Icons.pets, 657 | Icons.phone, 658 | Icons.phone_android, 659 | Icons.phone_bluetooth_speaker, 660 | Icons.phone_forwarded, 661 | Icons.phone_in_talk, 662 | Icons.phone_iphone, 663 | Icons.phone_locked, 664 | Icons.phone_missed, 665 | Icons.phone_paused, 666 | Icons.phonelink, 667 | Icons.phonelink_erase, 668 | Icons.phonelink_lock, 669 | Icons.phonelink_off, 670 | Icons.phonelink_ring, 671 | Icons.phonelink_setup, 672 | Icons.photo, 673 | Icons.photo_album, 674 | Icons.photo_camera, 675 | Icons.photo_filter, 676 | Icons.photo_library, 677 | Icons.photo_size_select_actual, 678 | Icons.photo_size_select_large, 679 | Icons.photo_size_select_small, 680 | Icons.picture_as_pdf, 681 | Icons.picture_in_picture, 682 | Icons.picture_in_picture_alt, 683 | Icons.pie_chart, 684 | Icons.pie_chart_outline_outlined, 685 | Icons.pin_drop, 686 | Icons.place, 687 | Icons.play_arrow, 688 | Icons.play_circle_filled, 689 | Icons.play_circle_outline, 690 | Icons.play_for_work, 691 | Icons.playlist_add, 692 | Icons.playlist_add_check, 693 | Icons.playlist_play, 694 | Icons.plus_one, 695 | Icons.poll, 696 | Icons.polymer, 697 | Icons.pool, 698 | Icons.portable_wifi_off, 699 | Icons.portrait, 700 | Icons.power, 701 | Icons.power_input, 702 | Icons.power_settings_new, 703 | Icons.pregnant_woman, 704 | Icons.present_to_all, 705 | Icons.print, 706 | Icons.priority_high, 707 | Icons.public, 708 | Icons.publish, 709 | Icons.query_builder, 710 | Icons.question_answer, 711 | Icons.queue, 712 | Icons.queue_music, 713 | Icons.queue_play_next, 714 | Icons.radio, 715 | Icons.radio_button_checked, 716 | Icons.radio_button_unchecked, 717 | Icons.rate_review, 718 | Icons.receipt, 719 | Icons.recent_actors, 720 | Icons.record_voice_over, 721 | Icons.redeem, 722 | Icons.redo, 723 | Icons.refresh, 724 | Icons.remove, 725 | Icons.remove_circle, 726 | Icons.remove_circle_outline, 727 | Icons.remove_from_queue, 728 | Icons.remove_red_eye, 729 | Icons.remove_shopping_cart, 730 | Icons.reorder, 731 | Icons.repeat, 732 | Icons.repeat_one, 733 | Icons.replay, 734 | Icons.replay_10, 735 | Icons.replay_30, 736 | Icons.replay_5, 737 | Icons.reply, 738 | Icons.reply_all, 739 | Icons.report, 740 | Icons.report_off, 741 | Icons.report_problem, 742 | Icons.restaurant, 743 | Icons.restaurant_menu, 744 | Icons.restore, 745 | Icons.restore_from_trash, 746 | Icons.restore_page, 747 | Icons.ring_volume, 748 | Icons.room, 749 | Icons.room_service, 750 | Icons.rotate_90_degrees_ccw, 751 | Icons.rotate_left, 752 | Icons.rotate_right, 753 | Icons.rounded_corner, 754 | Icons.router, 755 | Icons.rowing, 756 | Icons.rss_feed, 757 | Icons.rv_hookup, 758 | Icons.satellite, 759 | Icons.save, 760 | Icons.save_alt, 761 | Icons.scanner, 762 | Icons.scatter_plot, 763 | Icons.schedule, 764 | Icons.school, 765 | Icons.score, 766 | Icons.screen_lock_landscape, 767 | Icons.screen_lock_portrait, 768 | Icons.screen_lock_rotation, 769 | Icons.screen_rotation, 770 | Icons.screen_share, 771 | Icons.sd_card, 772 | Icons.sd_storage, 773 | Icons.search, 774 | Icons.security, 775 | Icons.select_all, 776 | Icons.send, 777 | Icons.sentiment_dissatisfied, 778 | Icons.sentiment_neutral, 779 | Icons.sentiment_satisfied, 780 | Icons.sentiment_very_dissatisfied, 781 | Icons.sentiment_very_satisfied, 782 | Icons.settings, 783 | Icons.settings_applications, 784 | Icons.settings_backup_restore, 785 | Icons.settings_bluetooth, 786 | Icons.settings_brightness, 787 | Icons.settings_cell, 788 | Icons.settings_ethernet, 789 | Icons.settings_input_antenna, 790 | Icons.settings_input_component, 791 | Icons.settings_input_composite, 792 | Icons.settings_input_hdmi, 793 | Icons.settings_input_svideo, 794 | Icons.settings_overscan, 795 | Icons.settings_phone, 796 | Icons.settings_power, 797 | Icons.settings_remote, 798 | Icons.settings_system_daydream, 799 | Icons.settings_voice, 800 | Icons.share, 801 | Icons.shop, 802 | Icons.shop_two, 803 | Icons.shopping_basket, 804 | Icons.shopping_cart, 805 | Icons.short_text, 806 | Icons.show_chart, 807 | Icons.shuffle, 808 | Icons.shutter_speed, 809 | Icons.signal_cellular_4_bar, 810 | Icons.signal_cellular_connected_no_internet_4_bar, 811 | Icons.signal_cellular_no_sim, 812 | Icons.signal_cellular_null, 813 | Icons.signal_cellular_off, 814 | Icons.signal_wifi_4_bar, 815 | Icons.signal_wifi_4_bar_lock, 816 | Icons.signal_wifi_off, 817 | Icons.sim_card, 818 | Icons.sim_card_alert, 819 | Icons.skip_next, 820 | Icons.skip_previous, 821 | Icons.slideshow, 822 | Icons.slow_motion_video, 823 | Icons.smartphone, 824 | Icons.smoke_free, 825 | Icons.smoking_rooms, 826 | Icons.sms, 827 | Icons.sms_failed, 828 | Icons.snooze, 829 | Icons.sort, 830 | Icons.sort_by_alpha, 831 | Icons.spa, 832 | Icons.space_bar, 833 | Icons.speaker, 834 | Icons.speaker_group, 835 | Icons.speaker_notes, 836 | Icons.speaker_notes_off, 837 | Icons.speaker_phone, 838 | Icons.spellcheck, 839 | Icons.star, 840 | Icons.star_border, 841 | Icons.star_half, 842 | Icons.stars, 843 | Icons.stay_current_landscape, 844 | Icons.stay_current_portrait, 845 | Icons.stay_primary_landscape, 846 | Icons.stay_primary_portrait, 847 | Icons.stop, 848 | Icons.stop_screen_share, 849 | Icons.storage, 850 | Icons.store, 851 | Icons.store_mall_directory, 852 | Icons.straighten, 853 | Icons.streetview, 854 | Icons.strikethrough_s, 855 | Icons.style, 856 | Icons.subdirectory_arrow_left, 857 | Icons.subdirectory_arrow_right, 858 | Icons.subject, 859 | Icons.subscriptions, 860 | Icons.subtitles, 861 | Icons.subway, 862 | Icons.supervised_user_circle, 863 | Icons.supervisor_account, 864 | Icons.surround_sound, 865 | Icons.swap_calls, 866 | Icons.swap_horiz, 867 | Icons.swap_horizontal_circle, 868 | Icons.swap_vert, 869 | Icons.swap_vertical_circle, 870 | Icons.switch_camera, 871 | Icons.switch_video, 872 | Icons.sync, 873 | Icons.sync_disabled, 874 | Icons.sync_problem, 875 | Icons.system_update, 876 | Icons.system_update_alt, 877 | Icons.tab, 878 | Icons.tab_unselected, 879 | Icons.table_chart, 880 | Icons.tablet, 881 | Icons.tablet_android, 882 | Icons.tablet_mac, 883 | Icons.tag_faces, 884 | Icons.tap_and_play, 885 | Icons.terrain, 886 | Icons.text_fields, 887 | Icons.text_format, 888 | Icons.text_rotate_up, 889 | Icons.text_rotate_vertical, 890 | Icons.text_rotation_angledown, 891 | Icons.text_rotation_angleup, 892 | Icons.text_rotation_down, 893 | Icons.text_rotation_none, 894 | Icons.textsms, 895 | Icons.texture, 896 | Icons.theaters, 897 | Icons.thumb_down, 898 | Icons.thumb_up, 899 | Icons.thumbs_up_down, 900 | Icons.time_to_leave, 901 | Icons.timelapse, 902 | Icons.timeline, 903 | Icons.timer, 904 | Icons.timer_10, 905 | Icons.timer_3, 906 | Icons.timer_off, 907 | Icons.title, 908 | Icons.toc, 909 | Icons.today, 910 | Icons.toll, 911 | Icons.tonality, 912 | Icons.touch_app, 913 | Icons.toys, 914 | Icons.track_changes, 915 | Icons.traffic, 916 | Icons.train, 917 | Icons.tram, 918 | Icons.transfer_within_a_station, 919 | Icons.transform, 920 | Icons.transit_enterexit, 921 | Icons.translate, 922 | Icons.trending_down, 923 | Icons.trending_flat, 924 | Icons.trending_up, 925 | Icons.trip_origin, 926 | Icons.tune, 927 | Icons.turned_in, 928 | Icons.turned_in_not, 929 | Icons.tv, 930 | Icons.unarchive, 931 | Icons.undo, 932 | Icons.unfold_less, 933 | Icons.unfold_more, 934 | Icons.update, 935 | Icons.usb, 936 | Icons.verified_user, 937 | Icons.vertical_align_bottom, 938 | Icons.vertical_align_center, 939 | Icons.vertical_align_top, 940 | Icons.vibration, 941 | Icons.video_call, 942 | Icons.video_label, 943 | Icons.video_library, 944 | Icons.videocam, 945 | Icons.videocam_off, 946 | Icons.videogame_asset, 947 | Icons.view_agenda, 948 | Icons.view_array, 949 | Icons.view_carousel, 950 | Icons.view_column, 951 | Icons.view_comfy, 952 | Icons.view_compact, 953 | Icons.view_day, 954 | Icons.view_headline, 955 | Icons.view_list, 956 | Icons.view_module, 957 | Icons.view_quilt, 958 | Icons.view_stream, 959 | Icons.view_week, 960 | Icons.vignette, 961 | Icons.visibility, 962 | Icons.visibility_off, 963 | Icons.voice_chat, 964 | Icons.voicemail, 965 | Icons.volume_down, 966 | Icons.volume_mute, 967 | Icons.volume_off, 968 | Icons.volume_up, 969 | Icons.vpn_key, 970 | Icons.vpn_lock, 971 | Icons.wallpaper, 972 | Icons.warning, 973 | Icons.watch, 974 | Icons.watch_later, 975 | Icons.wb_auto, 976 | Icons.wb_cloudy, 977 | Icons.wb_incandescent, 978 | Icons.wb_iridescent, 979 | Icons.wb_sunny, 980 | Icons.wc, 981 | Icons.web, 982 | Icons.web_asset, 983 | Icons.weekend, 984 | Icons.whatshot, 985 | Icons.widgets, 986 | Icons.wifi, 987 | Icons.wifi_lock, 988 | Icons.wifi_tethering, 989 | Icons.work, 990 | Icons.wrap_text, 991 | Icons.youtube_searched_for, 992 | Icons.zoom_in, 993 | Icons.zoom_out, 994 | Icons.zoom_out_map, 995 | ]; 996 | 997 | IconPicker({ 998 | required this.currentIconData, 999 | required this.onIconChanged, 1000 | Color? highlightColor, 1001 | Color? unHighlightColor, 1002 | }) : this.highlightColor = highlightColor ?? Colors.red, 1003 | this.unHighlightColor = unHighlightColor ?? Colors.blueGrey; 1004 | 1005 | @override 1006 | State createState() { 1007 | return _IconPickerState(); 1008 | } 1009 | } 1010 | 1011 | class _IconPickerState extends State { 1012 | late IconData selectedIconData; 1013 | 1014 | @override 1015 | void initState() { 1016 | selectedIconData = widget.currentIconData; 1017 | super.initState(); 1018 | } 1019 | 1020 | @override 1021 | Widget build(BuildContext context) { 1022 | Orientation orientation = MediaQuery.of(context).orientation; 1023 | return Container( 1024 | width: orientation == Orientation.portrait ? 300.0 : 300.0, 1025 | height: orientation == Orientation.portrait ? 360.0 : 200.0, 1026 | child: GridView.builder( 1027 | itemBuilder: (BuildContext context, int index) { 1028 | var iconData = widget.icons[index]; 1029 | return Material( 1030 | color: Colors.transparent, 1031 | child: InkWell( 1032 | onTap: () { 1033 | setState(() { 1034 | selectedIconData = iconData; 1035 | }); 1036 | widget.onIconChanged(iconData); 1037 | }, 1038 | borderRadius: BorderRadius.circular(50.0), 1039 | child: TodoBadge( 1040 | id: iconData.hashCode.toString(), 1041 | codePoint: iconData.codePoint, 1042 | outlineColor: iconData == selectedIconData 1043 | ? widget.highlightColor 1044 | : widget.unHighlightColor, 1045 | color: iconData == selectedIconData 1046 | ? widget.highlightColor 1047 | : widget.unHighlightColor, 1048 | size: 32, 1049 | ), 1050 | ), 1051 | ); 1052 | }, 1053 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 1054 | crossAxisCount: orientation == Orientation.portrait ? 4 : 6, 1055 | mainAxisSpacing: 8.0, 1056 | crossAxisSpacing: 8.0, 1057 | childAspectRatio: 1.0, 1058 | ), 1059 | itemCount: widget.icons.length, 1060 | ), 1061 | ); 1062 | } 1063 | } 1064 | -------------------------------------------------------------------------------- /lib/component/iconpicker/icon_picker_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:todo/component/todo_badge.dart'; 3 | 4 | import 'icon_picker.dart'; 5 | 6 | class IconPickerBuilder extends StatelessWidget { 7 | final IconData iconData; 8 | final ValueChanged action; 9 | final Color highlightColor; 10 | 11 | IconPickerBuilder({ 12 | required this.iconData, 13 | required this.action, 14 | required Color highlightColor, 15 | }) : this.highlightColor = highlightColor; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return InkWell( 20 | borderRadius: BorderRadius.circular(50.0), 21 | onTap: () { 22 | showDialog( 23 | context: context, 24 | builder: (BuildContext context) { 25 | return AlertDialog( 26 | title: Text('Select an icon'), 27 | content: SingleChildScrollView( 28 | child: IconPicker( 29 | currentIconData: iconData, 30 | onIconChanged: action, 31 | highlightColor: highlightColor, 32 | ), 33 | ), 34 | ); 35 | }, 36 | ); 37 | }, 38 | child: TodoBadge( 39 | id: 'id', 40 | codePoint: iconData.codePoint, 41 | color: highlightColor, 42 | outlineColor: highlightColor, 43 | size: 24, 44 | ), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/component/todo_badge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TodoBadge extends StatelessWidget { 4 | final int codePoint; 5 | final Color color; 6 | final String id; 7 | final double? size; 8 | final Color outlineColor; 9 | 10 | TodoBadge({ 11 | required this.codePoint, 12 | required this.color, 13 | required this.id, 14 | Color? outlineColor, 15 | this.size, 16 | }) : this.outlineColor = outlineColor ?? Colors.grey.shade200; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Hero( 21 | tag: id, 22 | child: Container( 23 | padding: EdgeInsets.all(8.0), 24 | decoration: BoxDecoration( 25 | shape: BoxShape.circle, 26 | border: Border.all( 27 | color: outlineColor, 28 | ), 29 | ), 30 | child: Icon( 31 | IconData( 32 | codePoint, 33 | fontFamily: 'MaterialIcons', 34 | ), 35 | color: color, 36 | size: size, 37 | ), 38 | ), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/db/db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:sqflite/sqflite.dart'; 3 | import 'package:path/path.dart' as p; 4 | import 'package:path_provider/path_provider.dart'; 5 | import 'dart:io'; 6 | 7 | import 'package:todo/model/todo_model.dart'; 8 | import 'package:todo/model/task_model.dart'; 9 | import 'package:sqflite_common/sqlite_api.dart'; 10 | import 'package:sqflite_common_ffi/sqflite_ffi.dart'; 11 | 12 | class DBProvider { 13 | static Database? _database; 14 | 15 | DBProvider._(); 16 | static final DBProvider db = DBProvider._(); 17 | 18 | var todos = [ 19 | Todo( 20 | "Vegetables", 21 | parent: '1', 22 | ), 23 | Todo( 24 | "Birthday gift", 25 | parent: '1', 26 | ), 27 | Todo("Chocolate cookies", parent: '1', isCompleted: 1), 28 | Todo( 29 | "20 pushups", 30 | parent: '2', 31 | ), 32 | Todo( 33 | "Tricep", 34 | parent: '2', 35 | ), 36 | Todo( 37 | "15 burpees (3 sets)", 38 | parent: '2', 39 | ), 40 | ]; 41 | 42 | var tasks = [ 43 | Task('Shopping', 44 | id: '1', 45 | color: Colors.purple.value, 46 | codePoint: Icons.shopping_cart.codePoint), 47 | Task('Workout', 48 | id: '2', 49 | color: Colors.pink.value, 50 | codePoint: Icons.fitness_center.codePoint), 51 | ]; 52 | 53 | Future get database async { 54 | return _database ?? await initDB(); 55 | } 56 | 57 | get _dbPath async { 58 | String documentsDirectory = await _localPath; 59 | return p.join(documentsDirectory, "Todo.db"); 60 | } 61 | 62 | Future dbExists() async { 63 | return File(await _dbPath).exists(); 64 | } 65 | 66 | initDB() async { 67 | String path = await _dbPath; 68 | if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) { 69 | sqfliteFfiInit(); 70 | var db = await databaseFactoryFfi.openDatabase(path); 71 | await db.execute("CREATE TABLE IF NOT EXISTS Task (" 72 | "id TEXT PRIMARY KEY," 73 | "name TEXT," 74 | "color INTEGER," 75 | "code_point INTEGER" 76 | ")"); 77 | await db.execute("CREATE TABLE IF NOT EXISTS Todo (" 78 | "id TEXT PRIMARY KEY," 79 | "name TEXT," 80 | "parent TEXT," 81 | "completed INTEGER NOT NULL DEFAULT 0" 82 | ")"); 83 | return db; 84 | } 85 | return await openDatabase(path, version: 1, onOpen: (db) {}, 86 | onCreate: (Database db, int version) async { 87 | print("DBProvider:: onCreate()"); 88 | await db.execute("CREATE TABLE IF NOT EXISTS Task (" 89 | "id TEXT PRIMARY KEY," 90 | "name TEXT," 91 | "color INTEGER," 92 | "code_point INTEGER" 93 | ")"); 94 | await db.execute("CREATE TABLE IF NOT EXISTS Todo (" 95 | "id TEXT PRIMARY KEY," 96 | "name TEXT," 97 | "parent TEXT," 98 | "completed INTEGER NOT NULL DEFAULT 0" 99 | ")"); 100 | }); 101 | } 102 | 103 | insertBulkTask(List tasks) async { 104 | final db = await database; 105 | tasks.forEach((it) async { 106 | var res = await db.insert("Task", it.toJson()); 107 | print("Task ${it.id} = $res"); 108 | }); 109 | } 110 | 111 | insertBulkTodo(List todos) async { 112 | final db = await database; 113 | todos.forEach((it) async { 114 | var res = await db.insert("Todo", it.toJson()); 115 | print("Todo ${it.id} = $res"); 116 | }); 117 | } 118 | 119 | Future> getAllTask() async { 120 | final db = await database; 121 | var result = await db.query('Task'); 122 | return result.map((it) => Task.fromJson(it)).toList(); 123 | } 124 | 125 | Future> getAllTodo() async { 126 | final db = await database; 127 | var result = await db.query('Todo'); 128 | return result.map((it) => Todo.fromJson(it)).toList(); 129 | } 130 | 131 | Future updateTodo(Todo todo) async { 132 | final db = await database; 133 | return db 134 | .update('Todo', todo.toJson(), where: 'id = ?', whereArgs: [todo.id]); 135 | } 136 | 137 | Future removeTodo(Todo todo) async { 138 | final db = await database; 139 | return db.delete('Todo', where: 'id = ?', whereArgs: [todo.id]); 140 | } 141 | 142 | Future insertTodo(Todo todo) async { 143 | final db = await database; 144 | return db.insert('Todo', todo.toJson()); 145 | } 146 | 147 | Future insertTask(Task task) async { 148 | final db = await database; 149 | return db.insert('Task', task.toJson()); 150 | } 151 | 152 | Future removeTask(Task task) async { 153 | final db = await database; 154 | return db.transaction((txn) async { 155 | await txn.delete('Todo', where: 'parent = ?', whereArgs: [task.id]); 156 | await txn.delete('Task', where: 'id = ?', whereArgs: [task.id]); 157 | }); 158 | } 159 | 160 | Future updateTask(Task task) async { 161 | final db = await database; 162 | return db 163 | .update('Task', task.toJson(), where: 'id = ?', whereArgs: [task.id]); 164 | } 165 | 166 | Future get _localPath async { 167 | final directory = await getApplicationDocumentsDirectory(); 168 | return directory.path; 169 | } 170 | 171 | closeDB() { 172 | _database?.close(); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /lib/diamond_border.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DiamondBorder extends ShapeBorder { 4 | const DiamondBorder(); 5 | 6 | @override 7 | EdgeInsetsGeometry get dimensions { 8 | return const EdgeInsets.only(); 9 | } 10 | 11 | @override 12 | Path getInnerPath(Rect rect, {TextDirection? textDirection}) { 13 | return getOuterPath(rect, textDirection: textDirection); 14 | } 15 | 16 | @override 17 | Path getOuterPath(Rect rect, {TextDirection? textDirection}) { 18 | return Path() 19 | ..moveTo(rect.left + rect.width / 2.0, rect.top) 20 | ..lineTo(rect.right, rect.top + rect.height / 2.0) 21 | ..lineTo(rect.left + rect.width / 2.0, rect.bottom) 22 | ..lineTo(rect.left, rect.top + rect.height / 2.0) 23 | ..close(); 24 | } 25 | 26 | @override 27 | void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} 28 | 29 | @override 30 | ShapeBorder scale(double t) { 31 | return CircleBorder().scale(t); 32 | } 33 | } 34 | 35 | // https://proandroiddev.com/a-deep-dive-into-floatingactionbutton-in-flutter-bf95bee11627 -------------------------------------------------------------------------------- /lib/gradient_background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class GradientBackground extends StatelessWidget { 4 | final Widget child; 5 | final Color color; 6 | 7 | GradientBackground({required this.child, required this.color}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return AnimatedContainer( 12 | decoration: BoxDecoration( 13 | // Box decoration takes a gradient 14 | gradient: LinearGradient( 15 | // Where the linear gradient begins and ends 16 | begin: Alignment.topRight, 17 | end: Alignment.bottomLeft, 18 | // Add one stop for each color. Stops should increase from 0 to 1 19 | stops: [0.3, 0.5, 0.7, 0.9], 20 | colors: getColorList(color)), 21 | ), 22 | curve: Curves.linear, 23 | child: child, 24 | duration: Duration(milliseconds: 500), 25 | ); 26 | } 27 | 28 | List getColorList(Color color) { 29 | if (color is MaterialColor) { 30 | return [ 31 | color.shade300, 32 | color.shade600, 33 | color.shade700, 34 | color.shade900, 35 | ]; 36 | } else { 37 | return List.filled(4, color); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | import 'package:todo/scopedmodel/todo_list_model.dart'; 5 | import 'package:todo/gradient_background.dart'; 6 | import 'package:todo/task_progress_indicator.dart'; 7 | import 'package:todo/page/add_task_screen.dart'; 8 | import 'package:todo/model/hero_id_model.dart'; 9 | import 'package:todo/model/task_model.dart'; 10 | import 'package:todo/route/scale_route.dart'; 11 | import 'package:todo/utils/color_utils.dart'; 12 | import 'package:todo/utils/datetime_utils.dart'; 13 | import 'package:todo/page/detail_screen.dart'; 14 | import 'package:todo/component/todo_badge.dart'; 15 | import 'package:todo/page/privacy_policy.dart'; 16 | import 'package:todo/model/data/choice_card.dart'; 17 | 18 | void main() => runApp(MyApp()); 19 | 20 | class MyApp extends StatelessWidget { 21 | @override 22 | Widget build(BuildContext context) { 23 | var app = MaterialApp( 24 | title: 'Todo', 25 | debugShowCheckedModeBanner: false, 26 | theme: ThemeData( 27 | primarySwatch: Colors.deepPurple, 28 | textTheme: TextTheme( 29 | headline1: TextStyle(fontSize: 32.0, fontWeight: FontWeight.w400), 30 | subtitle1: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w500), 31 | bodyText1: TextStyle( 32 | fontSize: 14.0, 33 | fontFamily: 'Hind', 34 | ), 35 | ), 36 | ), 37 | home: MyHomePage(title: ''), 38 | ); 39 | 40 | return ScopedModel( 41 | model: TodoListModel(), 42 | child: app, 43 | ); 44 | } 45 | } 46 | 47 | class MyHomePage extends StatefulWidget { 48 | MyHomePage({Key? key, required this.title}) : super(key: key); 49 | 50 | final String title; 51 | 52 | HeroId _generateHeroIds(Task task) { 53 | return HeroId( 54 | codePointId: 'code_point_id_${task.id}', 55 | progressId: 'progress_id_${task.id}', 56 | titleId: 'title_id_${task.id}', 57 | remainingTaskId: 'remaining_task_id_${task.id}', 58 | ); 59 | } 60 | 61 | String currentDay(BuildContext context) { 62 | return DateTimeUtils.currentDay; 63 | } 64 | 65 | @override 66 | _MyHomePageState createState() => _MyHomePageState(); 67 | } 68 | 69 | class _MyHomePageState extends State 70 | with SingleTickerProviderStateMixin { 71 | late AnimationController _controller; 72 | late Animation _animation; 73 | final GlobalKey _backdropKey = GlobalKey(debugLabel: 'Backdrop'); 74 | late PageController _pageController; 75 | int _currentPageIndex = 0; 76 | 77 | @override 78 | void initState() { 79 | super.initState(); 80 | _controller = AnimationController( 81 | vsync: this, 82 | duration: Duration(milliseconds: 300), 83 | ); 84 | _animation = Tween(begin: 0.0, end: 1.0).animate(_controller); 85 | _pageController = PageController(initialPage: 0, viewportFraction: 0.8); 86 | } 87 | 88 | @override 89 | Widget build(BuildContext context) { 90 | return ScopedModelDescendant( 91 | builder: (BuildContext context, Widget? child, TodoListModel model) { 92 | var _isLoading = model.isLoading; 93 | var _tasks = model.tasks; 94 | var _todos = model.todos; 95 | var backgroundColor = _tasks.isEmpty || _tasks.length == _currentPageIndex 96 | ? Colors.blueGrey 97 | : ColorUtils.getColorFrom(id: _tasks[_currentPageIndex].color); 98 | if (!_isLoading) { 99 | // move the animation value towards upperbound only when loading is complete 100 | _controller.forward(); 101 | } 102 | return GradientBackground( 103 | color: backgroundColor, 104 | child: Scaffold( 105 | backgroundColor: Colors.transparent, 106 | appBar: AppBar( 107 | title: Text(widget.title), 108 | centerTitle: true, 109 | elevation: 0.0, 110 | backgroundColor: Colors.transparent, 111 | actions: [ 112 | PopupMenuButton( 113 | onSelected: (choice) { 114 | Navigator.of(context).push(MaterialPageRoute( 115 | builder: (BuildContext context) => 116 | PrivacyPolicyScreen())); 117 | }, 118 | itemBuilder: (BuildContext context) { 119 | return choices.map((Choice choice) { 120 | return PopupMenuItem( 121 | value: choice, 122 | child: Text(choice.title), 123 | ); 124 | }).toList(); 125 | }, 126 | ), 127 | ], 128 | ), 129 | body: _isLoading 130 | ? Center( 131 | child: CircularProgressIndicator( 132 | strokeWidth: 1.0, 133 | valueColor: new AlwaysStoppedAnimation(Colors.white), 134 | ), 135 | ) 136 | : FadeTransition( 137 | opacity: _animation, 138 | child: Column( 139 | crossAxisAlignment: CrossAxisAlignment.start, 140 | children: [ 141 | Container( 142 | margin: EdgeInsets.only(top: 0.0, left: 56.0), 143 | child: Column( 144 | crossAxisAlignment: CrossAxisAlignment.start, 145 | children: [ 146 | // ShadowImage(), 147 | Container( 148 | // margin: EdgeInsets.only(top: 22.0), 149 | child: Text( 150 | '${widget.currentDay(context)}', 151 | style: Theme.of(context) 152 | .textTheme 153 | .headline1 154 | ?.copyWith(color: Colors.white), 155 | ), 156 | ), 157 | Text( 158 | '${DateTimeUtils.currentDate} ${DateTimeUtils.currentMonth}', 159 | style: Theme.of(context) 160 | .textTheme 161 | .subtitle1 162 | ?.copyWith( 163 | color: Colors.white.withOpacity(0.7)), 164 | ), 165 | Container(height: 16.0), 166 | Text( 167 | 'You have ${_todos.where((todo) => todo.isCompleted == 0).length} tasks to complete', 168 | style: Theme.of(context) 169 | .textTheme 170 | .bodyText1 171 | ?.copyWith( 172 | color: Colors.white.withOpacity(0.7)), 173 | ), 174 | Container( 175 | height: 16.0, 176 | ) 177 | // Container( 178 | // margin: EdgeInsets.only(top: 42.0), 179 | // child: Text( 180 | // 'TODAY : FEBURARY 13, 2019', 181 | // style: Theme.of(context) 182 | // .textTheme 183 | // .subtitle 184 | // .copyWith(color: Colors.white.withOpacity(0.8)), 185 | // ), 186 | // ), 187 | ], 188 | ), 189 | ), 190 | Expanded( 191 | key: _backdropKey, 192 | flex: 1, 193 | child: NotificationListener( 194 | onNotification: (notification) { 195 | if (notification is ScrollEndNotification) { 196 | print( 197 | "ScrollNotification = ${_pageController.page}"); 198 | var currentPage = 199 | _pageController.page?.round().toInt() ?? 0; 200 | if (_currentPageIndex != currentPage) { 201 | setState(() => _currentPageIndex = currentPage); 202 | } 203 | } 204 | return true; 205 | }, 206 | child: PageView.builder( 207 | controller: _pageController, 208 | itemBuilder: (BuildContext context, int index) { 209 | if (index == _tasks.length) { 210 | return AddPageCard( 211 | color: Colors.blueGrey, 212 | ); 213 | } else { 214 | return TaskCard( 215 | backdropKey: _backdropKey, 216 | color: ColorUtils.getColorFrom( 217 | id: _tasks[index].color), 218 | getHeroIds: widget._generateHeroIds, 219 | getTaskCompletionPercent: 220 | model.getTaskCompletionPercent, 221 | getTotalTodos: model.getTotalTodosFrom, 222 | task: _tasks[index], 223 | ); 224 | } 225 | }, 226 | itemCount: _tasks.length + 1, 227 | ), 228 | ), 229 | ), 230 | Container( 231 | margin: EdgeInsets.only(bottom: 32.0), 232 | ), 233 | ], 234 | ), 235 | ), 236 | ), 237 | ); 238 | }); 239 | } 240 | 241 | @override 242 | void dispose() { 243 | _controller.dispose(); 244 | super.dispose(); 245 | } 246 | } 247 | 248 | class AddPageCard extends StatelessWidget { 249 | final Color color; 250 | 251 | const AddPageCard({Key? key, this.color = Colors.black}) : super(key: key); 252 | 253 | @override 254 | Widget build(BuildContext context) { 255 | return Card( 256 | shape: RoundedRectangleBorder( 257 | borderRadius: BorderRadius.circular(16.0), 258 | ), 259 | elevation: 4.0, 260 | margin: EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), 261 | child: Material( 262 | borderRadius: BorderRadius.circular(16.0), 263 | color: Colors.white, 264 | child: InkWell( 265 | onTap: () { 266 | Navigator.push( 267 | context, 268 | MaterialPageRoute( 269 | builder: (context) => AddTaskScreen(), 270 | ), 271 | ); 272 | }, 273 | child: Padding( 274 | padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), 275 | child: Column( 276 | mainAxisAlignment: MainAxisAlignment.center, 277 | children: [ 278 | Icon( 279 | Icons.add, 280 | size: 52.0, 281 | color: color, 282 | ), 283 | Container( 284 | height: 8.0, 285 | ), 286 | Text( 287 | 'Add Category', 288 | style: TextStyle(color: color), 289 | ), 290 | ], 291 | ), 292 | ), 293 | ), 294 | ), 295 | ); 296 | } 297 | } 298 | 299 | typedef TaskGetter = V Function(T value); 300 | 301 | class TaskCard extends StatelessWidget { 302 | final GlobalKey backdropKey; 303 | final Task task; 304 | final Color color; 305 | 306 | final TaskGetter getTotalTodos; 307 | final TaskGetter getHeroIds; 308 | final TaskGetter getTaskCompletionPercent; 309 | 310 | TaskCard({ 311 | required this.backdropKey, 312 | required this.color, 313 | required this.task, 314 | required this.getTotalTodos, 315 | required this.getHeroIds, 316 | required this.getTaskCompletionPercent, 317 | }); 318 | 319 | @override 320 | Widget build(BuildContext context) { 321 | var heroIds = getHeroIds(task); 322 | return GestureDetector( 323 | onTap: () { 324 | final RenderBox? renderBox = 325 | backdropKey.currentContext?.findRenderObject() as RenderBox; 326 | var backDropHeight = renderBox?.size.height ?? 0; 327 | var bottomOffset = 60.0; 328 | var horizontalOffset = 52.0; 329 | var topOffset = MediaQuery.of(context).size.height - backDropHeight; 330 | 331 | var rect = RelativeRect.fromLTRB( 332 | horizontalOffset, topOffset, horizontalOffset, bottomOffset); 333 | Navigator.push( 334 | context, 335 | ScaleRoute( 336 | rect: rect, 337 | widget: DetailScreen( 338 | taskId: task.id, 339 | heroIds: heroIds, 340 | ), 341 | ), 342 | // MaterialPageRoute( 343 | // builder: (context) => DetailScreen( 344 | // taskId: task.id, 345 | // heroIds: heroIds, 346 | // ), 347 | // ), 348 | ); 349 | }, 350 | child: Card( 351 | shape: RoundedRectangleBorder( 352 | borderRadius: BorderRadius.circular(16.0), 353 | ), 354 | elevation: 4.0, 355 | margin: EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), 356 | color: Colors.white, 357 | child: Padding( 358 | padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), 359 | child: Column( 360 | crossAxisAlignment: CrossAxisAlignment.start, 361 | mainAxisAlignment: MainAxisAlignment.end, 362 | children: [ 363 | TodoBadge( 364 | id: heroIds.codePointId, 365 | codePoint: task.codePoint, 366 | color: ColorUtils.getColorFrom( 367 | id: task.color, 368 | ), 369 | ), 370 | Spacer( 371 | flex: 8, 372 | ), 373 | Container( 374 | margin: EdgeInsets.only(bottom: 4.0), 375 | child: Hero( 376 | tag: heroIds.remainingTaskId, 377 | child: Text( 378 | "${getTotalTodos(task)} Task", 379 | style: Theme.of(context) 380 | .textTheme 381 | .bodyText1 382 | ?.copyWith(color: Colors.grey[500]), 383 | ), 384 | ), 385 | ), 386 | Container( 387 | child: Hero( 388 | tag: heroIds.titleId, 389 | child: Text(task.name, 390 | style: Theme.of(context) 391 | .textTheme 392 | .subtitle1 393 | ?.copyWith(color: Colors.black54)), 394 | ), 395 | ), 396 | Spacer(), 397 | Hero( 398 | tag: heroIds.progressId, 399 | child: TaskProgressIndicator( 400 | color: color, 401 | progress: getTaskCompletionPercent(task), 402 | ), 403 | ), 404 | ], 405 | ), 406 | ), 407 | ), 408 | ); 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /lib/model/data/choice_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Choice { 4 | const Choice({required this.title, required this.icon}); 5 | 6 | final String title; 7 | final IconData icon; 8 | } 9 | 10 | const List choices = const [ 11 | const Choice(title: 'Privacy Policy', icon: Icons.vpn_key), 12 | ]; 13 | -------------------------------------------------------------------------------- /lib/model/hero_id_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | class HeroId { 4 | final String progressId; 5 | final String titleId; 6 | final String codePointId; 7 | final String remainingTaskId; 8 | 9 | HeroId({ 10 | required this.progressId, 11 | required this.titleId, 12 | required this.codePointId, 13 | required this.remainingTaskId, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/model/task_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | import 'package:todo/utils/uuid.dart'; 5 | 6 | part 'task_model.g.dart'; 7 | 8 | @JsonSerializable() 9 | class Task { 10 | String id; 11 | String name; 12 | int color; 13 | @JsonKey(name: 'code_point') 14 | int codePoint; 15 | 16 | Task( 17 | this.name, { 18 | required this.color, 19 | required this.codePoint, 20 | String? id, 21 | }) : this.id = id ?? Uuid().generateV4(); 22 | 23 | /// A necessary factory constructor for creating a new User instance 24 | /// from a map. Pass the map to the generated `_$TaskFromJson()` constructor. 25 | /// The constructor is named after the source class, in this case User. 26 | factory Task.fromJson(Map json) => _$TaskFromJson(json); 27 | 28 | /// `toJson` is the convention for a class to declare support for serialization 29 | /// to JSON. The implementation simply calls the private, generated 30 | /// helper method `_$TaskFromJson`. 31 | Map toJson() => _$TaskToJson(this); 32 | } 33 | -------------------------------------------------------------------------------- /lib/model/task_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'task_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Task _$TaskFromJson(Map json) { 10 | return Task(json['name'] as String, 11 | color: json['color'] as int, 12 | codePoint: json['code_point'] as int, 13 | id: json['id'] as String); 14 | } 15 | 16 | Map _$TaskToJson(Task instance) => { 17 | 'id': instance.id, 18 | 'name': instance.name, 19 | 'color': instance.color, 20 | 'code_point': instance.codePoint 21 | }; 22 | -------------------------------------------------------------------------------- /lib/model/todo_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | import 'package:todo/utils/uuid.dart'; 5 | 6 | part 'todo_model.g.dart'; 7 | 8 | @JsonSerializable() 9 | class Todo { 10 | final String id, parent; 11 | final String name; 12 | @JsonKey(name: 'completed') 13 | final int isCompleted; 14 | 15 | Todo(this.name, {required this.parent, this.isCompleted = 0, String? id}) 16 | : this.id = id ?? Uuid().generateV4(); 17 | 18 | Todo copy({String? name, int? isCompleted, String? id, String? parent}) { 19 | return Todo( 20 | name ?? this.name, 21 | isCompleted: isCompleted ?? this.isCompleted, 22 | id: id ?? this.id, 23 | parent: parent ?? this.parent, 24 | ); 25 | } 26 | 27 | /// A necessary factory constructor for creating a new User instance 28 | /// from a map. Pass the map to the generated `_$TodoFromJson()` constructor. 29 | /// The constructor is named after the source class, in this case User. 30 | factory Todo.fromJson(Map json) => _$TodoFromJson(json); 31 | 32 | /// `toJson` is the convention for a class to declare support for serialization 33 | /// to JSON. The implementation simply calls the private, generated 34 | /// helper method `_$TodoFromJson`. 35 | Map toJson() => _$TodoToJson(this); 36 | } 37 | -------------------------------------------------------------------------------- /lib/model/todo_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'todo_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Todo _$TodoFromJson(Map json) { 10 | return Todo(json['name'] as String, 11 | parent: json['parent'] as String, 12 | isCompleted: json['completed'] as int, 13 | id: json['id'] as String); 14 | } 15 | 16 | Map _$TodoToJson(Todo instance) => { 17 | 'id': instance.id, 18 | 'parent': instance.parent, 19 | 'name': instance.name, 20 | 'completed': instance.isCompleted 21 | }; 22 | -------------------------------------------------------------------------------- /lib/page/add_task_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | import 'package:todo/scopedmodel/todo_list_model.dart'; 5 | import 'package:todo/model/task_model.dart'; 6 | import 'package:todo/component/iconpicker/icon_picker_builder.dart'; 7 | import 'package:todo/component/colorpicker/color_picker_builder.dart'; 8 | import 'package:todo/utils/color_utils.dart'; 9 | 10 | class AddTaskScreen extends StatefulWidget { 11 | AddTaskScreen(); 12 | 13 | @override 14 | State createState() { 15 | return _AddTaskScreenState(); 16 | } 17 | } 18 | 19 | class _AddTaskScreenState extends State { 20 | late String newTask; 21 | final GlobalKey _scaffoldKey = new GlobalKey(); 22 | late Color taskColor; 23 | late IconData taskIcon; 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | newTask = ''; 29 | taskColor = ColorUtils.defaultColors[0]; 30 | taskIcon = Icons.work; 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return ScopedModelDescendant( 36 | builder: (BuildContext context, Widget? child, TodoListModel model) { 37 | return Scaffold( 38 | key: _scaffoldKey, 39 | backgroundColor: Colors.white, 40 | appBar: AppBar( 41 | title: Text( 42 | 'New Category', 43 | style: TextStyle(color: Colors.black), 44 | ), 45 | centerTitle: true, 46 | elevation: 0, 47 | iconTheme: IconThemeData(color: Colors.black26), 48 | brightness: Brightness.light, 49 | backgroundColor: Colors.white, 50 | ), 51 | body: Container( 52 | constraints: BoxConstraints.expand(), 53 | padding: EdgeInsets.symmetric(horizontal: 36.0, vertical: 36.0), 54 | child: Column( 55 | crossAxisAlignment: CrossAxisAlignment.start, 56 | children: [ 57 | Text( 58 | 'Category will help you group related task!', 59 | style: TextStyle( 60 | color: Colors.black38, 61 | fontWeight: FontWeight.w600, 62 | fontSize: 16.0), 63 | ), 64 | Container( 65 | height: 16.0, 66 | ), 67 | TextField( 68 | onChanged: (text) { 69 | setState(() => newTask = text); 70 | }, 71 | cursorColor: taskColor, 72 | autofocus: true, 73 | decoration: InputDecoration( 74 | border: InputBorder.none, 75 | hintText: 'Category Name...', 76 | hintStyle: TextStyle( 77 | color: Colors.black26, 78 | )), 79 | style: TextStyle( 80 | color: Colors.black54, 81 | fontWeight: FontWeight.w500, 82 | fontSize: 36.0), 83 | ), 84 | Container( 85 | height: 26.0, 86 | ), 87 | Row( 88 | children: [ 89 | ColorPickerBuilder( 90 | color: taskColor, 91 | onColorChanged: (newColor) => 92 | setState(() => taskColor = newColor)), 93 | Container( 94 | width: 22.0, 95 | ), 96 | IconPickerBuilder( 97 | iconData: taskIcon, 98 | highlightColor: taskColor, 99 | action: (newIcon) => 100 | setState(() => taskIcon = newIcon)), 101 | ], 102 | ), 103 | ], 104 | ), 105 | ), 106 | floatingActionButtonLocation: 107 | FloatingActionButtonLocation.centerFloat, 108 | floatingActionButton: Builder( 109 | builder: (BuildContext context) { 110 | return FloatingActionButton.extended( 111 | heroTag: 'fab_new_card', 112 | icon: Icon(Icons.save), 113 | backgroundColor: taskColor, 114 | label: Text('Create New Card'), 115 | onPressed: () { 116 | if (newTask.isEmpty) { 117 | final snackBar = SnackBar( 118 | content: Text( 119 | 'Ummm... It seems that you are trying to add an invisible task which is not allowed in this realm.'), 120 | backgroundColor: taskColor, 121 | ); 122 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 123 | // _scaffoldKey.currentState.showSnackBar(snackBar); 124 | } else { 125 | model.addTask(Task(newTask, 126 | codePoint: taskIcon.codePoint, color: taskColor.value)); 127 | Navigator.pop(context); 128 | } 129 | }, 130 | ); 131 | }, 132 | ), 133 | ); 134 | }, 135 | ); 136 | } 137 | } 138 | // Reason for wraping fab with builder (to get scafold context) 139 | // https://stackoverflow.com/a/52123080/4934757 140 | -------------------------------------------------------------------------------- /lib/page/add_todo_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | import 'package:todo/scopedmodel/todo_list_model.dart'; 5 | import 'package:todo/model/todo_model.dart'; 6 | import 'package:todo/utils/color_utils.dart'; 7 | import 'package:todo/component/todo_badge.dart'; 8 | import 'package:todo/model/hero_id_model.dart'; 9 | 10 | class AddTodoScreen extends StatefulWidget { 11 | final String taskId; 12 | final HeroId heroIds; 13 | 14 | AddTodoScreen({ 15 | required this.taskId, 16 | required this.heroIds, 17 | }); 18 | 19 | @override 20 | State createState() { 21 | return _AddTodoScreenState(); 22 | } 23 | } 24 | 25 | class _AddTodoScreenState extends State { 26 | late String newTask; 27 | final GlobalKey _scaffoldKey = new GlobalKey(); 28 | 29 | @override 30 | void initState() { 31 | super.initState(); 32 | newTask = ''; 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return ScopedModelDescendant( 38 | builder: (BuildContext context, Widget? child, TodoListModel model) { 39 | if (model.tasks.isEmpty) { 40 | // Loading 41 | return Container( 42 | color: Colors.white, 43 | ); 44 | } 45 | 46 | var _task = model.tasks.firstWhere((it) => it.id == widget.taskId); 47 | var _color = ColorUtils.getColorFrom(id: _task.color); 48 | return Scaffold( 49 | key: _scaffoldKey, 50 | backgroundColor: Colors.white, 51 | appBar: AppBar( 52 | title: Text( 53 | 'New Task', 54 | style: TextStyle(color: Colors.black), 55 | ), 56 | centerTitle: true, 57 | elevation: 0, 58 | iconTheme: IconThemeData(color: Colors.black26), 59 | brightness: Brightness.light, 60 | backgroundColor: Colors.white, 61 | ), 62 | body: Container( 63 | constraints: BoxConstraints.expand(), 64 | padding: EdgeInsets.symmetric(horizontal: 36.0, vertical: 36.0), 65 | child: Column( 66 | crossAxisAlignment: CrossAxisAlignment.start, 67 | children: [ 68 | Text( 69 | 'What task are you planning to perfrom?', 70 | style: TextStyle( 71 | color: Colors.black38, 72 | fontWeight: FontWeight.w600, 73 | fontSize: 16.0), 74 | ), 75 | Container( 76 | height: 16.0, 77 | ), 78 | TextField( 79 | onChanged: (text) { 80 | setState(() => newTask = text); 81 | }, 82 | cursorColor: _color, 83 | autofocus: true, 84 | decoration: InputDecoration( 85 | border: InputBorder.none, 86 | hintText: 'Your Task...', 87 | hintStyle: TextStyle( 88 | color: Colors.black26, 89 | )), 90 | style: TextStyle( 91 | color: Colors.black54, 92 | fontWeight: FontWeight.w500, 93 | fontSize: 36.0), 94 | ), 95 | Container( 96 | height: 26.0, 97 | ), 98 | Row( 99 | children: [ 100 | TodoBadge( 101 | codePoint: _task.codePoint, 102 | color: _color, 103 | id: widget.heroIds.codePointId, 104 | size: 20.0, 105 | ), 106 | Container( 107 | width: 16.0, 108 | ), 109 | Hero( 110 | child: Text( 111 | _task.name, 112 | style: TextStyle( 113 | color: Colors.black38, 114 | fontWeight: FontWeight.w600, 115 | ), 116 | ), 117 | tag: "not_using_right_now", //widget.heroIds.titleId, 118 | ), 119 | ], 120 | ) 121 | ], 122 | ), 123 | ), 124 | floatingActionButtonLocation: 125 | FloatingActionButtonLocation.centerFloat, 126 | floatingActionButton: Builder( 127 | builder: (BuildContext context) { 128 | return FloatingActionButton.extended( 129 | heroTag: 'fab_new_task', 130 | icon: Icon(Icons.add), 131 | backgroundColor: _color, 132 | label: Text('Create Task'), 133 | onPressed: () { 134 | if (newTask.isEmpty) { 135 | final snackBar = SnackBar( 136 | content: Text( 137 | 'Ummm... It seems that you are trying to add an invisible task which is not allowed in this realm.'), 138 | backgroundColor: _color, 139 | ); 140 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 141 | // _scaffoldKey.currentState.showSnackBar(snackBar); 142 | } else { 143 | model.addTodo(Todo( 144 | newTask, 145 | parent: _task.id, 146 | )); 147 | Navigator.pop(context); 148 | } 149 | }, 150 | ); 151 | }, 152 | ), 153 | ); 154 | }, 155 | ); 156 | } 157 | } 158 | 159 | // Reason for wraping fab with builder (to get scafold context) 160 | // https://stackoverflow.com/a/52123080/4934757 161 | -------------------------------------------------------------------------------- /lib/page/detail_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | import 'package:todo/scopedmodel/todo_list_model.dart'; 5 | import 'package:todo/task_progress_indicator.dart'; 6 | import 'package:todo/component/todo_badge.dart'; 7 | import 'package:todo/model/hero_id_model.dart'; 8 | import 'package:todo/model/task_model.dart'; 9 | import 'package:todo/utils/color_utils.dart'; 10 | import 'package:todo/page/add_todo_screen.dart'; 11 | import 'package:todo/page/edit_task_screen.dart'; 12 | 13 | class DetailScreen extends StatefulWidget { 14 | final String taskId; 15 | final HeroId heroIds; 16 | 17 | DetailScreen({ 18 | required this.taskId, 19 | required this.heroIds, 20 | }); 21 | 22 | @override 23 | State createState() { 24 | return _DetailScreenState(); 25 | } 26 | } 27 | 28 | class _DetailScreenState extends State 29 | with SingleTickerProviderStateMixin { 30 | late AnimationController _controller; 31 | late Animation _animation; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | _controller = AnimationController( 37 | vsync: this, 38 | duration: Duration(milliseconds: 300), 39 | ); 40 | _animation = Tween(begin: Offset(0, 1.0), end: Offset(0.0, 0.0)) 41 | .animate(_controller); 42 | } 43 | 44 | // getContainer(bool isCompleted, {Widget child}) { 45 | // if (isCompleted) { 46 | // return Container( 47 | // padding: EdgeInsets.only(left: 22.0, right: 22.0), 48 | // decoration: BoxDecoration( 49 | // gradient: LinearGradient( 50 | // begin: Alignment.centerLeft, 51 | // end: Alignment.centerRight, 52 | // stops: [0.4, 0.6, 1], 53 | // colors: [ 54 | // Colors.grey.shade100, 55 | // Colors.grey.shade50, 56 | // Colors.white, 57 | // ], 58 | // ), 59 | // ), 60 | // child: child, 61 | // ); 62 | // } else { 63 | // return Container( 64 | // padding: EdgeInsets.only(left: 22.0, right: 22.0), 65 | // child: child, 66 | // ); 67 | // } 68 | // } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | _controller.forward(); 73 | return ScopedModelDescendant( 74 | builder: (BuildContext context, Widget? child, TodoListModel model) { 75 | Task _task; 76 | 77 | try { 78 | _task = model.tasks.firstWhere((it) => it.id == widget.taskId); 79 | } catch (e) { 80 | return Container( 81 | color: Colors.white, 82 | ); 83 | } 84 | 85 | var _todos = 86 | model.todos.where((it) => it.parent == widget.taskId).toList(); 87 | var _hero = widget.heroIds; 88 | var _color = ColorUtils.getMaterialColorFrom(id: _task.color); 89 | var _icon = IconData(_task.codePoint, fontFamily: 'MaterialIcons'); 90 | 91 | return Theme( 92 | data: ThemeData(primarySwatch: _color), 93 | child: Scaffold( 94 | backgroundColor: Colors.white, 95 | appBar: AppBar( 96 | elevation: 0, 97 | iconTheme: IconThemeData(color: Colors.black26), 98 | brightness: Brightness.light, 99 | backgroundColor: Colors.white, 100 | actions: [ 101 | IconButton( 102 | icon: Icon(Icons.edit), 103 | color: _color, 104 | onPressed: () { 105 | Navigator.push( 106 | context, 107 | MaterialPageRoute( 108 | builder: (context) => EditTaskScreen( 109 | taskId: _task.id, 110 | taskName: _task.name, 111 | icon: _icon, 112 | color: _color, 113 | ), 114 | ), 115 | ); 116 | }, 117 | ), 118 | SimpleAlertDialog( 119 | color: _color, 120 | onActionPressed: () => model.removeTask(_task), 121 | ), 122 | ], 123 | ), 124 | body: Padding( 125 | padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 8.0), 126 | child: Column(children: [ 127 | Container( 128 | margin: EdgeInsets.symmetric(horizontal: 36.0, vertical: 0.0), 129 | height: 160, 130 | child: Column( 131 | crossAxisAlignment: CrossAxisAlignment.start, 132 | mainAxisAlignment: MainAxisAlignment.end, 133 | children: [ 134 | TodoBadge( 135 | color: _color, 136 | codePoint: _task.codePoint, 137 | id: _hero.codePointId, 138 | ), 139 | Spacer( 140 | flex: 1, 141 | ), 142 | Container( 143 | margin: EdgeInsets.only(bottom: 4.0), 144 | child: Hero( 145 | tag: _hero.remainingTaskId, 146 | child: Text( 147 | "${model.getTotalTodosFrom(_task)} Task", 148 | style: Theme.of(context) 149 | .textTheme 150 | .bodyText1 151 | ?.copyWith(color: Colors.grey[500]), 152 | ), 153 | ), 154 | ), 155 | Container( 156 | child: Hero( 157 | tag: 'title_hero_unused', //_hero.titleId, 158 | child: Text(_task.name, 159 | style: Theme.of(context) 160 | .textTheme 161 | .subtitle1 162 | ?.copyWith(color: Colors.black54)), 163 | ), 164 | ), 165 | Spacer(), 166 | Hero( 167 | tag: _hero.progressId, 168 | child: TaskProgressIndicator( 169 | color: _color, 170 | progress: model.getTaskCompletionPercent(_task), 171 | ), 172 | ) 173 | ], 174 | ), 175 | ), 176 | Expanded( 177 | child: Padding( 178 | padding: EdgeInsets.only(top: 16.0), 179 | child: ListView.builder( 180 | itemBuilder: (BuildContext context, int index) { 181 | if (index == _todos.length) { 182 | return SizedBox( 183 | height: 56, // size of FAB 184 | ); 185 | } 186 | var todo = _todos[index]; 187 | return Container( 188 | padding: EdgeInsets.only(left: 22.0, right: 22.0), 189 | child: ListTile( 190 | onTap: () => model.updateTodo(todo.copy( 191 | isCompleted: todo.isCompleted == 1 ? 0 : 1)), 192 | contentPadding: EdgeInsets.symmetric( 193 | horizontal: 0, vertical: 8.0), 194 | leading: Checkbox( 195 | onChanged: (value) => model.updateTodo(todo 196 | .copy(isCompleted: value == true ? 1 : 0)), 197 | value: todo.isCompleted == 1 ? true : false), 198 | trailing: IconButton( 199 | icon: Icon(Icons.delete_outline), 200 | onPressed: () => model.removeTodo(todo), 201 | ), 202 | title: Text( 203 | todo.name, 204 | style: TextStyle( 205 | fontSize: 18.0, 206 | fontWeight: FontWeight.w600, 207 | color: todo.isCompleted == 1 208 | ? _color 209 | : Colors.black54, 210 | decoration: todo.isCompleted == 1 211 | ? TextDecoration.lineThrough 212 | : TextDecoration.none, 213 | ), 214 | ), 215 | ), 216 | ); 217 | }, 218 | itemCount: _todos.length + 1, 219 | ), 220 | ), 221 | ), 222 | ]), 223 | ), 224 | floatingActionButton: FloatingActionButton( 225 | heroTag: 'fab_new_task', 226 | onPressed: () { 227 | Navigator.push( 228 | context, 229 | MaterialPageRoute( 230 | builder: (context) => 231 | AddTodoScreen(taskId: widget.taskId, heroIds: _hero), 232 | ), 233 | ); 234 | }, 235 | tooltip: 'New Todo', 236 | backgroundColor: _color, 237 | foregroundColor: Colors.white, 238 | child: Icon(Icons.add), 239 | ), 240 | ), 241 | ); 242 | }, 243 | ); 244 | } 245 | 246 | @override 247 | void dispose() { 248 | _controller.dispose(); 249 | super.dispose(); 250 | } 251 | } 252 | 253 | typedef void Callback(); 254 | 255 | class SimpleAlertDialog extends StatelessWidget { 256 | final Color color; 257 | final Callback onActionPressed; 258 | 259 | SimpleAlertDialog({ 260 | required this.color, 261 | required this.onActionPressed, 262 | }); 263 | 264 | @override 265 | Widget build(BuildContext context) { 266 | return IconButton( 267 | color: color, 268 | icon: Icon(Icons.delete), 269 | onPressed: () { 270 | showDialog( 271 | context: context, 272 | barrierDismissible: false, // user must tap button! 273 | builder: (BuildContext context) { 274 | return AlertDialog( 275 | title: Text('Delete this card?'), 276 | content: SingleChildScrollView( 277 | child: ListBody( 278 | children: [ 279 | Text( 280 | 'This is a one way street! Deleting this will remove all the task assigned in this card.'), 281 | ], 282 | ), 283 | ), 284 | actions: [ 285 | TextButton( 286 | child: Text('Delete'), 287 | onPressed: () { 288 | Navigator.of(context).pop(); 289 | Navigator.of(context).pop(); 290 | onActionPressed(); 291 | }, 292 | ), 293 | TextButton( 294 | child: Text('Cancel'), 295 | style: TextButton.styleFrom(foregroundColor: Colors.grey), 296 | onPressed: () { 297 | Navigator.of(context).pop(); 298 | }, 299 | ), 300 | ], 301 | ); 302 | }, 303 | ); 304 | }, 305 | ); 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /lib/page/edit_task_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | import 'package:todo/scopedmodel/todo_list_model.dart'; 5 | import 'package:todo/model/task_model.dart'; 6 | import 'package:todo/component/iconpicker/icon_picker_builder.dart'; 7 | import 'package:todo/component/colorpicker/color_picker_builder.dart'; 8 | 9 | class EditTaskScreen extends StatefulWidget { 10 | final String taskId; 11 | final String taskName; 12 | final Color color; 13 | final IconData icon; 14 | 15 | EditTaskScreen({ 16 | required this.taskId, 17 | required this.taskName, 18 | required this.color, 19 | required this.icon, 20 | }); 21 | 22 | @override 23 | State createState() { 24 | return _EditCardScreenState(); 25 | } 26 | } 27 | 28 | class _EditCardScreenState extends State { 29 | late String taskName; 30 | late Color taskColor; 31 | late IconData taskIcon; 32 | 33 | final btnSaveTitle = "Save Changes"; 34 | 35 | final GlobalKey _scaffoldKey = new GlobalKey(); 36 | 37 | @override 38 | void initState() { 39 | super.initState(); 40 | taskName = widget.taskName; 41 | taskColor = widget.color; 42 | taskIcon = widget.icon; 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return ScopedModelDescendant( 48 | builder: (BuildContext context, Widget? child, TodoListModel model) { 49 | return Scaffold( 50 | key: _scaffoldKey, 51 | backgroundColor: Colors.white, 52 | appBar: AppBar( 53 | title: Text( 54 | 'Edit Category', 55 | style: TextStyle( 56 | color: Colors.black, 57 | ), 58 | ), 59 | centerTitle: true, 60 | elevation: 0, 61 | iconTheme: IconThemeData( 62 | color: Colors.black26, 63 | ), 64 | brightness: Brightness.light, 65 | backgroundColor: Colors.white, 66 | ), 67 | body: Container( 68 | constraints: BoxConstraints.expand(), 69 | padding: EdgeInsets.symmetric( 70 | horizontal: 36.0, 71 | vertical: 36.0, 72 | ), 73 | child: Column( 74 | crossAxisAlignment: CrossAxisAlignment.start, 75 | children: [ 76 | Text( 77 | 'Category will help you group related task!', 78 | style: TextStyle( 79 | color: Colors.black38, 80 | fontWeight: FontWeight.w600, 81 | fontSize: 16.0, 82 | ), 83 | ), 84 | Container( 85 | height: 16.0, 86 | ), 87 | TextFormField( 88 | initialValue: taskName, 89 | onChanged: (text) { 90 | setState( 91 | () => taskName = text, 92 | ); 93 | }, 94 | cursorColor: taskColor, 95 | autofocus: true, 96 | decoration: InputDecoration( 97 | border: InputBorder.none, 98 | hintText: 'Category Name...', 99 | hintStyle: TextStyle( 100 | color: Colors.black26, 101 | )), 102 | style: TextStyle( 103 | color: Colors.black54, 104 | fontWeight: FontWeight.w500, 105 | fontSize: 36.0), 106 | ), 107 | Container( 108 | height: 26.0, 109 | ), 110 | Row( 111 | children: [ 112 | ColorPickerBuilder( 113 | color: taskColor, 114 | onColorChanged: (newColor) => setState( 115 | () => taskColor = newColor, 116 | ), 117 | ), 118 | Container( 119 | width: 22.0, 120 | ), 121 | IconPickerBuilder( 122 | iconData: taskIcon, 123 | highlightColor: taskColor, 124 | action: (newIcon) => setState( 125 | () => taskIcon = newIcon, 126 | ), 127 | ), 128 | ], 129 | ), 130 | ], 131 | ), 132 | ), 133 | floatingActionButtonLocation: 134 | FloatingActionButtonLocation.centerFloat, 135 | floatingActionButton: Builder( 136 | builder: (BuildContext context) { 137 | return FloatingActionButton.extended( 138 | heroTag: 'fab_new_card', 139 | icon: Icon(Icons.save), 140 | backgroundColor: taskColor, 141 | label: Text(btnSaveTitle), 142 | onPressed: () { 143 | if (taskName.isEmpty) { 144 | final snackBar = SnackBar( 145 | content: Text( 146 | 'Ummm... It seems that you are trying to add an invisible task which is not allowed in this realm.'), 147 | backgroundColor: taskColor, 148 | ); 149 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 150 | // _scaffoldKey.currentState.showSnackBar(snackBar); 151 | } else { 152 | model.updateTask( 153 | Task( 154 | taskName, 155 | codePoint: taskIcon.codePoint, 156 | color: taskColor.value, 157 | id: widget.taskId, 158 | ), 159 | ); 160 | Navigator.pop(context); 161 | } 162 | }, 163 | ); 164 | }, 165 | ), 166 | ); 167 | }, 168 | ); 169 | } 170 | } 171 | 172 | // Reason for wraping fab with builder (to get scafold context) 173 | // https://stackoverflow.com/a/52123080/4934757 174 | -------------------------------------------------------------------------------- /lib/page/privacy_policy.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_markdown/flutter_markdown.dart'; 3 | 4 | class PrivacyPolicyScreen extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Scaffold( 8 | backgroundColor: Colors.white, 9 | appBar: AppBar( 10 | title: Text( 11 | 'Privacy Policy', 12 | style: TextStyle(color: Colors.black), 13 | ), 14 | centerTitle: true, 15 | elevation: 0, 16 | iconTheme: IconThemeData(color: Colors.black26), 17 | brightness: Brightness.light, 18 | backgroundColor: Colors.white, 19 | ), 20 | body: Markdown(data: _PRIVACY_POLICY), 21 | ); 22 | } 23 | 24 | static const _PRIVACY_POLICY = """ 25 | 26 | Sabin Bajracharya built the Todo app as a Free app. This SERVICE is provided by Sabin Bajracharya at no cost and is intended for use as is. 27 | 28 | This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service. 29 | 30 | If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy. 31 | 32 | The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at Todo unless otherwise defined in this Privacy Policy. 33 | 34 | **Information Collection and Use** 35 | 36 | For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way. 37 | 38 | The app does use third party services that may collect information used to identify you. 39 | 40 | Link to privacy policy of third party service providers used by the app 41 | 42 | * [Firebase Analytics](https://firebase.google.com/policies/analytics) 43 | 44 | **Log Data** 45 | 46 | I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics. 47 | 48 | **Cookies** 49 | 50 | Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory. 51 | 52 | This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service. 53 | 54 | **Service Providers** 55 | 56 | I may employ third-party companies and individuals due to the following reasons: 57 | 58 | * To facilitate our Service; 59 | * To provide the Service on our behalf; 60 | * To perform Service-related services; or 61 | * To assist us in analyzing how our Service is used. 62 | 63 | I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose. 64 | 65 | **Security** 66 | 67 | I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security. 68 | 69 | **Links to Other Sites** 70 | 71 | This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services. 72 | 73 | **Children’s Privacy** 74 | 75 | These Services do not address anyone under the age of 13\. I do not knowingly collect personally identifiable information from children under 13\. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions. 76 | 77 | **Changes to This Privacy Policy** 78 | 79 | I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page. 80 | 81 | **Contact Us** 82 | 83 | If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at birqueens@gmail.com 84 | """; 85 | 86 | } 87 | -------------------------------------------------------------------------------- /lib/route/scale_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | // class MaterialScaleRoute extends MaterialPageRoute { 4 | // final Widget widget; 5 | 6 | // MaterialScaleRoute({this.widget}) 7 | // : super( 8 | // builder: (BuildContext context) { 9 | // return new ScaleTransition( 10 | // scale: new Tween( 11 | // begin: 0.6, 12 | // end: 1.0, 13 | // ).animate( 14 | // CurvedAnimation( 15 | // parent: animation, 16 | // curve: Interval( 17 | // 0.00, 18 | // 1.00, 19 | // curve: Curves.linear, 20 | // ), 21 | // ), 22 | // ), 23 | // child: widget, 24 | // ); 25 | // }, 26 | // ); 27 | // } 28 | 29 | // class ScaleRoute extends PageRouteBuilder { 30 | // final Widget widget; 31 | // ScaleRoute({this.widget}) 32 | // : super(pageBuilder: ( 33 | // BuildContext context, 34 | // Animation animation, 35 | // Animation secondaryAnimation, 36 | // ) { 37 | // return widget; 38 | // }, transitionsBuilder: ( 39 | // BuildContext context, 40 | // Animation animation, 41 | // Animation secondaryAnimation, 42 | // Widget child, 43 | // ) { 44 | 45 | // return new PositionedTransition( 46 | // // scale: new Tween( 47 | // // begin: 0, 48 | // // end: 1, 49 | // // ).animate( 50 | // // CurvedAnimation( 51 | // // parent: animation, 52 | // // curve: Interval( 53 | // // 0.00, 54 | // // 1.00, 55 | // // curve: Curves.linear, 56 | // // ), 57 | // // ), 58 | // // ), 59 | // child: child, rect: RelativeRectTween( 60 | // begin: RelativeRect.fromLTRB( 61 | // 0, 100, 0.0, 100), 62 | // end: RelativeRect.fromLTRB(0.0, 0.0, 0.0, 0.0), 63 | // ).animate( 64 | // animation 65 | // ), 66 | // ); 67 | // }, transitionDuration: Duration(milliseconds: 300)); 68 | // } 69 | 70 | class ScaleRoute extends PageRouteBuilder { 71 | final Widget widget; 72 | final RelativeRect rect; 73 | ScaleRoute({required this.widget, required this.rect}) 74 | : super( 75 | pageBuilder: (BuildContext context, Animation animation, 76 | Animation secondaryAnimation) { 77 | return widget; 78 | }, 79 | transitionsBuilder: (BuildContext context, 80 | Animation animation, 81 | Animation secondaryAnimation, 82 | Widget child) { 83 | return Stack( 84 | children: [ 85 | Container(), 86 | PositionedTransition( 87 | child: child, 88 | rect: RelativeRectTween( 89 | begin: rect, 90 | end: RelativeRect.fromLTRB(0.0, 0.0, 0.0, 0.0), 91 | ).animate(animation), 92 | ), 93 | ], 94 | ); 95 | }, 96 | transitionDuration: Duration(milliseconds: 300), 97 | ); 98 | } 99 | // Ref: https://medium.com/@agungsurya/create-custom-router-transition-in-flutter-using-pageroutebuilder-73a1a9c4a171 100 | // Ref: Tween: https://flutterbyexample.com/step-one-tweening/ 101 | -------------------------------------------------------------------------------- /lib/scopedmodel/todo_list_model.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:convert'; 2 | // import 'dart:io'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:scoped_model/scoped_model.dart'; 5 | 6 | // import 'package:objectdb/objectdb.dart'; 7 | 8 | import 'package:todo/model/todo_model.dart'; 9 | import 'package:todo/model/task_model.dart'; 10 | import 'package:todo/db/db_provider.dart'; 11 | 12 | class TodoListModel extends Model { 13 | // ObjectDB db; 14 | var _db = DBProvider.db; 15 | List get todos => _todos.toList(); 16 | List get tasks => _tasks.toList(); 17 | int getTaskCompletionPercent(Task task) => 18 | _taskCompletionPercentage[task.id] ?? 0; 19 | int getTotalTodosFrom(Task task) => 20 | todos.where((it) => it.parent == task.id).length; 21 | bool get isLoading => _isLoading; 22 | 23 | bool _isLoading = false; 24 | List _tasks = []; 25 | List _todos = []; 26 | Map _taskCompletionPercentage = Map(); 27 | 28 | static TodoListModel of(BuildContext context) => 29 | ScopedModel.of(context); 30 | 31 | @override 32 | void addListener(listener) { 33 | super.addListener(listener); 34 | // update data for every subscriber, especially for the first one 35 | _isLoading = true; 36 | loadTodos(); 37 | notifyListeners(); 38 | } 39 | 40 | void loadTodos() async { 41 | var isNew = !await DBProvider.db.dbExists(); 42 | if (isNew) { 43 | await _db.insertBulkTask(_db.tasks); 44 | await _db.insertBulkTodo(_db.todos); 45 | } 46 | _tasks = await _db.getAllTask(); 47 | _todos = await _db.getAllTodo(); 48 | _tasks.forEach((it) => _calcTaskCompletionPercent(it.id)); 49 | _isLoading = false; 50 | await Future.delayed(Duration(milliseconds: 300)); 51 | notifyListeners(); 52 | } 53 | 54 | @override 55 | void removeListener(listener) { 56 | super.removeListener(listener); 57 | print("remove listner called"); 58 | // DBProvider.db.closeDB(); 59 | } 60 | 61 | void addTask(Task task) { 62 | _tasks.add(task); 63 | _calcTaskCompletionPercent(task.id); 64 | _db.insertTask(task); 65 | notifyListeners(); 66 | } 67 | 68 | void removeTask(Task task) { 69 | _db.removeTask(task).then((_) { 70 | _tasks.removeWhere((it) => it.id == task.id); 71 | _todos.removeWhere((it) => it.parent == task.id); 72 | notifyListeners(); 73 | }); 74 | } 75 | 76 | void updateTask(Task task) { 77 | var oldTask = _tasks.firstWhere((it) => it.id == task.id); 78 | var replaceIndex = _tasks.indexOf(oldTask); 79 | _tasks.replaceRange(replaceIndex, replaceIndex + 1, [task]); 80 | _db.updateTask(task); 81 | notifyListeners(); 82 | } 83 | 84 | void removeTodo(Todo todo) { 85 | _todos.removeWhere((it) => it.id == todo.id); 86 | _syncJob(todo); 87 | _db.removeTodo(todo); 88 | notifyListeners(); 89 | } 90 | 91 | void addTodo(Todo todo) { 92 | _todos.add(todo); 93 | _syncJob(todo); 94 | _db.insertTodo(todo); 95 | notifyListeners(); 96 | } 97 | 98 | void updateTodo(Todo todo) { 99 | var oldTodo = _todos.firstWhere((it) => it.id == todo.id); 100 | var replaceIndex = _todos.indexOf(oldTodo); 101 | _todos.replaceRange(replaceIndex, replaceIndex + 1, [todo]); 102 | 103 | _syncJob(todo); 104 | _db.updateTodo(todo); 105 | 106 | notifyListeners(); 107 | } 108 | 109 | _syncJob(Todo todo) { 110 | _calcTaskCompletionPercent(todo.parent); 111 | // _syncTodoToDB(); 112 | } 113 | 114 | void _calcTaskCompletionPercent(String taskId) { 115 | var todos = this.todos.where((it) => it.parent == taskId); 116 | var totalTodos = todos.length; 117 | 118 | if (totalTodos == 0) { 119 | _taskCompletionPercentage[taskId] = 0; 120 | } else { 121 | var totalCompletedTodos = todos.where((it) => it.isCompleted == 1).length; 122 | _taskCompletionPercentage[taskId] = 123 | (totalCompletedTodos / totalTodos * 100).toInt(); 124 | } 125 | // return todos.fold(0, (total, todo) => todo.isCompleted ? total + scoreOfTask : total); 126 | } 127 | 128 | // Future _syncTodoToDB() async { 129 | // return await db.update({'user': 'guest'}, {'todos': _todos}); 130 | // } 131 | } 132 | -------------------------------------------------------------------------------- /lib/shadow_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ShadowImage extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Container( 7 | decoration: BoxDecoration( 8 | shape: BoxShape.circle, 9 | color: Colors.white, 10 | boxShadow: [ 11 | BoxShadow( 12 | color: Colors.black.withOpacity(0.6), 13 | blurRadius: 25.0, // has the effect of softening the shadow 14 | spreadRadius: 0.0, // has the effect of extending the shadow 15 | offset: Offset( 16 | 0.0, // horizontal, move right 10 17 | 8.0, // vertical, move down 10 18 | ), 19 | ), 20 | ], 21 | ), 22 | child: ClipOval( 23 | child: Image.network( 24 | 'https://content-static.upwork.com/uploads/2014/10/01073427/profilephoto1.jpg', 25 | height: 52, 26 | width: 52, 27 | fit: BoxFit.cover, 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/task_progress_indicator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TaskProgressIndicator extends StatelessWidget { 4 | final Color color; 5 | final progress; 6 | 7 | final _height = 3.0; 8 | 9 | TaskProgressIndicator({required this.color, required this.progress}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Row( 14 | children: [ 15 | Expanded( 16 | child: LayoutBuilder( 17 | builder: (BuildContext context, BoxConstraints constraints) { 18 | return Stack( 19 | children: [ 20 | Container( 21 | height: _height, 22 | color: Colors.grey.withOpacity(0.1), 23 | ), 24 | AnimatedContainer( 25 | height: _height, 26 | width: (progress / 100) * constraints.maxWidth, 27 | color: color, 28 | duration: Duration(milliseconds: 300), 29 | ), 30 | ], 31 | ); 32 | }, 33 | ), 34 | ), 35 | Container( 36 | margin: EdgeInsets.only(left: 8.0), 37 | child: Text( 38 | "$progress%", 39 | style: Theme.of(context).textTheme.caption, 40 | ), 41 | ) 42 | ], 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/utils/color_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ColorUtils { 4 | static const List defaultColors = [ 5 | Colors.blueGrey, 6 | Colors.red, 7 | Colors.pink, 8 | Colors.purple, 9 | Colors.deepPurple, 10 | Colors.indigo, 11 | Colors.blue, 12 | Colors.lightBlue, 13 | Colors.cyan, 14 | Colors.teal, 15 | Colors.green, 16 | Colors.lightGreen, 17 | Colors.lime, 18 | Colors.yellow, 19 | Colors.amber, 20 | Colors.orange, 21 | Colors.deepOrange, 22 | Colors.brown, 23 | Colors.grey, 24 | ]; 25 | 26 | static Map _color = { 27 | 50: Color.fromRGBO(136, 14, 79, .1), 28 | 100: Color.fromRGBO(136, 14, 79, .2), 29 | 200: Color.fromRGBO(136, 14, 79, .3), 30 | 300: Color.fromRGBO(136, 14, 79, .4), 31 | 400: Color.fromRGBO(136, 14, 79, .5), 32 | 500: Color.fromRGBO(136, 14, 79, .6), 33 | 600: Color.fromRGBO(136, 14, 79, .7), 34 | 700: Color.fromRGBO(136, 14, 79, .8), 35 | 800: Color.fromRGBO(136, 14, 79, .9), 36 | 900: Color.fromRGBO(136, 14, 79, 1), 37 | }; 38 | 39 | static Map _colors = Map(); 40 | 41 | static Map get colors { 42 | if (_colors.isNotEmpty) { 43 | return _colors; 44 | } 45 | 46 | defaultColors.forEach((color) { 47 | _colors[color.value] = color; 48 | }); 49 | return _colors; 50 | } 51 | 52 | static Color getColorFrom({required int id}) { 53 | return colors[id] ?? Colors.blueGrey; 54 | } 55 | 56 | static MaterialColor getMaterialColorFrom({required int id}) { 57 | return MaterialColor((colors[id] ?? Colors.blueGrey).value, _color); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/utils/datetime_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; 2 | 3 | class DateTimeUtils { 4 | 5 | static String get currentDay { 6 | DateTime now = DateTime.now(); 7 | return DateFormat('EEEE').format(now); 8 | } 9 | 10 | static String get currentMonth { 11 | DateTime now = DateTime.now(); 12 | return DateFormat('MMM').format(now); 13 | } 14 | 15 | static String get currentDate { 16 | DateTime now = DateTime.now(); 17 | return DateFormat('d').format(now); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /lib/utils/uuid.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. 2 | // Use of this source code is governed by the MIT license that can be found 3 | // in the LICENSE file. 4 | 5 | import 'dart:math'; 6 | 7 | /// A UUID generator, useful for generating unique IDs for your Todos. 8 | /// Shamelessly extracted from the Flutter source code. 9 | /// 10 | /// This will generate unique IDs in the format: 11 | /// 12 | /// f47ac10b-58cc-4372-a567-0e02b2c3d479 13 | /// 14 | /// ### Example 15 | /// 16 | /// final String id = Uuid().generateV4(); 17 | class Uuid { 18 | final Random _random = Random(); 19 | 20 | /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses 21 | /// random numbers as the source of the generated uuid. 22 | String generateV4() { 23 | // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12. 24 | final int special = 8 + _random.nextInt(4); 25 | 26 | return '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-' 27 | '${_bitsDigits(16, 4)}-' 28 | '4${_bitsDigits(12, 3)}-' 29 | '${_printDigits(special, 1)}${_bitsDigits(12, 3)}-' 30 | '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}'; 31 | } 32 | 33 | String _bitsDigits(int bitCount, int digitCount) => 34 | _printDigits(_generateBits(bitCount), digitCount); 35 | 36 | int _generateBits(int bitCount) => _random.nextInt(1 << bitCount); 37 | 38 | String _printDigits(int value, int count) => 39 | value.toRadixString(16).padLeft(count, '0'); 40 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: todo 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.1.1+20191101 15 | 16 | environment: 17 | sdk: ">=2.12.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | scoped_model: ^2.0.0-nullsafety.0 23 | # objectdb: ^1.0.5 24 | path_provider: ^2.0.9 25 | json_annotation: ^4.0.1 26 | sqflite: ^2.0.0+3 27 | flutter_colorpicker: ^1.0.3 28 | intl: ^0.17.0 29 | # firebase_analytics: ^2.0.2+1 30 | flutter_markdown: ^0.6.2 31 | 32 | # The following adds the Cupertino Icons font to your application. 33 | # Use with the CupertinoIcons class for iOS style icons. 34 | cupertino_icons: ^1.0.3 35 | sqflite_common_ffi: 36 | 37 | dev_dependencies: 38 | flutter_test: 39 | sdk: flutter 40 | build_runner: ^2.0.5 41 | json_serializable: ^4.1.3 42 | 43 | # For information on the generic Dart part of this file, see the 44 | # following page: https://www.dartlang.org/tools/pub/pubspec 45 | 46 | # The following section is specific to Flutter. 47 | flutter: 48 | # The following line ensures that the Material Icons font is 49 | # included with your application, so that you can use the icons in 50 | # the material Icons class. 51 | uses-material-design: true 52 | 53 | # To add assets to your application, add an assets section, like this: 54 | # assets: 55 | # - images/a_dot_burr.jpeg 56 | # - images/a_dot_ham.jpeg 57 | 58 | # An image asset can refer to one or more resolution-specific "variants", see 59 | # https://flutter.dev/assets-and-images/#resolution-aware. 60 | 61 | # For details regarding adding assets from package dependencies, see 62 | # https://flutter.dev/assets-and-images/#from-packages 63 | 64 | # To add custom fonts to your application, add a fonts section here, 65 | # in this "flutter" section. Each entry in this list should have a 66 | # "family" key with the font family name, and a "fonts" key with a 67 | # list giving the asset and other descriptors for the font. For 68 | # example: 69 | # fonts: 70 | # - family: Schyler 71 | # fonts: 72 | # - asset: fonts/Schyler-Regular.ttf 73 | # - asset: fonts/Schyler-Italic.ttf 74 | # style: italic 75 | # - family: Trajan Pro 76 | # fonts: 77 | # - asset: fonts/TrajanPro.ttf 78 | # - asset: fonts/TrajanPro_Bold.ttf 79 | # weight: 700 80 | # 81 | # For details regarding fonts from package dependencies, 82 | # see https://flutter.dev/custom-fonts/#from-packages 83 | -------------------------------------------------------------------------------- /screenshots/screen01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/screenshots/screen01.png -------------------------------------------------------------------------------- /screenshots/screen02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/screenshots/screen02.png -------------------------------------------------------------------------------- /screenshots/screen03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/screenshots/screen03.png -------------------------------------------------------------------------------- /screenshots/screen04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sabinbajracharya/fluttery-todo/e71447c0132be9b1f1e361a9039dbd057bb43f6a/screenshots/screen04.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 | import 'package:flutter_test/flutter_test.dart' as prefix0; 11 | 12 | import 'package:todo/main.dart'; 13 | 14 | void main() { 15 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 16 | // Build our app and trigger a frame. 17 | await tester.pumpWidget(MyApp()); 18 | expect(0,0); 19 | 20 | // // Verify that our counter starts at 0. 21 | // expect(find.text('0'), findsOneWidget); 22 | // expect(find.text('1'), findsNothing); 23 | 24 | // // Tap the '+' icon and trigger a frame. 25 | // await tester.tap(find.byIcon(Icons.add)); 26 | // await tester.pump(); 27 | 28 | // // Verify that our counter has incremented. 29 | // expect(find.text('0'), findsNothing); 30 | // expect(find.text('1'), findsOneWidget); 31 | }); 32 | } 33 | --------------------------------------------------------------------------------