├── .fvm └── fvm_config.json ├── .github └── workflows │ ├── android-deploy.yaml │ ├── ios-deploy.yaml │ └── main.yml ├── .gitignore ├── .metadata ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── Gemfile ├── app │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── ja │ │ │ └── burhanrashid52 │ │ │ └── whattodo │ │ │ └── MainActivityTest.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── ja │ │ │ └── burhanrashid52 │ │ │ └── whattodo │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── drawable │ │ └── launch_background.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ └── styles.xml ├── build.gradle ├── fastlane │ ├── Appfile │ ├── Fastfile │ ├── README.md │ ├── metadata │ │ └── android │ │ │ └── en-US │ │ │ ├── full_description.txt │ │ │ ├── images │ │ │ ├── featureGraphic.png │ │ │ ├── icon.png │ │ │ └── phoneScreenshots │ │ │ │ ├── 1_en-US.png │ │ │ │ ├── 2_en-US.png │ │ │ │ ├── 3_en-US.png │ │ │ │ └── 4_en-US.png │ │ │ ├── short_description.txt │ │ │ ├── title.txt │ │ │ └── video.txt │ └── report.xml ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── Logo │ ├── horizontal.png │ ├── logomark.png │ └── vertical.png ├── facebook_logo.png ├── profile_pic.jpg └── twitter_logo.png ├── integration_test ├── about_us_page_test.dart ├── add_label_page_test.dart ├── add_project_page_test.dart ├── add_task_page_test.dart ├── completed_tasks_page_test.dart ├── home_page_test.dart ├── main.dart ├── test_data.dart └── test_helper.dart ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Gemfile ├── Gemfile.lock ├── 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 │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 167.png │ │ │ ├── 180.png │ │ │ ├── 20.png │ │ │ ├── 29.png │ │ │ ├── 40.png │ │ │ ├── 50.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ └── Contents.json │ │ └── 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 ├── exportOptions.plist └── fastlane │ ├── Appfile │ ├── Fastfile │ ├── Matchfile │ ├── README.md │ └── report.xml ├── lib ├── bloc │ └── bloc_provider.dart ├── db │ └── app_db.dart ├── main.dart ├── models │ └── priority.dart ├── pages │ ├── about │ │ └── about_us.dart │ ├── home │ │ ├── home.dart │ │ ├── home_bloc.dart │ │ └── side_drawer.dart │ ├── labels │ │ ├── add_label.dart │ │ ├── label.dart │ │ ├── label_bloc.dart │ │ ├── label_db.dart │ │ └── label_widget.dart │ ├── projects │ │ ├── add_project.dart │ │ ├── project.dart │ │ ├── project_bloc.dart │ │ ├── project_db.dart │ │ └── project_widget.dart │ └── tasks │ │ ├── add_task.dart │ │ ├── bloc │ │ ├── add_task_bloc.dart │ │ └── task_bloc.dart │ │ ├── models │ │ ├── task_labels.dart │ │ └── tasks.dart │ │ ├── row_task.dart │ │ ├── task_completed │ │ ├── row_task_completed.dart │ │ └── task_complted.dart │ │ ├── task_db.dart │ │ └── task_widgets.dart └── utils │ ├── app_constant.dart │ ├── app_util.dart │ ├── collapsable_expand_tile.dart │ ├── color_utils.dart │ ├── date_util.dart │ ├── extension.dart │ └── keys.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── app_icon_1024.png │ │ ├── app_icon_128.png │ │ ├── app_icon_16.png │ │ ├── app_icon_256.png │ │ ├── app_icon_32.png │ │ ├── app_icon_512.png │ │ └── app_icon_64.png │ ├── Base.lproj │ └── MainMenu.xib │ ├── Configs │ ├── AppInfo.xcconfig │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements ├── pubspec.yaml ├── shorebird.yaml ├── test ├── add_task.png ├── add_task_widget_test.dart ├── add_task_widget_test.mocks.dart ├── home_bloc_test.dart ├── label_bloc_test.dart ├── label_project_row_widget_test.dart ├── project_bloc_test.dart ├── task_list_dissmissble_widget_test.dart ├── task_list_dissmissble_widget_test.mocks.dart ├── task_row_widget_test.dart ├── test_data.dart └── test_helpers.dart └── test_driver └── integration_test.dart /.fvm/fvm_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "flutterSdkVersion": "3.24.0", 3 | "flavors": {} 4 | } -------------------------------------------------------------------------------- /.github/workflows/android-deploy.yaml: -------------------------------------------------------------------------------- 1 | name: 🍏🤖 Deploy to play store 2 | 3 | on: 4 | push: 5 | tags: 6 | - '[0-9]+.[0-9]+.[0-9]+' 7 | 8 | jobs: 9 | deployAndroid: 10 | runs-on: ubuntu-latest 11 | env: 12 | GPS_JSON_KEY: ${{ secrets.GPS_JSON_KEY }} 13 | RELEASE_KEYSTORE_FILE: ${{ secrets.RELEASE_KEYSTORE_FILE }} 14 | KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }} 15 | steps: 16 | - name: ⬇️ Checkout repository 17 | uses: actions/checkout@v3 18 | - name: Configure Java for the runner 19 | uses: actions/setup-java@v1 20 | with: 21 | java-version: "17" 22 | - name: ⚙️ Setup Flutter 23 | uses: subosito/flutter-action@v2 24 | with: 25 | flutter-version: "3.24.0" 26 | channel: 'stable' 27 | cache: true 28 | id: flutter 29 | - name: Update version number from tag 30 | run: | 31 | # Extract the version components from refs tag (e.g., 1.2.3) 32 | TAG_NAME=${{ github.ref_name }} 33 | VERSION=${TAG_NAME#v} # Remove the 'v' prefix if it exists 34 | echo "FLUTTER_BUILD_NAME=$VERSION" >> $GITHUB_ENV 35 | MAJOR=$(echo $VERSION | cut -d. -f1) 36 | MINOR=$(echo $VERSION | cut -d. -f2) 37 | PATCH=$(echo $VERSION | cut -d. -f3) 38 | NUMBER=$MAJOR$MINOR$PATCH 39 | echo "FLUTTER_BUILD_NUMBER=$NUMBER" >> $GITHUB_ENV 40 | - name: 📦 Get Packages 41 | run: flutter pub get 42 | - name: Setup Fastlane 43 | uses: ruby/setup-ruby@v1 44 | with: 45 | ruby-version: "3.3" 46 | bundler-cache: true 47 | - name: Setup play store service 48 | run: echo "$GPS_JSON_KEY" >> ./android/play-store.json 49 | - name: Setup store key properties 50 | run: echo "$KEYSTORE_PROPERTIES" >> ./android/key.properties 51 | - name: Get the release keystore 52 | run: | 53 | echo $RELEASE_KEYSTORE_FILE | base64 --decode > android/app/whattodo_keystore.jks 54 | - name: Build and Deploy to Play store 55 | run: | 56 | cd ./android 57 | fastlane android beta -------------------------------------------------------------------------------- /.github/workflows/ios-deploy.yaml: -------------------------------------------------------------------------------- 1 | name: 🍏🚀 Deploy to appstore 2 | 3 | on: 4 | push: 5 | tags: 6 | - '[0-9]+.[0-9]+.[0-9]+' 7 | 8 | jobs: 9 | deployIos: 10 | runs-on: macos-latest 11 | env: 12 | ASC_JSON_KEY: ${{ secrets.ASC_JSON_KEY }} 13 | FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }} 14 | FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }} 15 | steps: 16 | - name: ⬇️ Checkout repository 17 | uses: actions/checkout@v3 18 | - name: ⚙️ Setup Flutter 19 | uses: subosito/flutter-action@v2 20 | with: 21 | flutter-version: "3.24.0" 22 | channel: 'stable' 23 | cache: true 24 | id: flutter 25 | - name: Update version number from tag 26 | run: | 27 | # Extract the version components from refs tag (e.g., 1.2.3) 28 | TAG_NAME=${{ github.ref_name }} 29 | VERSION=${TAG_NAME#v} # Remove the 'v' prefix if it exists 30 | echo "FLUTTER_BUILD_NAME=$VERSION" >> $GITHUB_ENV 31 | MAJOR=$(echo $VERSION | cut -d. -f1) 32 | MINOR=$(echo $VERSION | cut -d. -f2) 33 | PATCH=$(echo $VERSION | cut -d. -f3) 34 | NUMBER=$MAJOR$MINOR$PATCH 35 | echo "FLUTTER_BUILD_NUMBER=$NUMBER" >> $GITHUB_ENV 36 | - name: 📦 Get Packages 37 | run: flutter pub get 38 | - name: Setup Fastlane 39 | uses: ruby/setup-ruby@v1 40 | with: 41 | ruby-version: "3.3" 42 | bundler-cache: true 43 | working-directory: ios 44 | - name: Setup app store connect 45 | run: echo "$ASC_JSON_KEY" >> ./ios/fastlane/store.json 46 | - name: Install pod 47 | run: cd ios && pod install 48 | - name: Build and Deploy to TestFlight 49 | env: 50 | MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} 51 | MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} 52 | run: | 53 | cd ./ios 54 | bundle exec fastlane ios beta 55 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: WhatTodo Flutter Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test: 13 | name: Run Flutter Tests 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: subosito/flutter-action@v2 19 | with: 20 | flutter-version: '3.24.0' 21 | channel: 'stable' 22 | - run: flutter --version 23 | 24 | - name: Get Packages 25 | run: flutter pub get 26 | 27 | - name: Run Tests 28 | run: flutter test 29 | -------------------------------------------------------------------------------- /.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 | coverage 19 | 20 | # Visual Studio Code related 21 | .vscode/ 22 | 23 | # Flutter repo-specific 24 | /bin/cache/ 25 | /bin/mingit/ 26 | /dev/benchmarks/mega_gallery/ 27 | /dev/bots/.recipe_deps 28 | /dev/bots/android_tools/ 29 | /dev/docs/doc/ 30 | /dev/docs/lib/ 31 | /dev/docs/pubspec.yaml 32 | /packages/flutter/coverage/ 33 | version 34 | 35 | # Flutter/Dart/Pub related 36 | **/doc/api/ 37 | .dart_tool/ 38 | .flutter-plugins 39 | .packages 40 | .pub-cache/ 41 | .pub/ 42 | build/ 43 | flutter_*.png 44 | linked_*.ds 45 | unlinked.ds 46 | unlinked_spec.ds 47 | 48 | # Android related 49 | **/android/**/gradle-wrapper.jar 50 | **/android/.gradle 51 | **/android/captures/ 52 | **/android/gradlew 53 | **/android/gradlew.bat 54 | **/android/local.properties 55 | **/android/**/GeneratedPluginRegistrant.java 56 | 57 | # iOS/XCode related 58 | **/ios/**/*.mode1v3 59 | **/ios/**/*.mode2v3 60 | **/ios/**/*.moved-aside 61 | **/ios/**/*.pbxuser 62 | **/ios/**/*.perspectivev3 63 | **/ios/**/*sync/ 64 | **/ios/**/.sconsign.dblite 65 | **/ios/**/.tags* 66 | **/ios/**/.vagrant/ 67 | **/ios/**/DerivedData/ 68 | **/ios/**/Icon? 69 | **/ios/**/Pods/ 70 | **/ios/**/.symlinks/ 71 | **/ios/**/profile 72 | **/ios/**/xcuserdata 73 | **/ios/.generated/ 74 | **/ios/Flutter/App.framework 75 | **/ios/Flutter/Flutter.framework 76 | **/ios/Flutter/Generated.xcconfig 77 | **/ios/Flutter/app.flx 78 | **/ios/Flutter/app.zip 79 | **/ios/Flutter/flutter_assets/ 80 | **/ios/Flutter/flutter_export_environment.sh 81 | **/ios/ServiceDefinitions.json 82 | **/ios/Runner/GeneratedPluginRegistrant.* 83 | .flutter-plugins-dependencies 84 | 85 | # Exceptions to above rules. 86 | !**/ios/**/default.mode1v3 87 | !**/ios/**/default.mode2v3 88 | !**/ios/**/default.pbxuser 89 | !**/ios/**/default.perspectivev3 90 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 91 | .fvm/flutter_sdk 92 | /ios/Flutter/Flutter.podspec 93 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 3ea4d06340a97a1e9d7cae97567c64e0569dcaa2 8 | channel: beta 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at burhanrashid5253@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to contribute? 2 | 3 | 1. Fork the project. 4 | 2. Make required changes and commit. 5 | 3. Generate pull request. Mention all the required description regarding changes you made. 6 | 7 | Happy coding.:-) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WhatTodo 2 | 3 | [![GitHub Actions](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fburhanrashid52%2Fwhattodo%2Fbadge&label=build&logo=none)](https://actions-badge.atrox.dev/burhanrashid52/whattodo/goto) ![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg) ![API](https://img.shields.io/badge/API-16%2B-brightgreen.svg) [![Uplabs](https://img.shields.io/badge/Uplabs-WhatTodo-orange.svg)](https://www.uplabs.com/posts/whattodo) [![FlutterWeekly](https://img.shields.io/badge/Flutter%20Weekly-%2319-pink.svg)](https://mailchi.mp/193f2a7fe907/flutter-weekly-257173) [![AwesomeAndroid](https://img.shields.io/badge/Awesome%20Android-%23101-yellow.svg)](https://android.libhunt.com/newsletter/101) 4 | Buy Me A Coffee 5 | 6 | ![logo](/assets/Logo/horizontal.png) 7 | 8 | Life can feel overwhelming. But it doesn’t have to. 9 | 10 | A Simple To-do app design in flutter to keep track of your task on daily basis. You can add project, labels and due-date to your tasks 11 | 12 | [](https://play.google.com/store/apps/details?id=ja.burhanrashid52.whattodo) 13 | 14 | ## Features 15 | 16 | - Build on [**BLoC**](#bloc-diagram) Architecture Pattern 17 | - Add [**Projects**](#project) by specifying a unique color to it 18 | - Add [**Labels**](#labels) by specifying a unique color to it 19 | - Add [**Task**](#task) by defining its priority 20 | - [**Swipe**](#swipe-the-task) to delete or complete the task 21 | - [**Sorting**](#sorting) Task 22 | - Works offline using [**Sqflite**](https://github.com/tekartik/sqflite "Flutter Database") database 23 | 24 | ## BLoC Diagram 25 | This diagram show case the dependencies to create a feature specific BLoCs.The HomeBloc is independent and used as communication channel between its child widgets. 26 | 27 | ![](https://i.imgur.com/byajGE7.png) 28 | 29 | ## Widget-BLoC Relationship 30 | This diagram shows that how each widget uses BLoCs. 31 | 32 | ![](https://i.imgur.com/fHGTASw.png) 33 | 34 | ## Project 35 | The app already has a preloaded **_Inbox_** project. You can add more projects by clicking add project button on SideDrawer. From material color list you can specify any single color to the project 36 | 37 | ![](https://i.imgur.com/f01IjGz.gif) 38 | 39 | > You can assign only one project to a single task 40 | 41 | ## Labels 42 | You can add multiple labels by clicking add Labels button on SideDrawer. From material color list you can specify any single color to the label 43 | 44 | ![](https://i.imgur.com/tZQgEwW.gif) 45 | 46 | > You can assign multiple labels to a single task 47 | 48 | ## Task 49 | You can add task with multiple attributes. You must assign a project to task if not than by default it will be added in _Inbox_ project. 50 | Task can have zero or more to label assing to it 51 | 52 | ![](https://i.imgur.com/mNs0D3B.gif) 53 | 54 | ## Swipe the Task 55 | You can delete a task by swiping left-to-right or your can mark task as completed by swiping right-to-left. You can also undo a completed task by clicking on options menu where it shows the list of all completed tasks there you can swipe right-to-left to undo the completed task 56 | 57 | ![](https://i.imgur.com/yU0gP1t.gif) 58 | 59 | ## Sorting 60 | You can sort your task with date i.e today and next 7 days and also acoording to project and labels 61 | 62 | ![](https://i.imgur.com/wzou22S.gif) 63 | 64 | 65 | ## How to contribute? 66 | * Check out contribution guidelines 👉[CONTRIBUTING.md](https://github.com/burhanrashid52/WhatTodo/blob/master/CONTRIBUTING.md) 67 | 68 | 69 | ## What's next? 70 | 71 | - Editable Project,label and Task 72 | - Deletable Project and Label 73 | - Comment/Description in Task 74 | - Reminder with notification 75 | 76 | 77 | ## Questions?🤔 78 | Hit me on twitter [![Twitter](https://img.shields.io/badge/Twitter-%40burhanrashid52-blue.svg)](https://twitter.com/burhanrashid52) 79 | [![Medium](https://img.shields.io/badge/Medium-%40burhanrashid52-brightgreen.svg)](https://medium.com/@burhanrashid52) 80 | [![Facebook](https://img.shields.io/badge/Facebook-Burhanuddin%20Rashid-blue.svg)](https://www.facebook.com/Bursid) 81 | 82 | 83 | ## Credits 84 | - UI/UX inspired from [**Todoist**](https://play.google.com/store/apps/details?id=com.todoist&hl=en) app 85 | - Flutter [**Documentation**](https://flutter.io/docs/) 86 | - [**Collin Jackson**](https://stackoverflow.com/users/1463116/collin-jackson) answer's on stackoverflow :laughing: 87 | 88 | ## License 89 | Copyright 2020 Burhanuddin Rashid 90 | 91 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 92 | 93 | http://www.apache.org/licenses/LICENSE-2.0 94 | 95 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 96 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | key.properties 12 | app/whattodo_keystore.jks 13 | play-store.json 14 | *.jks 15 | -------------------------------------------------------------------------------- /android/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | def keystoreProperties = new Properties() 26 | def keystorePropertiesFile = rootProject.file('key.properties') 27 | if (keystorePropertiesFile.exists()) { 28 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 29 | } 30 | 31 | android { 32 | compileSdkVersion 34 33 | 34 | lintOptions { 35 | disable 'InvalidPackage' 36 | } 37 | 38 | defaultConfig { 39 | applicationId "ja.burhanrashid52.whattodo" 40 | minSdkVersion 24 //flutter.minSdkVersion 41 | targetSdkVersion 34 42 | versionCode flutterVersionCode.toInteger() 43 | versionName flutterVersionName 44 | } 45 | 46 | compileOptions { 47 | sourceCompatibility JavaVersion.VERSION_1_8 48 | targetCompatibility JavaVersion.VERSION_1_8 49 | } 50 | 51 | kotlinOptions { 52 | jvmTarget = '1.8' 53 | } 54 | 55 | sourceSets { 56 | main.java.srcDirs += 'src/main/kotlin' 57 | } 58 | 59 | signingConfigs { 60 | file(rootProject.file('key.properties')).with { propFile -> 61 | if (propFile.canRead()) { 62 | release { 63 | keyAlias keystoreProperties['keyAlias'] 64 | keyPassword keystoreProperties['keyPassword'] 65 | storeFile file(keystoreProperties['storeFile']) 66 | storePassword keystoreProperties['storePassword'] 67 | } 68 | } else { 69 | print('not signed') 70 | } 71 | } 72 | } 73 | 74 | buildTypes { 75 | release { 76 | file(rootProject.file('key.properties')).with { propFile -> 77 | if (propFile.canRead()) { 78 | signingConfig signingConfigs.release 79 | } 80 | } 81 | 82 | applicationVariants.all { variant -> 83 | variant.outputs.all { output -> 84 | output.outputFileName = "app-release.apk" 85 | } 86 | } 87 | } 88 | } 89 | 90 | buildFeatures { 91 | viewBinding true 92 | } 93 | } 94 | 95 | flutter { 96 | source '../..' 97 | } 98 | 99 | dependencies { 100 | implementation 'com.android.support:support-annotations:28.0.0' 101 | } 102 | -------------------------------------------------------------------------------- /android/app/src/androidTest/java/ja/burhanrashid52/whattodo/MainActivityTest.java: -------------------------------------------------------------------------------- 1 | package ja.burhanrashid52.whattodo; 2 | 3 | import androidx.test.rule.ActivityTestRule; 4 | import ja.burhanrashid52.whattodo.MainActivity; 5 | import dev.flutter.plugins.integration_test.FlutterTestRunner; 6 | import org.junit.Rule; 7 | import org.junit.runner.RunWith; 8 | 9 | @RunWith(FlutterTestRunner.class) 10 | public class MainActivityTest { 11 | @Rule 12 | public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class, true, false); 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 30 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 51 | -------------------------------------------------------------------------------- /android/app/src/main/java/ja/burhanrashid52/whattodo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package ja.burhanrashid52.whattodo 2 | 3 | import io.flutter.embedding.android.FlutterFragmentActivity 4 | 5 | class MainActivity: FlutterFragmentActivity() { 6 | } -------------------------------------------------------------------------------- /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/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } -------------------------------------------------------------------------------- /android/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | json_key_file("play-store.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one 2 | package_name("ja.burhanrashid52.whattodo") # e.g. com.krausefx.app 3 | -------------------------------------------------------------------------------- /android/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # This file contains the fastlane.tools configuration 2 | # You can find the documentation at https://docs.fastlane.tools 3 | # 4 | # For a list of all available actions, check out 5 | # 6 | # https://docs.fastlane.tools/actions 7 | # 8 | # For a list of all available plugins, check out 9 | # 10 | # https://docs.fastlane.tools/plugins/available-plugins 11 | # 12 | 13 | # Uncomment the line if you want fastlane to automatically update itself 14 | # update_fastlane 15 | 16 | default_platform(:android) 17 | 18 | platform :android do 19 | desc "Deploy a new version to the Google Play" 20 | lane :beta do 21 | updated_version_name = ENV["FLUTTER_BUILD_NAME"] 22 | updated_version_number = ENV["FLUTTER_BUILD_NUMBER"] 23 | sh "flutter build apk --release --build-name=#{updated_version_name} --build-number=#{updated_version_number}" 24 | upload_to_play_store( 25 | track: "internal", 26 | apk: "../build/app/outputs/flutter-apk/app-release.apk", 27 | ) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /android/fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ## Android 17 | 18 | ### android beta 19 | 20 | ```sh 21 | [bundle exec] fastlane android beta 22 | ``` 23 | 24 | Deploy a new version to the Google Play 25 | 26 | ---- 27 | 28 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 29 | 30 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 31 | 32 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 33 | -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | A Simple To-do app design in flutter to keep track of your task on daily basis. You can add project, labels and due-date to your tasks. 2 | 3 | - Build on BLoC Architecture Pattern 4 | - Add Projects by specifying a unique color to it 5 | - Add Labels by specifying a unique color to it 6 | - Add Task by defining its priority 7 | - Swipe to delete or complete the task 8 | - Sorting Task 9 | - Works offline using Sqflite database -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/featureGraphic.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | A Simple To-do app design in flutter to keep track of your task on daily basis. -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/title.txt: -------------------------------------------------------------------------------- 1 | WhatTodo -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/video.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/android/fastlane/metadata/android/en-US/video.txt -------------------------------------------------------------------------------- /android/fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xms1024m -Xmx4096m 2 | android.useAndroidX=true 3 | android.enableJetifier=true -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "7.4.2" apply false 22 | id "org.jetbrains.kotlin.android" version "1.9.0" apply false 23 | } 24 | 25 | include ":app" -------------------------------------------------------------------------------- /assets/Logo/horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/Logo/horizontal.png -------------------------------------------------------------------------------- /assets/Logo/logomark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/Logo/logomark.png -------------------------------------------------------------------------------- /assets/Logo/vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/Logo/vertical.png -------------------------------------------------------------------------------- /assets/facebook_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/facebook_logo.png -------------------------------------------------------------------------------- /assets/profile_pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/profile_pic.jpg -------------------------------------------------------------------------------- /assets/twitter_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burhanrashid52/WhatTodo/db6ba701a4b71cf15ee6c53646c05cbff247863f/assets/twitter_logo.png -------------------------------------------------------------------------------- /integration_test/about_us_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_app/pages/about/about_us.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | 7 | void main() { 8 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 9 | 10 | group("About Screen", () { 11 | testWidgets('Profile Details', (WidgetTester tester) async { 12 | await tester.pumpWidget( 13 | MaterialApp( 14 | home: AboutUsScreen(), 15 | ), 16 | ); 17 | expect(find.text("About"), findsOneWidget); 18 | expect(find.text("Report an Issue"), findsOneWidget); 19 | expect(find.text("Having an issue ? Report it here"), findsOneWidget); 20 | expect(find.text("Burhanuddin Rashid"), findsOneWidget); 21 | expect(find.text("burhanrashid52"), findsOneWidget); 22 | expect(find.text("burhanrashid5253@gmail.com"), findsOneWidget); 23 | expect(find.text("1.0.0"), findsOneWidget); 24 | }); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /integration_test/add_label_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_app/main.dart' as app; 3 | import 'package:flutter_app/utils/keys.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | 7 | import 'test_helper.dart'; 8 | 9 | void main() { 10 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 11 | 12 | group("Add Labels", () { 13 | setUp(() async { 14 | await cleanDb(); 15 | }); 16 | 17 | testWidgets('Enter Label Details and verify on Side drawer screen', 18 | (WidgetTester tester) async { 19 | app.main(); 20 | await tester.pumpAndSettle(); 21 | 22 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 23 | 24 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_LABELS); 25 | 26 | await tester.tapAndSettle(SideDrawerKeys.ADD_LABEL); 27 | 28 | var addLabelNameField = 29 | find.byValueKey(AddLabelKeys.TEXT_FORM_LABEL_NAME); 30 | 31 | await tester.enterText(addLabelNameField, "Android"); 32 | await tester.pumpAndSettle(); 33 | 34 | await tester.tapAndSettle(AddLabelKeys.ADD_LABEL_BUTTON); 35 | 36 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 37 | 38 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_LABELS); 39 | 40 | expect(find.text("@ Android"), findsOneWidget); 41 | //TODO Match the Label color as well 42 | },skip: true);//Flaky on CI 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /integration_test/add_project_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_app/main.dart' as app; 3 | import 'package:flutter_app/utils/keys.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | 7 | import 'test_helper.dart'; 8 | 9 | void main() { 10 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 11 | 12 | group("Add Projects", () { 13 | 14 | setUp(() async { 15 | await cleanDb(); 16 | }); 17 | 18 | testWidgets('Enter Project Details and verify on Side drawer screen', 19 | (WidgetTester tester) async { 20 | app.main(); 21 | await tester.pumpAndSettle(); 22 | 23 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 24 | 25 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_PROJECTS); 26 | 27 | await tester.tapAndSettle(SideDrawerKeys.ADD_PROJECT); 28 | 29 | final addProjectName = 30 | find.byValueKey(AddProjectKeys.TEXT_FORM_PROJECT_NAME); 31 | await tester.enterText(addProjectName, "Personal"); 32 | 33 | await tester.tapAndSettle(AddProjectKeys.ADD_PROJECT_BUTTON); 34 | 35 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 36 | 37 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_PROJECTS); 38 | 39 | expect(find.text("Personal"), findsOneWidget); 40 | //TODO Match the project color as well 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /integration_test/add_task_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_app/main.dart' as app; 3 | import 'package:flutter_app/utils/keys.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | import 'test_helper.dart'; 7 | 8 | void main() { 9 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 10 | 11 | 12 | group("Add Tasks", () { 13 | 14 | setUp(() async { 15 | await cleanDb(); 16 | }); 17 | 18 | testWidgets('Enter Task Details and verify on Task page screen', 19 | (WidgetTester tester) async { 20 | app.main(); 21 | await tester.pumpAndSettle(); 22 | 23 | await tester.tapAndSettle(HomePageKeys.ADD_NEW_TASK_BUTTON); 24 | 25 | expect(find.text("Add Task"), findsOneWidget); 26 | 27 | await tester.enterText( 28 | find.byValueKey(AddTaskKeys.ADD_TITLE), "First Task"); 29 | await tester.pumpAndSettle(); 30 | //TODO: 1. Add Project in selection 2. Add Label from dialog 3. Change due date 31 | 32 | await tester.tapAndSettle(AddTaskKeys.ADD_TASK); 33 | 34 | expect(find.text("First Task"), findsOneWidget); 35 | expect(find.text("Inbox"), findsOneWidget); 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /integration_test/completed_tasks_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_app/main.dart' as app; 3 | import 'package:flutter_app/utils/keys.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | 7 | import 'test_helper.dart'; 8 | 9 | void main() { 10 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 11 | 12 | group('Completed Tasks Page', () { 13 | testWidgets('Show Today Tasks', (WidgetTester tester) async { 14 | app.main(); 15 | await tester.pumpAndSettle(); 16 | await seedDataInDb(); 17 | 18 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 19 | 20 | await tester.tapAndSettle(SideDrawerKeys.TODAY); 21 | 22 | //swipe left to mark as complete 23 | var firstTaskListItem = find.byValueKey('swipe_1_0'); 24 | await tester.drag(firstTaskListItem, const Offset(-300.0, 0.0)); 25 | await tester.pumpAndSettle(); 26 | 27 | await tester.tapAndSettle(CompletedTaskPageKeys.POPUP_ACTION); 28 | 29 | await tester.tapAndSettle(CompletedTaskPageKeys.COMPLETED_TASKS); 30 | 31 | expect(find.text("Task One"), findsOneWidget); 32 | 33 | //swipe left to mark to undo 34 | var firstCompletedTaskListItem = find.byValueKey('task_completed_1'); 35 | await tester.drag(firstCompletedTaskListItem, const Offset(-300.0, 0.0)); 36 | await tester.pumpAndSettle(); 37 | 38 | await tester.pageBack(); 39 | await tester.pumpAndSettle(); 40 | 41 | expect(find.text("Task One"), findsOneWidget); 42 | }); 43 | 44 | tearDown(() async { 45 | await cleanDb(); 46 | }); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /integration_test/home_page_test.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_app/main.dart' as app; 3 | import 'package:flutter_app/utils/keys.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:integration_test/integration_test.dart'; 6 | 7 | import 'test_helper.dart'; 8 | 9 | void main() { 10 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 11 | 12 | group('Home Page', () { 13 | testWidgets('Today in Title', (WidgetTester tester) async { 14 | app.main(); 15 | await tester.pumpAndSettle(); 16 | expect(find.text("Today"), findsOneWidget); 17 | expect(find.text("No Task Added"), findsOneWidget); 18 | }); 19 | 20 | testWidgets('Show Today Tasks', (WidgetTester tester) async { 21 | await seedAndStartApp(tester); 22 | 23 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 24 | 25 | await tester.tapAndSettle(SideDrawerKeys.TODAY); 26 | 27 | expect(find.text("Today"), findsOneWidget); 28 | 29 | expect(find.text("Task One"), findsOneWidget); 30 | expect(find.text("Inbox"), findsOneWidget); 31 | 32 | expect(find.text("Task Two"), findsOneWidget); 33 | expect(find.text("Personal"), findsOneWidget); 34 | }); 35 | 36 | testWidgets('Show Inbox Tasks', (WidgetTester tester) async { 37 | await seedAndStartApp(tester); 38 | 39 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 40 | 41 | await tester.tapAndSettle(SideDrawerKeys.INBOX); 42 | 43 | expect(find.text("Task One"), findsOneWidget); 44 | expect(find.text("Inbox"), findsNWidgets(2)); 45 | }); 46 | 47 | testWidgets('Show Next 7 days Tasks', (WidgetTester tester) async { 48 | await seedAndStartApp(tester); 49 | 50 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 51 | 52 | await tester.tapAndSettle(SideDrawerKeys.NEXT_7_DAYS); 53 | 54 | expect(find.text("Next 7 Days"), findsOneWidget); 55 | 56 | expect(find.text("Task One"), findsOneWidget); 57 | expect(find.text("Inbox"), findsOneWidget); 58 | 59 | expect(find.text("Task Two"), findsOneWidget); 60 | expect(find.text("Personal"), findsOneWidget); 61 | 62 | expect(find.text("Task Three"), findsOneWidget); 63 | expect(find.text("Work"), findsOneWidget); 64 | }); 65 | 66 | testWidgets('Show Personal project Tasks', (WidgetTester tester) async { 67 | await seedAndStartApp(tester); 68 | 69 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 70 | 71 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_PROJECTS); 72 | 73 | await tester.tapAndSettle('Personal_2'); 74 | 75 | expect(find.text("Task Two"), findsOneWidget); 76 | expect(find.text("Personal"), findsNWidgets(2)); 77 | }); 78 | 79 | testWidgets('Show No Travel project Tasks Found', 80 | (WidgetTester tester) async { 81 | await seedAndStartApp(tester); 82 | 83 | await tester.tapAndSettle(SideDrawerKeys.DRAWER); 84 | 85 | await tester.tapAndSettle(SideDrawerKeys.DRAWER_PROJECTS); 86 | 87 | await tester.tapAndSettle('Travel_4'); 88 | 89 | expect(find.text("No Task Added"), findsOneWidget); 90 | }); 91 | 92 | //TODO: Add test for tasks Label Filter 93 | }); 94 | 95 | tearDown(() async { 96 | await cleanDb(); 97 | }); 98 | } 99 | 100 | Future seedAndStartApp(WidgetTester tester) async { 101 | app.main(); 102 | await seedDataInDb(); 103 | await tester.pumpAndSettle(); 104 | } 105 | -------------------------------------------------------------------------------- /integration_test/main.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'about_us_page_test.dart' as about; 3 | import 'add_label_page_test.dart' as label; 4 | import 'add_project_page_test.dart' as project; 5 | import 'add_task_page_test.dart' as tasks; 6 | import 'completed_tasks_page_test.dart' as tasks_completed; 7 | import 'home_page_test.dart' as home; 8 | 9 | void main() { 10 | //Run test 11 | home.main(); 12 | tasks.main(); 13 | tasks_completed.main(); 14 | project.main(); 15 | label.main(); 16 | about.main(); 17 | } 18 | -------------------------------------------------------------------------------- /integration_test/test_data.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_app/models/priority.dart'; 4 | import 'package:flutter_app/pages/labels/label.dart'; 5 | import 'package:flutter_app/pages/projects/project.dart'; 6 | import 'package:flutter_app/pages/tasks/models/tasks.dart'; 7 | 8 | //Project Test data 9 | var testProject1 = Project.getInbox(); 10 | var testProject2 = Project.update( 11 | id: 2, 12 | name: "Personal", 13 | colorCode: Colors.red.value, 14 | colorName: "Red", 15 | ); 16 | var testProject3 = Project.update( 17 | id: 3, 18 | name: "Work", 19 | colorCode: Colors.black.value, 20 | colorName: "Black", 21 | ); 22 | var testProject4 = Project.update( 23 | id: 4, 24 | name: "Travel", 25 | colorCode: Colors.orange.value, 26 | colorName: "Orange", 27 | ); 28 | 29 | //Label Test data 30 | var testLabel1 = Label.update( 31 | id: 1, 32 | name: "Android", 33 | colorCode: Colors.green.value, 34 | colorName: "Green", 35 | ); 36 | 37 | var testLabel2 = Label.update( 38 | id: 2, 39 | name: "Flutter", 40 | colorCode: Colors.lightBlue.value, 41 | colorName: "Blue Light", 42 | ); 43 | 44 | var testLabel3 = Label.update( 45 | id: 3, 46 | name: "React", 47 | colorCode: Colors.purple.value, 48 | colorName: "Purple", 49 | ); 50 | 51 | 52 | //Task Test data 53 | var testTask1 = Tasks.update( 54 | id: 1, 55 | title: "Task One", 56 | projectId: 1, 57 | priority: Status.PRIORITY_3, 58 | dueDate: DateTime.now().millisecondsSinceEpoch, 59 | ); 60 | 61 | var testTask2 = Tasks.update( 62 | id: 2, 63 | title: "Task Two", 64 | projectId: 2, 65 | priority: Status.PRIORITY_2, 66 | dueDate: DateTime.now().millisecondsSinceEpoch, 67 | ); 68 | 69 | var testTask3 = Tasks.update( 70 | id: 3, 71 | title: "Task Three", 72 | projectId: 3, 73 | priority: Status.PRIORITY_1, 74 | dueDate: DateTime.now().add(new Duration(days: 7)).millisecondsSinceEpoch, 75 | ); 76 | -------------------------------------------------------------------------------- /integration_test/test_helper.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_app/pages/labels/label.dart'; 4 | import 'package:flutter_app/pages/labels/label_db.dart'; 5 | import 'package:flutter_app/pages/projects/project.dart'; 6 | import 'package:flutter_app/pages/projects/project_db.dart'; 7 | import 'package:flutter_app/pages/tasks/models/tasks.dart'; 8 | import 'package:flutter_app/pages/tasks/task_db.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'test_data.dart'; 12 | 13 | extension TestFinder on CommonFinders { 14 | Finder byValueKey(String key) { 15 | return find.byKey(ValueKey(key)); 16 | } 17 | } 18 | 19 | extension TestWidgetTester on WidgetTester { 20 | Future tapAndSettle(String key) async { 21 | await this.tap(find.byKey(ValueKey(key))); 22 | await pumpAndSettle(); 23 | } 24 | } 25 | 26 | seedDataInDb() async { 27 | var projectDB = ProjectDB.get(); 28 | await projectDB.insertOrReplace(testProject1); 29 | await projectDB.insertOrReplace(testProject2); 30 | await projectDB.insertOrReplace(testProject3); 31 | await projectDB.insertOrReplace(testProject4); 32 | 33 | var labelDB = LabelDB.get(); 34 | await labelDB.updateLabels(testLabel1); 35 | await labelDB.updateLabels(testLabel2); 36 | await labelDB.updateLabels(testLabel3); 37 | 38 | var taskDB = TaskDB.get(); 39 | await taskDB.updateTask(testTask1); 40 | await taskDB.updateTask(testTask2); 41 | await taskDB.updateTask(testTask3); 42 | } 43 | 44 | cleanDb() async { 45 | var projectDB = ProjectDB.get(); 46 | List projects = await projectDB.getProjects(isInboxVisible: false); 47 | projects.forEach((project) { 48 | projectDB.deleteProject(project.id!); 49 | }); 50 | 51 | var labelDB = LabelDB.get(); 52 | List