From 4e11c2de721504fb130a2ad99664a4d83b66eafa Mon Sep 17 00:00:00 2001 From: Prince Date: Thu, 29 Jan 2026 12:09:19 +0530 Subject: [PATCH 01/12] Improve date picker flow handling --- .../add_task_dialogue/date_picker_input.dart | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/app/utils/add_task_dialogue/date_picker_input.dart b/lib/app/utils/add_task_dialogue/date_picker_input.dart index fe1d6f13..0a4c2b67 100644 --- a/lib/app/utils/add_task_dialogue/date_picker_input.dart +++ b/lib/app/utils/add_task_dialogue/date_picker_input.dart @@ -106,11 +106,36 @@ class _AddTaskDatePickerInputState extends State { firstDate: DateTime.now(), lastDate: DateTime(2101), ); + + // FIX: Check if date was selected before showing time picker + if (picked == null) { + return; // User canceled date picker, exit early + } + + // Only show time picker if date was selected final TimeOfDay? time = await showTimePicker( context: context, initialTime: TimeOfDay.now(), ); - if (picked == null || time == null) return; + + // If user cancels time picker, still set the date with default time + if (time == null) { + setState(() { + // Set date with end-of-day time (23:59) + _selectedDates[forIndex] = picked.add( + const Duration(hours: 23, minutes: 59), + ); + // Update the controller text + _controllers[forIndex].text = + dateToStringForAddTask(_selectedDates[forIndex]!); + }); + if (widget.onDateChanges != null) { + widget.onDateChanges!(_selectedDates); + } + return; + } + + // Both date and time selected setState(() { _selectedDates[forIndex] = picked.add(Duration(hours: time.hour, minutes: time.minute)); @@ -135,4 +160,4 @@ class _AddTaskDatePickerInputState extends State { } return null; } -} +} \ No newline at end of file From 9f7813b7362579669f0d3dde78bac6bf2c63c255 Mon Sep 17 00:00:00 2001 From: Prince Date: Fri, 30 Jan 2026 15:28:08 +0530 Subject: [PATCH 02/12] Preserve taskd.trust when importing and exporting taskrc --- .../manage_task_server_controller.dart | 32 ++++++++++++------- lib/app/utils/taskserver/taskrc.dart | 6 ++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart b/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart index 2fe75484..02b478c2 100644 --- a/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart +++ b/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart @@ -24,7 +24,9 @@ class ManageTaskServerController extends GetxController { late RxString alias; Server? server; Credentials? credentials; + String? trust; final TextEditingController taskrcContentController = TextEditingController(); + RxBool isTaskDServerActive = true.obs; RxBool hideKey = true.obs; @@ -37,13 +39,12 @@ class ManageTaskServerController extends GetxController { alias = RxString(splashController.profilesMap[profile.value] ?? ''); var contents = rc.Taskrc(storage.home.home).readTaskrc(); if (contents != null) { - server = Taskrc.fromString(contents).server; - credentials = Taskrc.fromString(contents).credentials; - } - if (contents != null) { - server = Taskrc.fromString(contents).server; - credentials = Taskrc.fromString(contents).credentials; + final taskrc = Taskrc.fromString(contents); + server = taskrc.server; + credentials = taskrc.credentials; + trust = taskrc.trust; // ⬅️ ADD THIS } + configureCredentialString(); update(); } @@ -53,8 +54,7 @@ class ManageTaskServerController extends GetxController { var contents = await rootBundle.loadString('assets/.taskrc'); rc.Taskrc(storage.home.home).addTaskrc(contents); var taskrc = Taskrc.fromString(contents); - server = taskrc.server; - credentials = taskrc.credentials; + trust = taskrc.trust; for (var entry in { 'taskd.certificate': '.task/first_last.cert.pem', 'taskd.key': '.task/first_last.key.pem', @@ -96,12 +96,12 @@ class ManageTaskServerController extends GetxController { // Check if the server and credentials are present in the Taskrc object if (taskrc.server != null && taskrc.credentials != null) { - // Update the server and credentials variables - server = taskrc.server; credentials = taskrc.credentials; + trust = taskrc.trust; // ⬅️ ADD THIS update(); + // Handle the case when server or credentials are missing in the Taskrc object Navigator.pop(context); @@ -162,8 +162,16 @@ class ManageTaskServerController extends GetxController { if (credentialsString!.value.isNotEmpty && server.toString().isNotEmpty) { //print(credentialsString.value); - taskrcContentController.text = - "taskd.server=$server\ntaskd.credentials=${credentials!.org}/${credentials!.user}/$key"; + var taskrcContent = + "taskd.server=$server\n" + "taskd.credentials=${credentials!.org}/${credentials!.user}/$key"; + + if (trust?.isNotEmpty == true) { + taskrcContent += "\ntaskd.trust=$trust"; // ⬅️ ADD THIS + } + + taskrcContentController.text = taskrcContent; + isTaskDServerActive.value = false; } diff --git a/lib/app/utils/taskserver/taskrc.dart b/lib/app/utils/taskserver/taskrc.dart index 36348b9a..67dd406b 100644 --- a/lib/app/utils/taskserver/taskrc.dart +++ b/lib/app/utils/taskserver/taskrc.dart @@ -7,6 +7,7 @@ class Taskrc { Taskrc({ this.server, this.credentials, + this.trust, // ignore: always_put_required_named_parameters_first required this.pemFilePaths, }); @@ -20,15 +21,20 @@ class Taskrc { factory Taskrc.fromMap(Map taskrc) { var server = taskrc['taskd.server']; var credentials = taskrc['taskd.credentials']; + var trust = taskrc['taskd.trust']; // ⬅️ ADD THIS LINE + return Taskrc( server: (server == null) ? null : Server.fromString(server), credentials: (credentials == null) ? null : Credentials.fromString(credentials), + trust: trust, // ⬅️ ADD THIS LINE pemFilePaths: PemFilePaths.fromTaskrc(taskrc), ); } + final Server? server; final Credentials? credentials; + final String? trust; final PemFilePaths pemFilePaths; } From eb65d403b0c5cc98db010ab95c502760396d8a01 Mon Sep 17 00:00:00 2001 From: Prince Date: Sat, 31 Jan 2026 16:48:35 +0530 Subject: [PATCH 03/12] Added A status Filter For Deleted Tasks --- lib/app/models/filters.dart | 10 ++- .../home/controllers/home_controller.dart | 52 ++++++++++++++- .../home/views/filter_drawer_home_page.dart | 66 ++++++++++--------- 3 files changed, 92 insertions(+), 36 deletions(-) diff --git a/lib/app/models/filters.dart b/lib/app/models/filters.dart index a2296246..67b3ecae 100644 --- a/lib/app/models/filters.dart +++ b/lib/app/models/filters.dart @@ -1,11 +1,13 @@ -import 'package:taskwarrior/app/services/tag_filter.dart'; - class Filters { const Filters({ required this.pendingFilter, required this.waitingFilter, + required this.completedFilter, // NEW + required this.deletedFilter, // NEW required this.togglePendingFilter, required this.toggleWaitingFilter, + required this.toggleCompletedFilter, // NEW + required this.toggleDeletedFilter, // NEW required this.tagFilters, required this.projects, required this.projectFilter, @@ -14,8 +16,12 @@ class Filters { final bool pendingFilter; final bool waitingFilter; + final bool completedFilter; // NEW + final bool deletedFilter; // NEW final void Function() togglePendingFilter; final void Function() toggleWaitingFilter; + final void Function() toggleCompletedFilter; // NEW + final void Function() toggleDeletedFilter; // NEW final TagFilters tagFilters; final dynamic projects; final String projectFilter; diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index a882111a..e92c7902 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -50,6 +50,8 @@ class HomeController extends GetxController { final RxBool pendingFilter = false.obs; final RxBool waitingFilter = false.obs; final RxString projectFilter = ''.obs; + final RxBool completedFilter = false.obs; + final RxBool deletedFilter = false.obs; final RxBool tagUnion = false.obs; final RxString selectedSort = ''.obs; final RxSet selectedTags = {}.obs; @@ -101,6 +103,8 @@ class HomeController extends GetxController { everAll([ pendingFilter, waitingFilter, + completedFilter, + deletedFilter, projectFilter, tagUnion, selectedSort, @@ -237,15 +241,35 @@ class HomeController extends GetxController { } void _refreshTasks() { - if (pendingFilter.value) { + + if (deletedFilter.value) { + // Show ONLY deleted tasks + queriedTasks.value = storage.data + .completedData() + .where((task) => task.status == 'deleted') + .toList(); + } + else if (completedFilter.value) { + // Show completed tasks (EXCLUDE deleted) + queriedTasks.value = storage.data + .completedData() + .where((task) => task.status == 'completed') + .toList(); + } + else if (pendingFilter.value) { + // Show pending tasks (default behaviour) queriedTasks.value = storage.data .pendingData() .where((task) => task.status == 'pending') .toList(); - } else { - queriedTasks.value = storage.data.completedData(); + } + else { + // Fallback: pending tasks + queriedTasks.value = storage.data.pendingData(); } + + // Rest of the method stays the same... if (waitingFilter.value) { var currentTime = DateTime.now(); queriedTasks.value = queriedTasks @@ -347,6 +371,22 @@ class HomeController extends GetxController { _refreshTasks(); } + void toggleCompletedFilter() { + completedFilter.toggle(); + if (completedFilter.value) { + deletedFilter.value = false; + } + _refreshTasks(); + } + + void toggleDeletedFilter() { + deletedFilter.toggle(); + if (deletedFilter.value) { + completedFilter.value = false; + } + _refreshTasks(); + } + void toggleProjectFilter(String project) { Query(storage.tabs.tab()).toggleProjectFilter(project); projectFilter.value = Query(storage.tabs.tab()).projectFilter(); @@ -613,11 +653,17 @@ class HomeController extends GetxController { tags: tags, toggleTagFilter: toggleTagFilter, ); + + // REPLACE this entire Filters() instantiation: var filters = Filters( pendingFilter: pendingFilter.value, waitingFilter: waitingFilter.value, + completedFilter: completedFilter.value, // NEW - Add this line + deletedFilter: deletedFilter.value, // NEW - Add this line togglePendingFilter: togglePendingFilter, toggleWaitingFilter: toggleWaitingFilter, + toggleCompletedFilter: toggleCompletedFilter, // NEW - Add this line + toggleDeletedFilter: toggleDeletedFilter, // NEW - Add this line projects: projects, projectFilter: projectFilter.value, toggleProjectFilter: toggleProjectFilter, diff --git a/lib/app/modules/home/views/filter_drawer_home_page.dart b/lib/app/modules/home/views/filter_drawer_home_page.dart index 085a969d..e4a61518 100644 --- a/lib/app/modules/home/views/filter_drawer_home_page.dart +++ b/lib/app/modules/home/views/filter_drawer_home_page.dart @@ -97,17 +97,20 @@ class FilterDrawer extends StatelessWidget { color: tColors.primaryTextColor, )), TextSpan( - text: filters.pendingFilter - ? SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerPending - : SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerCompleted, + text: filters.deletedFilter + ? 'Deleted' + : filters.completedFilter + ? SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerCompleted + : SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerPending, + style: TextStyle( fontFamily: FontFamily.poppins, fontSize: TaskWarriorFonts.fontSizeMedium, @@ -116,7 +119,16 @@ class FilterDrawer extends StatelessWidget { ], ), ), - onTap: filters.togglePendingFilter, + onTap: () { + if (filters.deletedFilter) { + filters.toggleDeletedFilter(); + } else if (filters.completedFilter) { + filters.toggleCompletedFilter(); + } else { + filters.togglePendingFilter(); + } + }, + textColor: tColors.primaryTextColor, ), ), @@ -137,31 +149,23 @@ class FilterDrawer extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - !filters.waitingFilter - ? SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerShowWaiting - : SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerHideWaiting, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - )), + 'Show Deleted', + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + ), + ), Switch( - value: filters.waitingFilter, - onChanged: (_) => filters.toggleWaitingFilter(), - ) + value: filters.deletedFilter, + onChanged: (_) => filters.toggleDeletedFilter(), + ), ], ), ), ), ), + const Divider( color: Color.fromARGB(0, 48, 46, 46), ), From 067d869c428471aa19791c68776c249be6c3b940 Mon Sep 17 00:00:00 2001 From: Prince Date: Tue, 3 Feb 2026 11:34:00 +0530 Subject: [PATCH 04/12] fix: auto-dismiss TaskServer not configured banner --- .../home/controllers/home_controller.dart | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index e92c7902..780a055a 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously, unrelated_type_equality_checks +import 'package:taskwarrior/app/utils/language/sentences.dart'; + import 'dart:collection'; import 'dart:io'; @@ -47,6 +49,7 @@ import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; class HomeController extends GetxController { final SplashController splashController = Get.find(); late Storage storage; + final RxBool taskServerBannerShown = false.obs; final RxBool pendingFilter = false.obs; final RxBool waitingFilter = false.obs; final RxString projectFilter = ''.obs; @@ -572,6 +575,44 @@ class HomeController extends GetxController { _refreshTasks(); } + void showTaskServerNotConfiguredBanner(BuildContext context) { + if (taskServerBannerShown.value) return; + + taskServerBannerShown.value = true; + final messenger = ScaffoldMessenger.of(context); + + messenger.clearMaterialBanners(); + + messenger.showMaterialBanner( + MaterialBanner( + content: Text(sentences.homePageTaskWarriorNotConfigured), + actions: [ + TextButton( + onPressed: () { + messenger.hideCurrentMaterialBanner(); + taskServerBannerShown.value = false; // ✅ RESET flag + Get.toNamed(Routes.TASKSERVER_SETUP); + }, + child: Text(sentences.homePageSetup), + ), + TextButton( + onPressed: () { + messenger.hideCurrentMaterialBanner(); + taskServerBannerShown.value = false; // ✅ RESET flag + }, + child: const Text('Dismiss'), + ), + ], + ), + ); + + Future.delayed(const Duration(seconds: 5), () { + messenger.hideCurrentMaterialBanner(); + taskServerBannerShown.value = false; // ✅ RESET flag + }); + } + + void renameTab({ required String tab, required String name, @@ -600,9 +641,14 @@ class HomeController extends GetxController { clientId = await CredentialsStorage.getClientId(); encryptionSecret = await CredentialsStorage.getEncryptionSecret(); if (value) { + if (clientId == null || encryptionSecret == null) { + showTaskServerNotConfiguredBanner(context); + return; + } + synchronize(context, false); - refreshTasks(clientId!, encryptionSecret!); - } else {} + refreshTasks(clientId, encryptionSecret); + } } RxBool syncOnStart = false.obs; From 8c60251683b5a03f29dfec94281a4a8684f6820e Mon Sep 17 00:00:00 2001 From: Prince Date: Wed, 4 Feb 2026 13:53:53 +0530 Subject: [PATCH 05/12] Solved CI --- lib/app/models/filters.dart | 42 ++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/lib/app/models/filters.dart b/lib/app/models/filters.dart index 67b3ecae..c53732d2 100644 --- a/lib/app/models/filters.dart +++ b/lib/app/models/filters.dart @@ -1,13 +1,39 @@ +// lib/app/models/filters.dart + +class TagFilterMetadata { + final String display; + final bool selected; + + TagFilterMetadata({ + required this.display, + required this.selected, + }); +} + +class TagFilters { + final bool tagUnion; + final void Function() toggleTagUnion; + final Map tags; + final void Function(String) toggleTagFilter; + + TagFilters({ + required this.tagUnion, + required this.toggleTagUnion, + required this.tags, + required this.toggleTagFilter, + }); +} + class Filters { const Filters({ required this.pendingFilter, required this.waitingFilter, - required this.completedFilter, // NEW - required this.deletedFilter, // NEW + required this.completedFilter, + required this.deletedFilter, required this.togglePendingFilter, required this.toggleWaitingFilter, - required this.toggleCompletedFilter, // NEW - required this.toggleDeletedFilter, // NEW + required this.toggleCompletedFilter, + required this.toggleDeletedFilter, required this.tagFilters, required this.projects, required this.projectFilter, @@ -16,12 +42,12 @@ class Filters { final bool pendingFilter; final bool waitingFilter; - final bool completedFilter; // NEW - final bool deletedFilter; // NEW + final bool completedFilter; + final bool deletedFilter; final void Function() togglePendingFilter; final void Function() toggleWaitingFilter; - final void Function() toggleCompletedFilter; // NEW - final void Function() toggleDeletedFilter; // NEW + final void Function() toggleCompletedFilter; + final void Function() toggleDeletedFilter; final TagFilters tagFilters; final dynamic projects; final String projectFilter; From 984cb125102ce21d31419bc65b952157dd3ce5a5 Mon Sep 17 00:00:00 2001 From: Prince Date: Wed, 4 Feb 2026 15:13:48 +0530 Subject: [PATCH 06/12] Fix analyzer errors by separating TagFilters model and updating imports --- lib/app/models/filters.dart | 23 +-------- lib/app/models/tag_filters.dart | 25 ++++++++++ .../home/controllers/home_controller.dart | 11 ++-- lib/app/services/tag_filter.dart | 50 ++----------------- 4 files changed, 36 insertions(+), 73 deletions(-) create mode 100644 lib/app/models/tag_filters.dart diff --git a/lib/app/models/filters.dart b/lib/app/models/filters.dart index c53732d2..d29f7a1d 100644 --- a/lib/app/models/filters.dart +++ b/lib/app/models/filters.dart @@ -1,28 +1,7 @@ // lib/app/models/filters.dart -class TagFilterMetadata { - final String display; - final bool selected; +import 'package:taskwarrior/app/models/tag_filters.dart'; - TagFilterMetadata({ - required this.display, - required this.selected, - }); -} - -class TagFilters { - final bool tagUnion; - final void Function() toggleTagUnion; - final Map tags; - final void Function(String) toggleTagFilter; - - TagFilters({ - required this.tagUnion, - required this.toggleTagUnion, - required this.tags, - required this.toggleTagFilter, - }); -} class Filters { const Filters({ diff --git a/lib/app/models/tag_filters.dart b/lib/app/models/tag_filters.dart new file mode 100644 index 00000000..29fa88cb --- /dev/null +++ b/lib/app/models/tag_filters.dart @@ -0,0 +1,25 @@ +// lib/app/models/tag_filters.dart + +class TagFilterMetadata { + const TagFilterMetadata({ + required this.display, + required this.selected, + }); + + final String display; + final bool selected; +} + +class TagFilters { + const TagFilters({ + required this.tagUnion, + required this.toggleTagUnion, + required this.tags, + required this.toggleTagFilter, + }); + + final bool tagUnion; + final void Function() toggleTagUnion; + final Map tags; + final void Function(String) toggleTagFilter; +} diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index 88ad5c30..05ed23c3 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -5,6 +5,8 @@ import 'package:taskwarrior/app/utils/language/sentences.dart'; import 'dart:collection'; import 'dart:io'; +import 'package:taskwarrior/app/routes/app_routes.dart'; + import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -20,7 +22,8 @@ import 'package:taskwarrior/app/models/tag_meta_data.dart'; import 'package:taskwarrior/app/modules/home/controllers/widget.controller.dart'; import 'package:taskwarrior/app/modules/splash/controllers/splash_controller.dart'; import 'package:taskwarrior/app/services/deep_link_service.dart'; -import 'package:taskwarrior/app/services/tag_filter.dart'; +import 'package:taskwarrior/app/models/tag_filters.dart'; + import 'package:taskwarrior/app/tour/filter_drawer_tour.dart'; import 'package:taskwarrior/app/tour/home_page_tour.dart'; import 'package:taskwarrior/app/tour/task_swipe_tour.dart'; @@ -581,15 +584,15 @@ class HomeController extends GetxController { messenger.showMaterialBanner( MaterialBanner( - content: Text(sentences.homePageTaskWarriorNotConfigured), + content: Text(Sentences.homePageTaskWarriorNotConfigured), actions: [ TextButton( onPressed: () { messenger.hideCurrentMaterialBanner(); taskServerBannerShown.value = false; // ✅ RESET flag - Get.toNamed(Routes.TASKSERVER_SETUP); + Get.toNamed(Routes.TASKSERVER_SETUP), }, - child: Text(sentences.homePageSetup), + child: Text(Sentences.homePageSetup), ), TextButton( onPressed: () { diff --git a/lib/app/services/tag_filter.dart b/lib/app/services/tag_filter.dart index 2eaa7a56..81fddff8 100644 --- a/lib/app/services/tag_filter.dart +++ b/lib/app/services/tag_filter.dart @@ -1,29 +1,5 @@ import 'package:flutter/material.dart'; - - -class TagFilterMetadata { - const TagFilterMetadata({ - required this.display, - required this.selected, - }); - - final String display; - final bool selected; -} - -class TagFilters { - const TagFilters({ - required this.tagUnion, - required this.toggleTagUnion, - required this.tags, - required this.toggleTagFilter, - }); - - final bool tagUnion; - final void Function() toggleTagUnion; - final Map tags; - final void Function(String) toggleTagFilter; -} +import 'package:taskwarrior/app/models/tag_filters.dart'; class TagFiltersWrap extends StatelessWidget { const TagFiltersWrap(this.filters, {super.key}); @@ -37,32 +13,12 @@ class TagFiltersWrap extends StatelessWidget { children: [ FilterChip( onSelected: (_) => filters.toggleTagUnion(), - label: Text( - filters.tagUnion ? 'OR' : 'AND', - // style: GoogleFonts.poppins( - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.black - // : TaskWarriorColors.white) - ), - // backgroundColor: AppSettings.isDarkMode - // ? TaskWarriorColors.kLightSecondaryBackgroundColor - // : TaskWarriorColors.ksecondaryBackgroundColor, + label: Text(filters.tagUnion ? 'OR' : 'AND'), ), for (var entry in filters.tags.entries) FilterChip( onSelected: (_) => filters.toggleTagFilter(entry.key), - label: Text( - entry.value.display, - // style: GoogleFonts.poppins( - // fontWeight: - // entry.value.selected ? TaskWarriorFonts.bold : null, - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.black - // : TaskWarriorColors.white), - ), - // backgroundColor: AppSettings.isDarkMode - // ? TaskWarriorColors.kLightSecondaryBackgroundColor - // : TaskWarriorColors.kprimaryBackgroundColor, + label: Text(entry.value.display), ), ], ); From b91ed32a78e4106603af6c28d9895c5cd3e1a8b4 Mon Sep 17 00:00:00 2001 From: Prince Date: Wed, 4 Feb 2026 15:36:20 +0530 Subject: [PATCH 07/12] Fix Flutter analyzer errors and update Filters tests --- .../home/controllers/home_controller.dart | 9 ++++++--- test/models/filters_test.dart | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index 05ed23c3..7ddcfa6e 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -5,7 +5,7 @@ import 'package:taskwarrior/app/utils/language/sentences.dart'; import 'dart:collection'; import 'dart:io'; -import 'package:taskwarrior/app/routes/app_routes.dart'; +import 'package:taskwarrior/app/routes/app_pages.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; @@ -45,10 +45,13 @@ import 'package:textfield_tags/textfield_tags.dart'; import 'package:taskwarrior/app/utils/themes/theme_extension.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; + + class HomeController extends GetxController { final SplashController splashController = Get.find(); late Storage storage; final RxBool taskServerBannerShown = false.obs; + final Sentences sentences = Sentences(); final RxBool pendingFilter = false.obs; final RxBool waitingFilter = false.obs; final RxString projectFilter = ''.obs; @@ -584,7 +587,7 @@ class HomeController extends GetxController { messenger.showMaterialBanner( MaterialBanner( - content: Text(Sentences.homePageTaskWarriorNotConfigured), + content: Text(sentences.homePageTaskWarriorNotConfigured), actions: [ TextButton( onPressed: () { @@ -592,7 +595,7 @@ class HomeController extends GetxController { taskServerBannerShown.value = false; // ✅ RESET flag Get.toNamed(Routes.TASKSERVER_SETUP), }, - child: Text(Sentences.homePageSetup), + child: Text(sentences.homePageSetup), ), TextButton( onPressed: () { diff --git a/test/models/filters_test.dart b/test/models/filters_test.dart index 8d577349..c1ea77fd 100644 --- a/test/models/filters_test.dart +++ b/test/models/filters_test.dart @@ -1,9 +1,14 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:taskwarrior/app/models/filters.dart'; -import 'package:taskwarrior/app/services/tag_filter.dart'; +import 'package:taskwarrior/app/models/tag_filters.dart'; + void main() { group('Filters', () { + + late bool completedFilter; + late bool deletedFilter; + late Filters filters; late bool pendingFilter; late bool waitingFilter; @@ -12,6 +17,9 @@ void main() { late Map tags; setUp(() { + completedFilter = false; + deletedFilter = false; + pendingFilter = false; waitingFilter = false; projectFilter = 'TestProject'; @@ -24,12 +32,20 @@ void main() { filters = Filters( pendingFilter: pendingFilter, waitingFilter: waitingFilter, + completedFilter: completedFilter, + deletedFilter: deletedFilter, togglePendingFilter: () { pendingFilter = !pendingFilter; }, toggleWaitingFilter: () { waitingFilter = !waitingFilter; }, + toggleCompletedFilter: () { + completedFilter = !completedFilter; + }, + toggleDeletedFilter: () { + deletedFilter = !deletedFilter; + }, tagFilters: TagFilters( tagUnion: tagUnion, toggleTagUnion: () { @@ -49,6 +65,7 @@ void main() { projectFilter = project; }, ); + }); test('should correctly initialize with given parameters', () { From 2984c68c013031bb3268372d58a0ce4387038346 Mon Sep 17 00:00:00 2001 From: Prince Date: Sat, 21 Feb 2026 22:10:26 +0530 Subject: [PATCH 08/12] fix: hide blocked tasks filter and depends UI (#595) --- lib/app/models/filters.dart | 4 ++ .../home/controllers/home_controller.dart | 33 +++++++----- .../home/views/filter_drawer_home_page.dart | 29 ++++++++++ .../controllers/taskc_details_controller.dart | 54 ++++++++++++++++++- .../views/taskc_details_view.dart | 15 ++++++ 5 files changed, 119 insertions(+), 16 deletions(-) diff --git a/lib/app/models/filters.dart b/lib/app/models/filters.dart index d29f7a1d..d47cf749 100644 --- a/lib/app/models/filters.dart +++ b/lib/app/models/filters.dart @@ -17,6 +17,8 @@ class Filters { required this.projects, required this.projectFilter, required this.toggleProjectFilter, + required this.hideBlocked, // ADD + required this.toggleHideBlocked, }); final bool pendingFilter; @@ -31,4 +33,6 @@ class Filters { final dynamic projects; final String projectFilter; final void Function(String) toggleProjectFilter; + final bool hideBlocked; + final void Function() toggleHideBlocked; } \ No newline at end of file diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index 7ddcfa6e..dea84b13 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -54,6 +54,7 @@ class HomeController extends GetxController { final Sentences sentences = Sentences(); final RxBool pendingFilter = false.obs; final RxBool waitingFilter = false.obs; + final RxBool hideBlocked = false.obs; final RxString projectFilter = ''.obs; final RxBool completedFilter = false.obs; final RxBool deletedFilter = false.obs; @@ -248,31 +249,30 @@ class HomeController extends GetxController { void _refreshTasks() { if (deletedFilter.value) { - // Show ONLY deleted tasks queriedTasks.value = storage.data .completedData() .where((task) => task.status == 'deleted') .toList(); - } - else if (completedFilter.value) { - // Show completed tasks (EXCLUDE deleted) + } else if (completedFilter.value) { queriedTasks.value = storage.data .completedData() .where((task) => task.status == 'completed') .toList(); - } - else if (pendingFilter.value) { - // Show pending tasks (default behaviour) + } else if (pendingFilter.value) { queriedTasks.value = storage.data .pendingData() .where((task) => task.status == 'pending') .toList(); - } - else { - // Fallback: pending tasks + } else { queriedTasks.value = storage.data.pendingData(); } + if (hideBlocked.value) { + queriedTasks.value = queriedTasks + .where((task) => task.depends == null || task.depends!.isEmpty) + .toList(); + } + // Rest of the method stays the same... if (waitingFilter.value) { @@ -706,16 +706,21 @@ class HomeController extends GetxController { var filters = Filters( pendingFilter: pendingFilter.value, waitingFilter: waitingFilter.value, - completedFilter: completedFilter.value, // NEW - Add this line - deletedFilter: deletedFilter.value, // NEW - Add this line + completedFilter: completedFilter.value, + deletedFilter: deletedFilter.value, togglePendingFilter: togglePendingFilter, toggleWaitingFilter: toggleWaitingFilter, - toggleCompletedFilter: toggleCompletedFilter, // NEW - Add this line - toggleDeletedFilter: toggleDeletedFilter, // NEW - Add this line + toggleCompletedFilter: toggleCompletedFilter, + toggleDeletedFilter: toggleDeletedFilter, projects: projects, projectFilter: projectFilter.value, toggleProjectFilter: toggleProjectFilter, tagFilters: tagFilters, + hideBlocked: hideBlocked.value, + toggleHideBlocked: () { + hideBlocked.value = !hideBlocked.value; + _refreshTasks(); + }, ); return filters; } diff --git a/lib/app/modules/home/views/filter_drawer_home_page.dart b/lib/app/modules/home/views/filter_drawer_home_page.dart index e4a61518..12d9e563 100644 --- a/lib/app/modules/home/views/filter_drawer_home_page.dart +++ b/lib/app/modules/home/views/filter_drawer_home_page.dart @@ -166,6 +166,35 @@ class FilterDrawer extends StatelessWidget { ), ), + Container( + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: TaskWarriorColors.borderColor), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Hide Blocked Tasks', + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + ), + ), + Obx(() => Switch( + value: homeController.hideBlocked.value, + onChanged: (_) => filters.toggleHideBlocked(), + )), + ], + ), + ), + ), + const Divider(color: Color.fromARGB(0, 48, 46, 46)), + const Divider( color: Color.fromARGB(0, 48, 46, 46), ), diff --git a/lib/app/modules/taskc_details/controllers/taskc_details_controller.dart b/lib/app/modules/taskc_details/controllers/taskc_details_controller.dart index 6116cf7e..a6db9b9e 100644 --- a/lib/app/modules/taskc_details/controllers/taskc_details_controller.dart +++ b/lib/app/modules/taskc_details/controllers/taskc_details_controller.dart @@ -60,7 +60,8 @@ class TaskcDetailsController extends GetxController { ? task.tags!.map((e) => e.toString()).toList().obs : [].obs; previousTags = tags.toList().obs; - depends = "".split(",").obs; + // For TaskForC block: + depends = (task.depends ?? []).obs; rtype = "".obs; recur = "".obs; annotations = [].obs; @@ -81,7 +82,9 @@ class TaskcDetailsController extends GetxController { ? task.tags!.map((e) => e.toString()).toList().obs : [].obs; previousTags = tags.toList().obs; - depends = "".split(",").obs; + + // For TaskForReplica block: + depends = (task.depends ?? []).obs; rtype = "".obs; recur = "".obs; annotations = [].obs; @@ -501,4 +504,51 @@ class TaskcDetailsController extends GetxController { ), ); } + Future showDependencyPicker() async { + // Get all pending tasks except current + final allTasks = await taskDatabase.fetchTasksFromDatabase(); + final BuildContext context = Get.context!; + TaskwarriorColorTheme tColors = + Theme.of(context).extension()!; + + await Get.dialog( + AlertDialog( + backgroundColor: tColors.secondaryBackgroundColor, + title: Text('Select Dependencies', style: TextStyle(color: tColors.primaryTextColor)), + content: StatefulBuilder( + builder: (context, setState) { + return SizedBox( + width: double.maxFinite, + child: ListView( + shrinkWrap: true, + children: allTasks + .where((t) => t.uuid != initialTask.uuid && t.status == 'pending') + .map((t) => CheckboxListTile( + title: Text(t.description, style: TextStyle(color: tColors.primaryTextColor)), + value: depends.contains(t.uuid), + onChanged: (checked) { + setState(() { + if (checked == true) { + depends.add(t.uuid!); + } else { + depends.remove(t.uuid); + } + hasChanges.value = true; + }); + }, + )) + .toList(), + ), + ); + }, + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text('Done', style: TextStyle(color: tColors.primaryTextColor)), + ), + ], + ), + ); + } } diff --git a/lib/app/modules/taskc_details/views/taskc_details_view.dart b/lib/app/modules/taskc_details/views/taskc_details_view.dart index a3938743..728f2611 100644 --- a/lib/app/modules/taskc_details/views/taskc_details_view.dart +++ b/lib/app/modules/taskc_details/views/taskc_details_view.dart @@ -41,6 +41,7 @@ class TaskcDetailsView extends GetView { (value) => controller.updateField(controller.description, value), ), + _buildDependsDetail(context), _buildEditableDetail( context, '${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.project}:', @@ -169,6 +170,20 @@ class TaskcDetailsView extends GetView { ); } + Widget _buildDependsDetail(BuildContext context) { + return InkWell( + onTap: () => controller.showDependencyPicker(), + child: Obx(() => _buildDetail( + context, + 'Dependencies:', + controller.depends.isEmpty || + (controller.depends.length == 1 && controller.depends[0].isEmpty) + ? 'None' + : controller.depends.join(', '), + )), + ); + } + Widget _buildEditableDetail(BuildContext context, String label, String value, Function(String) onChanged) { return InkWell( From 698c4f44702c8bbfd191dcd2c84e6602be733f06 Mon Sep 17 00:00:00 2001 From: Prince Date: Mon, 23 Feb 2026 19:17:35 +0530 Subject: [PATCH 09/12] Fixes:Android Widget crashes --- .../TaskWarriorWidgetProvider.kt | 30 +++++++------------ lib/app/services/deep_link_service.dart | 10 ++++++- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/android/app/src/main/kotlin/com/ccextractor/taskwarriorflutter/TaskWarriorWidgetProvider.kt b/android/app/src/main/kotlin/com/ccextractor/taskwarriorflutter/TaskWarriorWidgetProvider.kt index d57d4cb0..dd6e8935 100644 --- a/android/app/src/main/kotlin/com/ccextractor/taskwarriorflutter/TaskWarriorWidgetProvider.kt +++ b/android/app/src/main/kotlin/com/ccextractor/taskwarriorflutter/TaskWarriorWidgetProvider.kt @@ -83,21 +83,12 @@ override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appW MainActivity::class.java ) setOnClickPendingIntent(R.id.logo, pendingIntent) - - // Set up the Add Button click (Custom Action) - val intent_for_add = Intent(context, TaskWarriorWidgetProvider::class.java).apply { - action = "TASK_ACTION" - putExtra("launchedFor", "ADD_TASK") - // Unique data to ensure the broadcast is fresh - data = Uri.parse("taskwarrior://addtask/$widgetId") - } - val pendingIntentAdd: PendingIntent = PendingIntent.getBroadcast( - context, - widgetId, - intent_for_add, - PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT - ) + val pendingIntentAdd: PendingIntent = HomeWidgetLaunchIntent.getActivity( + context, + MainActivity::class.java, + Uri.parse("taskwarrior://addclicked") + ) setOnClickPendingIntent(R.id.add_btn, pendingIntentAdd) // Attach the adapter to the ListView @@ -111,12 +102,11 @@ override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appW ).run { action = "TASK_ACTION" // Important: Use widgetId as requestCode to keep it unique - PendingIntent.getBroadcast( - context, - widgetId, - this, - PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT - ) + val clickPendingIntent: PendingIntent = HomeWidgetLaunchIntent.getActivity( + context, + MainActivity::class.java, + Uri.parse("taskwarrior://cardclicked") + ) } views.setPendingIntentTemplate(R.id.list_view, clickPendingIntent) diff --git a/lib/app/services/deep_link_service.dart b/lib/app/services/deep_link_service.dart index f016c93c..28a30ad7 100644 --- a/lib/app/services/deep_link_service.dart +++ b/lib/app/services/deep_link_service.dart @@ -15,8 +15,16 @@ class DeepLinkService extends GetxService { _initDeepLinks(); } - void _initDeepLinks() { + void _initDeepLinks() async { _appLinks = AppLinks(); + + // Cold start fix + final Uri? initialUri = await _appLinks.getInitialLink(); + if (initialUri != null) { + debugPrint('🔗 COLD START LINK: $initialUri'); + _handleWidgetUri(initialUri); + } + _appLinks.uriLinkStream.listen((uri) { debugPrint('🔗 LINK RECEIVED: $uri'); _handleWidgetUri(uri); From 4e92d2c4969ab247e096450947e93f0e465a6e42 Mon Sep 17 00:00:00 2001 From: PRINCE BHADANIA Date: Tue, 24 Feb 2026 22:08:38 +0530 Subject: [PATCH 10/12] Follow System Locale with Optional Override --- .../controllers/settings_controller.dart | 16 +++++++++++---- ...ngs_page_select_the_language_trailing.dart | 2 ++ lib/app/utils/app_settings/app_settings.dart | 9 +++++++-- .../utils/app_settings/selected_language.dart | 11 ++++++++++ .../utils/language/supported_language.dart | 13 ++++++++++++ lib/main.dart | 20 +++++++++++++++++-- pubspec.yaml | 2 ++ 7 files changed, 65 insertions(+), 8 deletions(-) diff --git a/lib/app/modules/settings/controllers/settings_controller.dart b/lib/app/modules/settings/controllers/settings_controller.dart index 8eceeb70..b5b9b437 100644 --- a/lib/app/modules/settings/controllers/settings_controller.dart +++ b/lib/app/modules/settings/controllers/settings_controller.dart @@ -29,10 +29,18 @@ class SettingsController extends GetxController { RxString baseDirectory = "".obs; void setSelectedLanguage(SupportedLanguage language) async { - await SelectedLanguage.saveSelectedLanguage(language); - selectedLanguage.value = language; - AppSettings.selectedLanguage = language; - Get.find().selectedLanguage.value = language; + if (language == SupportedLanguage.system) { + await SelectedLanguage.clearSelectedLanguage(); // clears prefs + selectedLanguage.value = SupportedLanguage.system; + AppSettings.selectedLanguage = SupportedLanguage.system; + Get.updateLocale(SupportedLanguageExtension.getSystemLanguage().toLocale()); + } else { + await SelectedLanguage.saveSelectedLanguage(language); + selectedLanguage.value = language; + AppSettings.selectedLanguage = language; + Get.updateLocale(Locale(language.languageCode)); + } + Get.find().selectedLanguage.value = selectedLanguage.value; } Future getBaseDirectory() async { diff --git a/lib/app/modules/settings/views/settings_page_select_the_language_trailing.dart b/lib/app/modules/settings/views/settings_page_select_the_language_trailing.dart index 7648f8aa..6f50f965 100644 --- a/lib/app/modules/settings/views/settings_page_select_the_language_trailing.dart +++ b/lib/app/modules/settings/views/settings_page_select_the_language_trailing.dart @@ -44,6 +44,8 @@ class SettingsPageSelectTheLanguageTrailing extends StatelessWidget { String _getLanguageName(SupportedLanguage language) { switch (language) { + case SupportedLanguage.system: + return 'Follow System Language'; case SupportedLanguage.english: return 'English'; case SupportedLanguage.hindi: diff --git a/lib/app/utils/app_settings/app_settings.dart b/lib/app/utils/app_settings/app_settings.dart index 335132ab..38215b3f 100644 --- a/lib/app/utils/app_settings/app_settings.dart +++ b/lib/app/utils/app_settings/app_settings.dart @@ -30,8 +30,6 @@ class AppSettings { } else { // If no explicit preference, use the system language (if supported) selectedLanguage = SupportedLanguageExtension.getSystemLanguage(); - // Save the system language as the user's preference - await SelectedLanguage.saveSelectedLanguage(selectedLanguage); } use24HourFormatRx.value = SelectedTimeFormat.getTimeFormat() ?? false; } @@ -42,4 +40,11 @@ class AppSettings { await SelectedLanguage.saveSelectedLanguage(language); await SelectedTimeFormat.saveTimeFormat(use24hour); } + + static Locale? get selectedLocale { + // If user explicitly saved a language, return it + String? saved = SelectedLanguage.getRawCode(); + if (saved == null || saved.isEmpty) return null; // null = follow system + return Locale(AppSettings.selectedLanguage.languageCode); + } } diff --git a/lib/app/utils/app_settings/selected_language.dart b/lib/app/utils/app_settings/selected_language.dart index aea3259a..2ce2fa89 100644 --- a/lib/app/utils/app_settings/selected_language.dart +++ b/lib/app/utils/app_settings/selected_language.dart @@ -8,6 +8,10 @@ class SelectedLanguage { } static Future saveSelectedLanguage(SupportedLanguage language) async { + if (language == SupportedLanguage.system) { + await _preferences?.remove('_selectedLanguage'); + return; + } await _preferences?.setString('_selectedLanguage', language.languageCode); } @@ -15,4 +19,11 @@ class SelectedLanguage { String? languageCode = _preferences?.getString('_selectedLanguage'); return SupportedLanguageExtension.fromCode(languageCode); } + + static String? getRawCode() { + return _preferences?.getString('_selectedLanguage'); + } + static Future clearSelectedLanguage() async { + await _preferences?.remove('_selectedLanguage'); +} } diff --git a/lib/app/utils/language/supported_language.dart b/lib/app/utils/language/supported_language.dart index 404f9553..9c7ef5a8 100644 --- a/lib/app/utils/language/supported_language.dart +++ b/lib/app/utils/language/supported_language.dart @@ -1,6 +1,7 @@ import 'package:flutter/widgets.dart'; enum SupportedLanguage { + system, english, hindi, marathi, @@ -12,6 +13,8 @@ enum SupportedLanguage { extension SupportedLanguageExtension on SupportedLanguage { String get languageCode { switch (this) { + case SupportedLanguage.system: + return ''; // empty = follow system case SupportedLanguage.english: return 'en'; case SupportedLanguage.hindi: @@ -31,6 +34,8 @@ extension SupportedLanguageExtension on SupportedLanguage { static SupportedLanguage? fromCode(String? code) { switch (code) { + case 'system': + return SupportedLanguage.system; case 'en': return SupportedLanguage.english; case 'hi': @@ -58,4 +63,12 @@ extension SupportedLanguageExtension on SupportedLanguage { // Return the supported language or default to English return supportedLanguage ?? SupportedLanguage.english; } + + Locale toLocale() { + if (this == SupportedLanguage.system || languageCode.isEmpty) { + return const Locale('en'); + } + return Locale(languageCode); + } + } diff --git a/lib/main.dart b/lib/main.dart index 09f0268c..83fbef66 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,8 @@ import 'dart:ffi'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; // ADD THIS import 'package:get/get.dart'; -// 1. Add this import import 'package:app_links/app_links.dart'; import 'package:taskwarrior/app/services/deep_link_service.dart'; @@ -51,6 +51,22 @@ void main() async { initialRoute: AppPages.INITIAL, getPages: AppPages.routes, themeMode: AppSettings.isDarkMode ? ThemeMode.dark : ThemeMode.light, + + // ADD THESE 3 PROPERTIES + locale: AppSettings.selectedLocale, // null = follow system + supportedLocales: const [ + Locale('en'), + Locale('hi'), + Locale('mr'), + Locale('fr'), + Locale('es'), + Locale('bn'), + ], + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], ), ); -} +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 12e80726..504235ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,8 @@ dependencies: flutter_rust_bridge: ^2.11.1 ffi: any # Required for FFI app_links: ^6.4.1 + flutter_localizations: + sdk: flutter dev_dependencies: build_runner: null From 1b649ea536de6569e1a61889533478d4beeb28d6 Mon Sep 17 00:00:00 2001 From: PRINCE BHADANIA Date: Thu, 26 Feb 2026 16:40:50 +0530 Subject: [PATCH 11/12] Fixes: Hide waiting tasks --- .../modules/home/controllers/home_controller.dart | 8 ++++++-- lib/app/v3/champion/models/task_for_replica.dart | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index dea84b13..dd01fd94 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -45,13 +45,14 @@ import 'package:textfield_tags/textfield_tags.dart'; import 'package:taskwarrior/app/utils/themes/theme_extension.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; +import 'package:taskwarrior/app/utils/language/sentence_manager.dart'; class HomeController extends GetxController { final SplashController splashController = Get.find(); late Storage storage; final RxBool taskServerBannerShown = false.obs; - final Sentences sentences = Sentences(); + late Sentences sentences; final RxBool pendingFilter = false.obs; final RxBool waitingFilter = false.obs; final RxBool hideBlocked = false.obs; @@ -82,6 +83,9 @@ class HomeController extends GetxController { @override void onInit() { super.onInit(); + sentences = SentenceManager( + currentLanguage: AppSettings.selectedLanguage, + ).sentences; storage = Storage( Directory( '${splashController.baseDirectory.value.path}/profiles/${splashController.currentProfile.value}', @@ -593,7 +597,7 @@ class HomeController extends GetxController { onPressed: () { messenger.hideCurrentMaterialBanner(); taskServerBannerShown.value = false; // ✅ RESET flag - Get.toNamed(Routes.TASKSERVER_SETUP), + Get.toNamed(Routes.MANAGE_TASK_SERVER); }, child: Text(sentences.homePageSetup), ), diff --git a/lib/app/v3/champion/models/task_for_replica.dart b/lib/app/v3/champion/models/task_for_replica.dart index daf22ca3..1f17a768 100644 --- a/lib/app/v3/champion/models/task_for_replica.dart +++ b/lib/app/v3/champion/models/task_for_replica.dart @@ -5,13 +5,13 @@ class TaskForReplica { final String? due; final String? start; final String? wait; - final String? status; final String? description; final List? tags; final String uuid; final String? priority; final String? project; + final List? depends; TaskForReplica({ this.modified, @@ -24,6 +24,7 @@ class TaskForReplica { required this.uuid, this.priority, this.project, + this.depends, }); factory TaskForReplica.fromJson(Map json) { @@ -38,6 +39,11 @@ class TaskForReplica { .toUtc() .toString() : null, + depends: (json['depends'] is List) + ? (json['depends'] as List).map((e) => e.toString()).toList() + : (json['depends'] is String) + ? json['depends'].toString().split(',') + : null, start: json['start'] != null ? DateTime.fromMillisecondsSinceEpoch( (int.tryParse(json['start'].toString()) ?? 0) * 1000, @@ -77,6 +83,7 @@ class TaskForReplica { 'uuid': uuid, if (priority != null) 'priority': priority, if (project != null) 'project': project, + if (depends != null) 'depends': depends, }; } @@ -90,6 +97,8 @@ class TaskForReplica { List? tags, String? uuid, String? priority, + String? project, + List? depends, }) { return TaskForReplica( modified: modified ?? this.modified, @@ -101,7 +110,8 @@ class TaskForReplica { tags: tags ?? this.tags, uuid: uuid ?? this.uuid, priority: priority ?? this.priority, - project: project ?? project, + project: project ?? this.project, + depends: depends ?? this.depends, ); } From e79b4b85aa8faad0d8c2713569066fdbe1048f4b Mon Sep 17 00:00:00 2001 From: PRINCE BHADANIA Date: Fri, 27 Feb 2026 22:37:57 +0530 Subject: [PATCH 12/12] fix: hide waiting tasks by default --- .../home/controllers/home_controller.dart | 20 +++++++++---------- lib/app/modules/home/views/tasks_builder.dart | 2 +- lib/app/utils/taskfunctions/query.dart | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index dd01fd94..a60aeaad 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -231,12 +231,7 @@ class HomeController extends GetxController { void _profileSet() { pendingFilter.value = Query(storage.tabs.tab()).getPendingFilter(); - if (!Query(storage.tabs.tab()).getWaitingFilter()) { - waitingFilter.value = Query(storage.tabs.tab()).getWaitingFilter(); - } else { - Query(storage.tabs.tab()).toggleWaitingFilter(); - waitingFilter.value = Query(storage.tabs.tab()).getWaitingFilter(); - } + waitingFilter.value = Query(storage.tabs.tab()).getWaitingFilter(); projectFilter.value = Query(storage.tabs.tab()).projectFilter(); tagUnion.value = Query(storage.tabs.tab()).tagUnion(); selectedSort.value = Query(storage.tabs.tab()).getSelectedSort(); @@ -268,7 +263,11 @@ class HomeController extends GetxController { .where((task) => task.status == 'pending') .toList(); } else { - queriedTasks.value = storage.data.pendingData(); + var currentTime = DateTime.now(); + queriedTasks.value = storage.data.pendingData().where((task) => + task.status != 'waiting' && + !(task.wait != null && task.wait!.isAfter(currentTime)) + ).toList(); } if (hideBlocked.value) { @@ -281,9 +280,10 @@ class HomeController extends GetxController { // Rest of the method stays the same... if (waitingFilter.value) { var currentTime = DateTime.now(); - queriedTasks.value = queriedTasks - .where((task) => task.wait != null && task.wait!.isAfter(currentTime)) - .toList(); + queriedTasks.value = storage.data.pendingData().where((task) => + task.status == 'waiting' || + (task.wait != null && task.wait!.isAfter(currentTime)) + ).toList(); } if (projectFilter.value.isNotEmpty) { diff --git a/lib/app/modules/home/views/tasks_builder.dart b/lib/app/modules/home/views/tasks_builder.dart index 54846126..9b0b2256 100644 --- a/lib/app/modules/home/views/tasks_builder.dart +++ b/lib/app/modules/home/views/tasks_builder.dart @@ -181,7 +181,7 @@ class TasksBuilder extends StatelessWidget { ? storageWidget.taskItemKey : ValueKey(task.uuid); - return pendingFilter + return (pendingFilter || waitingFilter) ? Slidable( key: itemKey, startActionPane: ActionPane( diff --git a/lib/app/utils/taskfunctions/query.dart b/lib/app/utils/taskfunctions/query.dart index 3040830c..de934b22 100644 --- a/lib/app/utils/taskfunctions/query.dart +++ b/lib/app/utils/taskfunctions/query.dart @@ -39,7 +39,7 @@ class Query { if (!_pendingFilter.existsSync()) { _pendingFilter ..createSync(recursive: true) - ..writeAsStringSync('true'); + ..writeAsStringSync('false'); } return json.decode(_pendingFilter.readAsStringSync()); } @@ -54,7 +54,7 @@ class Query { if (!_waitingFilter.existsSync()) { _waitingFilter ..createSync(recursive: true) - ..writeAsStringSync('true'); + ..writeAsStringSync('false'); } return json.decode(_waitingFilter.readAsStringSync()); }