├── linux
├── .gitignore
├── main.cc
├── flutter
│ ├── generated_plugin_registrant.h
│ ├── generated_plugins.cmake
│ ├── generated_plugin_registrant.cc
│ └── CMakeLists.txt
├── my_application.h
├── my_application.cc
└── CMakeLists.txt
├── metadata
└── en-US
│ ├── changelogs
│ ├── 1.txt
│ └── 2.txt
│ ├── short_description.txt
│ ├── images
│ ├── icon.png
│ └── phoneScreenshots
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ └── 4.png
│ └── full_description.txt
├── fonts
└── Manrope
│ └── Manrope-Regular.ttf
├── .gitmodules
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── ic_launcher-playstore.png
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ ├── ic_launcher_foreground.png
│ │ │ │ │ └── ic_launcher_monochrome.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ ├── ic_launcher_foreground.png
│ │ │ │ │ └── ic_launcher_monochrome.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ ├── ic_launcher_foreground.png
│ │ │ │ │ └── ic_launcher_monochrome.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ ├── ic_launcher_foreground.png
│ │ │ │ │ └── ic_launcher_monochrome.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ ├── ic_launcher_foreground.png
│ │ │ │ │ └── ic_launcher_monochrome.png
│ │ │ │ ├── values
│ │ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── drawable
│ │ │ │ │ ├── launch_background.xml
│ │ │ │ │ ├── ic_launcher_monochrome.xml
│ │ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── bored
│ │ │ │ │ └── codebyk
│ │ │ │ │ └── mint_task
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── build.gradle
└── settings.gradle
├── lib
├── pages
│ ├── views.dart
│ ├── settings.dart
│ ├── components
│ │ ├── listview.dart
│ │ └── listitemcard.dart
│ ├── sublist.dart
│ ├── base.dart
│ ├── edit.dart
│ └── home.dart
├── controller
│ ├── pref.dart
│ ├── tasklist.dart
│ ├── todosettings.dart
│ ├── settings_model.dart
│ ├── route.dart
│ └── db.dart
├── model
│ ├── customlist.dart
│ └── task.dart
└── main.dart
├── CHANGELOG.md
├── assets
├── github-mark-white.svg
└── github-mark.svg
├── .gitignore
├── .metadata
├── test
└── widget_test.dart
├── pubspec.yaml
├── README.md
├── analysis_options.yaml
├── .github
└── workflows
│ └── main.yml
├── LICENSE
└── pubspec.lock
/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/1.txt:
--------------------------------------------------------------------------------
1 | First release
--------------------------------------------------------------------------------
/metadata/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Simple todo manager.
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/2.txt:
--------------------------------------------------------------------------------
1 | Added option to edit each todo, delete from edit page and sort and filter method.
--------------------------------------------------------------------------------
/metadata/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/metadata/en-US/images/icon.png
--------------------------------------------------------------------------------
/fonts/Manrope/Manrope-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/fonts/Manrope/Manrope-Regular.ttf
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "flutter"]
2 | path = flutter
3 | url = https://github.com/flutter/flutter.git
4 | branch = stable
5 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/lib/pages/views.dart:
--------------------------------------------------------------------------------
1 | export 'home.dart';
2 | export 'base.dart';
3 | export 'settings.dart';
4 | export 'edit.dart';
5 | export 'sublist.dart';
6 |
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/metadata/en-US/images/phoneScreenshots/1.png
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/metadata/en-US/images/phoneScreenshots/2.png
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/metadata/en-US/images/phoneScreenshots/3.png
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/metadata/en-US/images/phoneScreenshots/4.png
--------------------------------------------------------------------------------
/android/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boredcodebyk/minttask/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E3E5C1
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 2.0.0
2 | - Updated UI
3 | - List by Category (WIP)
4 | - Using AppFlowy as rich text editor with Markdown support
5 |
6 | (and i lost motivation again...be back after a while)
7 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/bored/codebyk/mint_task/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package bored.codebyk.mint_task
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
--------------------------------------------------------------------------------
/linux/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/metadata/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | A simple todo manager for Android made using Flutter with Material Design 3.
2 |
3 | Features
4 | - Add todo
5 | - Edit and manage todo
6 | - Separate description page
7 | - Custom theme and dynamic theme
--------------------------------------------------------------------------------
/lib/controller/pref.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_riverpod/flutter_riverpod.dart';
2 | import 'package:shared_preferences/shared_preferences.dart';
3 |
4 | final sharedPreferencesProvider =
5 | Provider((ref) => throw UnimplementedError());
6 |
--------------------------------------------------------------------------------
/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.6.3-all.zip
6 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/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 | }
19 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/pages/settings.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SettingsView extends StatelessWidget {
4 | const SettingsView({super.key});
5 |
6 | @override
7 | Widget build(BuildContext context) {
8 | return Scaffold(
9 | body: CustomScrollView(
10 | slivers: [
11 | SliverAppBar.large(
12 | title: Text("Settings"),
13 | )
14 | ],
15 | ),
16 | );
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/linux/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/controller/tasklist.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_riverpod/flutter_riverpod.dart';
2 |
3 | import '../model/customlist.dart';
4 | import '../model/task.dart';
5 | import 'pref.dart';
6 |
7 | final taskListProvider = StateProvider>((ref) {
8 | List taskList = [];
9 | return taskList;
10 | });
11 |
12 | final customListProvider = StateProvider>((ref) {
13 | List customList = [];
14 | return customList;
15 | });
16 |
17 | final hideCompleted = StateProvider((ref) {
18 | final prefs = ref.watch(sharedPreferencesProvider);
19 | final hide = prefs.getBool("hideCompleted") ?? false;
20 | ref.listenSelf((previous, next) {
21 | prefs.setBool("hideCompleted", next);
22 | });
23 | return hide;
24 | });
25 |
--------------------------------------------------------------------------------
/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.3.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | dynamic_color
7 | printing
8 | url_launcher_linux
9 | )
10 |
11 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
12 | )
13 |
14 | set(PLUGIN_BUNDLED_LIBRARIES)
15 |
16 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
17 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
18 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
19 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
20 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
21 | endforeach(plugin)
22 |
23 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
24 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
25 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
26 | endforeach(ffi_plugin)
27 |
--------------------------------------------------------------------------------
/assets/github-mark-white.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/github-mark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 | android/*.jks
46 | android/key.properties
47 | keybase64.txt
--------------------------------------------------------------------------------
/lib/controller/todosettings.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_riverpod/flutter_riverpod.dart';
2 |
3 | import 'pref.dart';
4 | import '../model/task.dart';
5 |
6 | final filterProvider = StateProvider((ref) {
7 | final prefs = ref.watch(sharedPreferencesProvider);
8 | final filterSelected = Filter.values.firstWhere(
9 | (element) => element.toString() == prefs.getString("filter"),
10 | orElse: () => Filter.id,
11 | );
12 | ref.listenSelf(
13 | (previous, next) => prefs.setString("filter", next.name),
14 | );
15 | return filterSelected;
16 | });
17 |
18 | final sortProvider = StateProvider((ref) {
19 | final prefs = ref.watch(sharedPreferencesProvider);
20 | final sortSelected = Sort.values.firstWhere(
21 | (element) => element.toString() == prefs.getString("sort"),
22 | orElse: () => Sort.desc,
23 | );
24 | ref.listenSelf(
25 | (previous, next) => prefs.setString("sort", next.name),
26 | );
27 | return sortSelected;
28 | });
29 |
--------------------------------------------------------------------------------
/lib/model/customlist.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | class CustomList {
4 | int? id;
5 | String? name;
6 | bool? trash;
7 |
8 | CustomList({
9 | this.id,
10 | this.name,
11 | this.trash,
12 | });
13 |
14 | CustomList copyWith({
15 | int? id,
16 | String? name,
17 | bool? trash,
18 | }) =>
19 | CustomList(
20 | id: id ?? this.id,
21 | name: name ?? this.name,
22 | trash: trash ?? this.trash,
23 | );
24 |
25 | factory CustomList.fromRawJson(String str) =>
26 | CustomList.fromJson(json.decode(str));
27 |
28 | String toRawJson() => json.encode(toJson());
29 |
30 | factory CustomList.fromJson(Map json) => CustomList(
31 | id: json["id"],
32 | name: json["name"],
33 | trash: json["trash"] == 0 ? false : true,
34 | );
35 |
36 | Map toJson() => {
37 | "id": id,
38 | "name": name,
39 | "trash": trash! ? 1 : 0,
40 | };
41 | }
42 |
--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | void fl_register_plugins(FlPluginRegistry* registry) {
14 | g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
15 | fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
16 | dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
17 | g_autoptr(FlPluginRegistrar) printing_registrar =
18 | fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
19 | printing_plugin_register_with_registrar(printing_registrar);
20 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
21 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
22 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
23 | }
24 |
--------------------------------------------------------------------------------
/.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: "5dcb86f68f239346676ceb1ed1ea385bd215fba1"
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: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
17 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
18 | - platform: linux
19 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
20 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_launcher_monochrome.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/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 in the flutter_test package. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:minttask/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(const MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: minttask
2 | description: A simple todo manager for Android made using Flutter with Material Design 3.
3 |
4 | publish_to: "none"
5 |
6 | version: 2.0.0+200
7 |
8 | environment:
9 | sdk: ">=3.0.0 <4.0.0"
10 |
11 | dependencies:
12 | animations: ^2.0.7
13 | appflowy_editor: ^3.1.0
14 | cupertino_icons: ^1.0.2
15 | dynamic_color: ^1.7.0
16 | flutter:
17 | sdk: flutter
18 | flutter_colorpicker: ^1.0.3
19 | flutter_riverpod: ^2.5.1
20 | flutter_svg: ^2.0.6
21 | go_router: ^14.2.3
22 | intl: ^0.19.0
23 | material_color_utilities: ^0.11.1
24 | package_info_plus: ^8.0.2
25 | path: ^1.8.3
26 | shared_preferences: ^2.1.1
27 | sqflite: ^2.2.8+4
28 | sqflite_common_ffi: ^2.3.3
29 | url_launcher: ^6.1.11
30 | uuid: ^4.4.2
31 |
32 | dev_dependencies:
33 | custom_lint: ^0.6.4
34 | flutter_lints: ^4.0.0
35 | flutter_test:
36 | sdk: flutter
37 | riverpod_lint: ^2.3.10
38 |
39 | flutter:
40 | uses-material-design: true
41 | assets:
42 | - assets/github-mark-white.svg
43 | - assets/github-mark.svg
44 | fonts:
45 | - family: Manrope
46 | fonts:
47 | - asset: fonts/Manrope/Manrope-Regular.ttf
48 | # - asset: fonts/Schyler-Italic.ttf
49 | # style: italic
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mint Task
2 |
3 | 
4 |
5 | ## Update
6 | Recently, I thought to ditch the idea of a todo.txt file-based to-do list and work with SQLite again to work with Android Widgets and background tasks. But, sadly, I came across major setbacks. One of them is, old task made in v1.0.0 do not show up in the new version of the app when I was testing, even though the database structure remains the same, and so I'm starting to lose motivation again and stuff IRL and focus on my career. I'm happy with how the app turned out, but I can't keep up with the setbacks. I'll archive the repository for now. Thank you.
7 |
8 | ---
9 |
10 | A simple todo manager for Android made using Flutter with Material Design 3.
11 |
12 | ## Features
13 | - Add todo
14 | - Edit and manage todo
15 | - Separate description page
16 | - Custom theme and dynamic theme
17 |
18 | ## Work in progress
19 | - Reminder/Alarm functionality
20 | The work is in progress for this app. If any issues arises or if you have any suggestions to put forward, please open an issue ticket with label either "bug" or "feature request" respectively.
21 |
--------------------------------------------------------------------------------
/lib/pages/components/listview.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:minttask/model/task.dart';
3 |
4 | import 'listitemcard.dart';
5 |
6 | class ListViewCard extends StatelessWidget {
7 | const ListViewCard({super.key, required this.list});
8 |
9 | final List list;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Card(
14 | elevation: 0,
15 | clipBehavior: Clip.antiAlias,
16 | color: Colors.transparent,
17 | shape: RoundedRectangleBorder(
18 | borderRadius: BorderRadius.circular(18),
19 | ),
20 | child: ListView.separated(
21 | shrinkWrap: true,
22 | padding: EdgeInsets.zero,
23 | physics: const NeverScrollableScrollPhysics(),
24 | itemCount: list.length,
25 | separatorBuilder: (context, index) => Divider(
26 | color: Theme.of(context).brightness == Brightness.dark
27 | ? Theme.of(context).colorScheme.surfaceContainer
28 | : Theme.of(context).colorScheme.surfaceContainerHighest,
29 | height: 2,
30 | ),
31 | itemBuilder: (context, index) {
32 | var task = list[index];
33 | return ListItemCard(
34 | task: task,
35 | );
36 | },
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
18 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 | analyzer:
31 | plugins:
32 | - custom_lint
--------------------------------------------------------------------------------
/lib/pages/components/listitemcard.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_riverpod/flutter_riverpod.dart';
3 | import 'package:go_router/go_router.dart';
4 |
5 | import '../../controller/db.dart';
6 | import '../../controller/tasklist.dart';
7 | import '../../controller/todosettings.dart';
8 | import '../../model/task.dart';
9 |
10 | class ListItemCard extends ConsumerStatefulWidget {
11 | const ListItemCard({super.key, required this.task});
12 | final Task task;
13 |
14 | @override
15 | ConsumerState createState() => _ListItemCardState();
16 | }
17 |
18 | class _ListItemCardState extends ConsumerState {
19 | Future updateTodos(sortbycol, filter) async {
20 | final dbHelper = DatabaseHelper.instance;
21 | final todolist = await dbHelper.getTodos(sortbycol, filter);
22 |
23 | ref.read(taskListProvider.notifier).state = todolist
24 | .map(
25 | (e) => Task.fromJson(e),
26 | )
27 | .toList();
28 | }
29 |
30 | Future _toggleTodoStatus(int id, int isDone) async {
31 | final dbHelper = DatabaseHelper.instance;
32 | await dbHelper.updateTodoStauts(
33 | id, isDone, DateTime.now().millisecondsSinceEpoch);
34 | updateTodos(ref.watch(filterProvider).name, ref.watch(sortProvider).name);
35 | }
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return ListTile(
40 | tileColor: Theme.of(context).brightness == Brightness.dark
41 | ? Theme.of(context).colorScheme.surfaceContainerHigh
42 | : Theme.of(context).colorScheme.surfaceContainerLowest,
43 | leading: Checkbox(
44 | value: widget.task.isDone,
45 | onChanged: (value) {
46 | _toggleTodoStatus(widget.task.id!, value! ? 1 : 0);
47 | }),
48 | title: Text(
49 | widget.task.title ?? "",
50 | style: TextStyle(
51 | decoration: widget.task.isDone!
52 | ? TextDecoration.lineThrough
53 | : TextDecoration.none),
54 | ),
55 | onTap: () => context.push("/task/${widget.task.id}"),
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/controller/settings_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_riverpod/flutter_riverpod.dart';
3 |
4 | import 'pref.dart';
5 |
6 | final themeModeProvider = StateProvider((ref) {
7 | final prefs = ref.watch(sharedPreferencesProvider);
8 | final selectedThemeMode = ThemeMode.values.firstWhere(
9 | (element) => element.toString() == prefs.getString('themeMode'),
10 | orElse: () => ThemeMode.system);
11 | ref.listenSelf((previous, next) {
12 | prefs.setString('themeMode', next.toString());
13 | });
14 | return selectedThemeMode;
15 | });
16 |
17 | final useDynamicColor = StateProvider((ref) {
18 | final prefs = ref.watch(sharedPreferencesProvider);
19 | final usingDynamicColor = prefs.getBool("useDynamicColor") ?? false;
20 | ref.listenSelf((previous, next) {
21 | prefs.setBool("useDynamicColor", next);
22 | });
23 | return usingDynamicColor;
24 | });
25 |
26 | final useCustomColor = StateProvider((ref) {
27 | final prefs = ref.watch(sharedPreferencesProvider);
28 | final usingCustomColor = prefs.getBool("useCustomColor") ?? false;
29 | ref.listenSelf((previous, next) {
30 | prefs.setBool("useCustomColor", next);
31 | });
32 | return usingCustomColor;
33 | });
34 |
35 | final selectedCustomColor = StateProvider((ref) {
36 | final prefs = ref.watch(sharedPreferencesProvider);
37 | final customColor = prefs.getInt('customColor') ?? 16777215;
38 | ref.listenSelf((previous, next) {
39 | prefs.setInt('customColor', next);
40 | });
41 | return customColor;
42 | });
43 |
44 | final runSetup = StateProvider((ref) {
45 | final prefs = ref.watch(sharedPreferencesProvider);
46 | final runSetup = prefs.getBool("runSetup") ?? false;
47 | ref.listenSelf((previous, next) {
48 | prefs.setBool("runSetup", next);
49 | });
50 | return runSetup;
51 | });
52 |
53 | final minimalView = StateProvider((ref) {
54 | final prefs = ref.watch(sharedPreferencesProvider);
55 | final mini = prefs.getBool("minimalView") ?? false;
56 | ref.listenSelf(
57 | (previous, next) {
58 | prefs.setBool("minimalView", next);
59 | },
60 | );
61 | return mini;
62 | });
63 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Release Build
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 | workflow_dispatch:
8 |
9 | env:
10 | APK_BUILD_DIR: "/tmp/build"
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout the code
16 | uses: actions/checkout@v3
17 |
18 | - name: Setup Java to compile Android project
19 | uses: actions/setup-java@v3
20 | with:
21 | distribution: 'temurin'
22 | java-version: '17'
23 |
24 | - name: Get version from pubspec.yaml
25 | id: get_version
26 | run: |
27 | VERSION=$(sed -n 's/^version: \([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' pubspec.yaml)
28 | echo "version=$VERSION" >> $GITHUB_OUTPUT
29 |
30 | - name: Copy files to env.APK_BUILD_DIR
31 | run: |
32 | mkdir -p $APK_BUILD_DIR
33 | cp -r . $APK_BUILD_DIR
34 |
35 | - name: Setup Flutter
36 | uses: subosito/flutter-action@v2
37 | with:
38 | channel: 'stable'
39 |
40 | - name: Flutter version
41 | run: |
42 | flutter config --no-analytics
43 | flutter --version
44 |
45 | - name: Decode key.properties file
46 | working-directory: ${{ env.APK_BUILD_DIR }}
47 | env:
48 | ENCODED_STRING: ${{ secrets.ANDROID_KEY_PROPERTIES }}
49 | run: echo $ENCODED_STRING | base64 -di > android/key.properties
50 |
51 | - name: Decode android-keystore.jks file
52 | working-directory: ${{ env.APK_BUILD_DIR }}
53 | env:
54 | ENCODED_STRING: ${{ secrets.KEY_JKS }}
55 | run: echo $ENCODED_STRING | base64 -di > android/key.jks
56 |
57 | - name: Dependencies
58 | working-directory: ${{ env.APK_BUILD_DIR }}
59 | run: flutter pub get
60 |
61 | - name: Build APK
62 | working-directory: ${{ env.APK_BUILD_DIR }}
63 | run: flutter build apk --release
64 |
65 | - name: Upload artifacts
66 | uses: actions/upload-artifact@v3
67 | with:
68 | name: release-apk
69 | path: ${{ env.APK_BUILD_DIR }}/build/app/outputs/flutter-apk/app-release.apk
70 |
71 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id "dev.flutter.flutter-gradle-plugin"
6 | }
7 |
8 | def localProperties = new Properties()
9 | def localPropertiesFile = rootProject.file("local.properties")
10 | if (localPropertiesFile.exists()) {
11 | localPropertiesFile.withReader("UTF-8") { reader ->
12 | localProperties.load(reader)
13 | }
14 | }
15 |
16 | def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
17 | if (flutterVersionCode == null) {
18 | flutterVersionCode = "1"
19 | }
20 |
21 | def flutterVersionName = localProperties.getProperty("flutter.versionName")
22 | if (flutterVersionName == null) {
23 | flutterVersionName = "1.0"
24 | }
25 |
26 | def keystoreProperties = new Properties()
27 | def keystorePropertiesFile = rootProject.file('key.properties')
28 | if (keystorePropertiesFile.exists()) {
29 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
30 | }
31 |
32 |
33 | android {
34 | namespace = "bored.codebyk.mint_task"
35 | compileSdk = flutter.compileSdkVersion
36 | ndkVersion = flutter.ndkVersion
37 |
38 | compileOptions {
39 | sourceCompatibility = JavaVersion.VERSION_1_8
40 | targetCompatibility = JavaVersion.VERSION_1_8
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId = "bored.codebyk.mint_task"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdk = 23
49 | targetSdk = 34
50 | versionCode = flutterVersionCode.toInteger()
51 | versionName = flutterVersionName
52 | }
53 |
54 | signingConfigs {
55 | release {
56 | keyAlias keystoreProperties['keyAlias']
57 | keyPassword keystoreProperties['keyPassword']
58 | storeFile = file("../key.jks") ? file("../key.jks") : null
59 | storePassword keystoreProperties['storePassword']
60 | v1SigningEnabled true
61 | v2SigningEnabled true
62 | }
63 | }
64 |
65 | buildTypes {
66 | release {
67 | // TODO: Add your own signing config for the release build.
68 | // Signing with the debug keys for now, so `flutter run --release` works.
69 | signingConfig = signingConfigs.release
70 | }
71 | }
72 | }
73 |
74 | flutter {
75 | source = "../.."
76 | }
77 |
--------------------------------------------------------------------------------
/lib/model/task.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | enum Filter {
4 | id(filterName: "Default"),
5 | title(filterName: "Title"),
6 | // ignore: constant_identifier_filterNames, constant_identifier_names
7 | date_modified(filterName: "Date Modified"),
8 | // ignore: constant_identifier_filterNames, constant_identifier_names
9 | date_created(filterName: "Date Created");
10 |
11 | const Filter({required this.filterName});
12 |
13 | final String filterName;
14 | }
15 |
16 | enum Sort {
17 | asc(sortName: "Ascending"),
18 | desc(sortName: "Descending");
19 |
20 | const Sort({required this.sortName});
21 |
22 | final String sortName;
23 | }
24 |
25 | class Task {
26 | int? id;
27 | String? title;
28 | DateTime? dateCreated;
29 | DateTime? dateModified;
30 | String? description;
31 | bool? isDone;
32 | List? customList;
33 | bool? trash;
34 |
35 | Task({
36 | this.id,
37 | this.title,
38 | this.dateCreated,
39 | this.dateModified,
40 | this.description,
41 | this.isDone,
42 | this.customList,
43 | this.trash,
44 | });
45 |
46 | Task copyWith({
47 | int? id,
48 | String? title,
49 | DateTime? dateCreated,
50 | DateTime? dateModified,
51 | String? description,
52 | bool? isDone,
53 | List? customList,
54 | bool? trash,
55 | }) =>
56 | Task(
57 | id: id ?? this.id,
58 | title: title ?? this.title,
59 | dateCreated: dateCreated ?? this.dateCreated,
60 | dateModified: dateModified ?? this.dateModified,
61 | description: description ?? this.description,
62 | isDone: isDone ?? this.isDone,
63 | customList: customList ?? this.customList,
64 | trash: trash ?? this.trash,
65 | );
66 |
67 | factory Task.fromRawJson(String str) => Task.fromJson(json.decode(str));
68 |
69 | String toRawJson() => json.encode(toJson());
70 |
71 | factory Task.fromJson(Map json) => Task(
72 | id: json["id"],
73 | title: json["title"],
74 | dateCreated: DateTime.fromMillisecondsSinceEpoch(json["date_created"]),
75 | dateModified:
76 | DateTime.fromMillisecondsSinceEpoch(json["date_modified"]),
77 | description: json["description"],
78 | isDone: json["is_done"] == 0 ? false : true,
79 | customList: json["custom_list"].length > 0
80 | ? jsonDecode(json["custom_list"])
81 | : [],
82 | trash: json["trash"] == 0 ? false : true,
83 | );
84 |
85 | Map toJson() => {
86 | "id": id,
87 | "title": title,
88 | "date_created": dateCreated!.millisecondsSinceEpoch,
89 | "date_modified": dateModified!.millisecondsSinceEpoch,
90 | "description": description,
91 | "is_done": isDone! ? 1 : 0,
92 | "custom_list": jsonEncode(customList),
93 | "trash": trash! ? 1 : 0
94 | };
95 | }
96 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:appflowy_editor/appflowy_editor.dart';
2 | import 'package:dynamic_color/dynamic_color.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:flutter_riverpod/flutter_riverpod.dart';
6 | import 'package:minttask/controller/route.dart';
7 | import 'package:shared_preferences/shared_preferences.dart';
8 |
9 | import 'controller/pref.dart';
10 | import 'controller/settings_model.dart';
11 |
12 | Future main() async {
13 | WidgetsFlutterBinding.ensureInitialized();
14 |
15 | final prefs = await SharedPreferences.getInstance();
16 | runApp(
17 | ProviderScope(
18 | overrides: [
19 | sharedPreferencesProvider.overrideWithValue(prefs),
20 | ],
21 | child: const MyApp(),
22 | ),
23 | );
24 | }
25 |
26 | class MyApp extends ConsumerWidget {
27 | const MyApp({super.key});
28 |
29 | @override
30 | Widget build(BuildContext context, WidgetRef ref) {
31 | SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
32 | SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
33 | statusBarColor: Colors.transparent,
34 | systemNavigationBarDividerColor: Colors.transparent,
35 | systemNavigationBarContrastEnforced: true,
36 | systemNavigationBarColor: Colors.transparent,
37 | ));
38 |
39 | final defaultLightColorScheme = ColorScheme.fromSeed(
40 | seedColor: const Color.fromARGB(255, 217, 229, 129));
41 |
42 | final defaultDarkColorScheme = ColorScheme.fromSeed(
43 | seedColor: const Color.fromARGB(255, 217, 229, 129),
44 | brightness: Brightness.dark);
45 | final customLightColorScheme =
46 | ColorScheme.fromSeed(seedColor: Color(ref.watch(selectedCustomColor)));
47 |
48 | final customDarkColorScheme = ColorScheme.fromSeed(
49 | seedColor: Color(ref.watch(selectedCustomColor)),
50 | brightness: Brightness.dark);
51 |
52 | return DynamicColorBuilder(
53 | builder: (lightColorScheme, darkColorScheme) {
54 | return MaterialApp.router(
55 | title: 'Mint Task',
56 | routerConfig: ref.watch(routerProvider),
57 | localizationsDelegates: const [AppFlowyEditorLocalizations.delegate],
58 | theme: ThemeData(
59 | colorScheme: ref.watch(useDynamicColor)
60 | ? lightColorScheme
61 | : ref.watch(useCustomColor)
62 | ? customLightColorScheme
63 | : defaultLightColorScheme,
64 | fontFamily: 'Manrope',
65 | useMaterial3: true,
66 | ),
67 | darkTheme: ThemeData(
68 | colorScheme: ref.watch(useDynamicColor)
69 | ? darkColorScheme
70 | : ref.watch(useCustomColor)
71 | ? customDarkColorScheme
72 | : defaultDarkColorScheme,
73 | fontFamily: 'Manrope',
74 | useMaterial3: true,
75 | ),
76 | themeMode: ref.watch(themeModeProvider),
77 | );
78 | },
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/linux/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.10)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 |
12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13 | # which isn't available in 3.10.
14 | function(list_prepend LIST_NAME PREFIX)
15 | set(NEW_LIST "")
16 | foreach(element ${${LIST_NAME}})
17 | list(APPEND NEW_LIST "${PREFIX}${element}")
18 | endforeach(element)
19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20 | endfunction()
21 |
22 | # === Flutter Library ===
23 | # System-level dependencies.
24 | find_package(PkgConfig REQUIRED)
25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28 |
29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30 |
31 | # Published to parent scope for install step.
32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36 |
37 | list(APPEND FLUTTER_LIBRARY_HEADERS
38 | "fl_basic_message_channel.h"
39 | "fl_binary_codec.h"
40 | "fl_binary_messenger.h"
41 | "fl_dart_project.h"
42 | "fl_engine.h"
43 | "fl_json_message_codec.h"
44 | "fl_json_method_codec.h"
45 | "fl_message_codec.h"
46 | "fl_method_call.h"
47 | "fl_method_channel.h"
48 | "fl_method_codec.h"
49 | "fl_method_response.h"
50 | "fl_plugin_registrar.h"
51 | "fl_plugin_registry.h"
52 | "fl_standard_message_codec.h"
53 | "fl_standard_method_codec.h"
54 | "fl_string_codec.h"
55 | "fl_value.h"
56 | "fl_view.h"
57 | "flutter_linux.h"
58 | )
59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60 | add_library(flutter INTERFACE)
61 | target_include_directories(flutter INTERFACE
62 | "${EPHEMERAL_DIR}"
63 | )
64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65 | target_link_libraries(flutter INTERFACE
66 | PkgConfig::GTK
67 | PkgConfig::GLIB
68 | PkgConfig::GIO
69 | )
70 | add_dependencies(flutter flutter_assemble)
71 |
72 | # === Flutter tool backend ===
73 | # _phony_ is a non-existent file to force this command to run every time,
74 | # since currently there's no way to get a full input/output list from the
75 | # flutter tool.
76 | add_custom_command(
77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79 | COMMAND ${CMAKE_COMMAND} -E env
80 | ${FLUTTER_TOOL_ENVIRONMENT}
81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83 | VERBATIM
84 | )
85 | add_custom_target(flutter_assemble DEPENDS
86 | "${FLUTTER_LIBRARY}"
87 | ${FLUTTER_LIBRARY_HEADERS}
88 | )
89 |
--------------------------------------------------------------------------------
/lib/controller/route.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations/animations.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:flutter_riverpod/flutter_riverpod.dart';
4 | import 'package:go_router/go_router.dart';
5 |
6 | import '../pages/views.dart';
7 |
8 | final rootRouteProvider = Provider>((ref) {
9 | final GlobalKey rootNavigatorKey =
10 | GlobalKey(debugLabel: 'root');
11 | return rootNavigatorKey;
12 | });
13 |
14 | final shellRouteProvider = Provider>((ref) {
15 | final GlobalKey shellNavigatorKey =
16 | GlobalKey(debugLabel: 'shell');
17 | return shellNavigatorKey;
18 | });
19 |
20 | final routerProvider = Provider((ref) {
21 | final router = GoRouter(
22 | navigatorKey: ref.watch(rootRouteProvider),
23 | initialLocation: "/",
24 | debugLogDiagnostics: true,
25 |
26 | routes: [
27 | ShellRoute(
28 | navigatorKey: ref.watch(shellRouteProvider),
29 | builder: (context, state, child) => BaseView(child: child),
30 | routes: [
31 | GoRoute(
32 | path: '/',
33 | pageBuilder: (context, state) {
34 | return CustomTransitionPage(
35 | key: state.pageKey,
36 | child: HomeView(),
37 | transitionsBuilder:
38 | (context, animation, secondaryAnimation, child) {
39 | // Change the opacity of the screen using a Curve based on the the animation's
40 | // value
41 | return FadeTransition(
42 | opacity: CurveTween(curve: Curves.easeInOutCirc)
43 | .animate(animation),
44 | child: child,
45 | );
46 | },
47 | );
48 | },
49 | ),
50 | GoRoute(
51 | path: '/list/:id',
52 | pageBuilder: (context, state) {
53 | return CustomTransitionPage(
54 | key: state.pageKey,
55 | child: SubListView(
56 | taskID: int.tryParse(state.pathParameters['id']!)!),
57 | transitionsBuilder:
58 | (context, animation, secondaryAnimation, child) {
59 | // Change the opacity of the screen using a Curve based on the the animation's
60 | // value
61 | return FadeTransition(
62 | opacity: CurveTween(curve: Curves.easeInOutCirc)
63 | .animate(animation),
64 | child: child,
65 | );
66 | },
67 | );
68 | },
69 | ),
70 | ],
71 | ),
72 | GoRoute(
73 | path: '/new',
74 | builder: (context, state) => const EditView(
75 | editState: EditState.newTask,
76 | ),
77 | ),
78 | GoRoute(
79 | path: '/task/:id',
80 | pageBuilder: (context, state) => CustomTransitionPage(
81 | key: state.pageKey,
82 | child: EditView(
83 | editState: EditState.editTask,
84 | taskID: int.tryParse(state.pathParameters['id']!)),
85 | transitionsBuilder: (context, animation, secondaryAnimation, child) =>
86 | SharedAxisTransition(
87 | animation: animation,
88 | secondaryAnimation: secondaryAnimation,
89 | transitionType: SharedAxisTransitionType.horizontal,
90 | child: child,
91 | ),
92 | ),
93 | ),
94 | GoRoute(
95 | path: '/settings',
96 | pageBuilder: (context, state) => CustomTransitionPage(
97 | key: state.pageKey,
98 | child: const SettingsView(),
99 | transitionsBuilder: (context, animation, secondaryAnimation, child) =>
100 | SharedAxisTransition(
101 | animation: animation,
102 | secondaryAnimation: secondaryAnimation,
103 | transitionType: SharedAxisTransitionType.horizontal,
104 | child: child,
105 | ),
106 | ),
107 | ),
108 | ],
109 | // redirect: (context, state) {
110 | // if (!ref.watch(runSetup)) {
111 | // "continue";
112 | // } else {
113 | // return '/';
114 | // }
115 | // },
116 | );
117 | return router;
118 | });
119 |
--------------------------------------------------------------------------------
/linux/my_application.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | #include
4 | #ifdef GDK_WINDOWING_X11
5 | #include
6 | #endif
7 |
8 | #include "flutter/generated_plugin_registrant.h"
9 |
10 | struct _MyApplication {
11 | GtkApplication parent_instance;
12 | char** dart_entrypoint_arguments;
13 | };
14 |
15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16 |
17 | // Implements GApplication::activate.
18 | static void my_application_activate(GApplication* application) {
19 | MyApplication* self = MY_APPLICATION(application);
20 | GtkWindow* window =
21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
22 |
23 | // Use a header bar when running in GNOME as this is the common style used
24 | // by applications and is the setup most users will be using (e.g. Ubuntu
25 | // desktop).
26 | // If running on X and not using GNOME then just use a traditional title bar
27 | // in case the window manager does more exotic layout, e.g. tiling.
28 | // If running on Wayland assume the header bar will work (may need changing
29 | // if future cases occur).
30 | gboolean use_header_bar = TRUE;
31 | #ifdef GDK_WINDOWING_X11
32 | GdkScreen* screen = gtk_window_get_screen(window);
33 | if (GDK_IS_X11_SCREEN(screen)) {
34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
36 | use_header_bar = FALSE;
37 | }
38 | }
39 | #endif
40 | if (use_header_bar) {
41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
42 | gtk_widget_show(GTK_WIDGET(header_bar));
43 | gtk_header_bar_set_title(header_bar, "minttask");
44 | gtk_header_bar_set_show_close_button(header_bar, TRUE);
45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
46 | } else {
47 | gtk_window_set_title(window, "minttask");
48 | }
49 |
50 | gtk_window_set_default_size(window, 1280, 720);
51 | gtk_widget_show(GTK_WIDGET(window));
52 |
53 | g_autoptr(FlDartProject) project = fl_dart_project_new();
54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
55 |
56 | FlView* view = fl_view_new(project);
57 | gtk_widget_show(GTK_WIDGET(view));
58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
59 |
60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view));
61 |
62 | gtk_widget_grab_focus(GTK_WIDGET(view));
63 | }
64 |
65 | // Implements GApplication::local_command_line.
66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
67 | MyApplication* self = MY_APPLICATION(application);
68 | // Strip out the first argument as it is the binary name.
69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
70 |
71 | g_autoptr(GError) error = nullptr;
72 | if (!g_application_register(application, nullptr, &error)) {
73 | g_warning("Failed to register: %s", error->message);
74 | *exit_status = 1;
75 | return TRUE;
76 | }
77 |
78 | g_application_activate(application);
79 | *exit_status = 0;
80 |
81 | return TRUE;
82 | }
83 |
84 | // Implements GApplication::startup.
85 | static void my_application_startup(GApplication* application) {
86 | //MyApplication* self = MY_APPLICATION(object);
87 |
88 | // Perform any actions required at application startup.
89 |
90 | G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
91 | }
92 |
93 | // Implements GApplication::shutdown.
94 | static void my_application_shutdown(GApplication* application) {
95 | //MyApplication* self = MY_APPLICATION(object);
96 |
97 | // Perform any actions required at application shutdown.
98 |
99 | G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
100 | }
101 |
102 | // Implements GObject::dispose.
103 | static void my_application_dispose(GObject* object) {
104 | MyApplication* self = MY_APPLICATION(object);
105 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
106 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
107 | }
108 |
109 | static void my_application_class_init(MyApplicationClass* klass) {
110 | G_APPLICATION_CLASS(klass)->activate = my_application_activate;
111 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
112 | G_APPLICATION_CLASS(klass)->startup = my_application_startup;
113 | G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
114 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
115 | }
116 |
117 | static void my_application_init(MyApplication* self) {}
118 |
119 | MyApplication* my_application_new() {
120 | return MY_APPLICATION(g_object_new(my_application_get_type(),
121 | "application-id", APPLICATION_ID,
122 | "flags", G_APPLICATION_NON_UNIQUE,
123 | nullptr));
124 | }
125 |
--------------------------------------------------------------------------------
/lib/controller/db.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:path/path.dart';
4 | import 'package:sqflite/sqflite.dart';
5 |
6 | class DatabaseHelper {
7 | static final DatabaseHelper instance = DatabaseHelper._();
8 | static Database? _database;
9 | static const tableName = "basic_1";
10 | static const customList = "customList";
11 | DatabaseHelper._();
12 |
13 | Future get database async {
14 | if (_database != null) return _database!;
15 |
16 | _database = await _initDB();
17 | return _database!;
18 | }
19 |
20 | final initScript = [
21 | '''
22 | CREATE TABLE $tableName(
23 | id INTEGER PRIMARY KEY AUTOINCREMENT,
24 | title TEXT,
25 | description TEXT,
26 | is_done INTEGER,
27 | date_created INTEGER,
28 | date_modified INTEGER,
29 | has_alarm INTEGER,
30 | alarm_time TEXT,
31 | custom_list TEXT,
32 | trash INTEGER
33 | )
34 | ''',
35 | '''
36 | CREATE TABLE IF NOT EXISTS $customList(
37 | id INTEGER PRIMARY KEY AUTOINCREMENT,
38 | name TEXT,
39 | trash INTEGER
40 | )
41 | '''
42 | ];
43 |
44 | final migrationScript = [
45 | 'ALTER TABLE $tableName ADD IF NOT EXISTS custom_list TEXT, trash INTEGER',
46 | '''
47 | CREATE TABLE IF NOT EXISTS $customList(
48 | id INTEGER PRIMARY KEY AUTOINCREMENT,
49 | name TEXT,
50 | trash INTEGER
51 | )
52 | '''
53 | ];
54 |
55 | Future _initDB() async {
56 | final dbPath = await getDatabasesPath();
57 | final path = join(dbPath, 'todo.db');
58 |
59 | return await openDatabase(
60 | path,
61 | version: migrationScript.length,
62 | onCreate: (db, version) async {
63 | for (var script in initScript) {
64 | await db.execute(script);
65 | }
66 | },
67 | onUpgrade: (db, oldVersion, newVersion) async {
68 | var batch = db.batch();
69 | for (var i = oldVersion - 1; i <= newVersion - 1; i++) {
70 | batch.execute(migrationScript[i]);
71 | }
72 | await batch.commit();
73 | },
74 | );
75 | }
76 |
77 | Future>> getCustomList() async {
78 | final db = await instance.database;
79 | return db.query(customList, where: 'trash = 0');
80 | }
81 |
82 | Future addCustomList(String name) async {
83 | final db = await instance.database;
84 | return await db.insert(customList, {"name": name, 'trash': 0});
85 | }
86 |
87 | Future getCustomListName(int id) async {
88 | final db = await instance.database;
89 | final result = await db.query(customList,
90 | where: 'id = ?', whereArgs: [id], limit: 1, columns: ['name']);
91 | return result.first.entries.first.value.toString();
92 | }
93 |
94 | Future updateCustomListName(int id, String name) async {
95 | final db = await instance.database;
96 | return await db.update(customList, {'name': name},
97 | where: 'id = ?', whereArgs: [id]);
98 | }
99 |
100 | Future moveaToTrashCustomList(int id) async {
101 | final db = await instance.database;
102 | return await db.update(customList, {'trash': 1},
103 | where: 'id = ?', whereArgs: [id]);
104 | }
105 |
106 | Future>> getTodos(
107 | String colname, String filter) async {
108 | final db = await instance.database;
109 | //final List