diff --git a/lib/app/modules/detailRoute/controllers/detail_route_controller.dart b/lib/app/modules/detailRoute/controllers/detail_route_controller.dart index 3bc12109..85c3712c 100644 --- a/lib/app/modules/detailRoute/controllers/detail_route_controller.dart +++ b/lib/app/modules/detailRoute/controllers/detail_route_controller.dart @@ -15,6 +15,7 @@ class DetailRouteController extends GetxController { late String uuid; late Modify modify; var onEdit = false.obs; + var isReadOnly = false.obs; @override void onInit() { @@ -29,12 +30,26 @@ class DetailRouteController extends GetxController { uuid: uuid, ); initValues(); + + // Check if task is completed or deleted and set read-only state + isReadOnly.value = (modify.draft.status == 'completed' || + modify.draft.status == 'deleted'); } void setAttribute(String name, dynamic newValue) { + if (isReadOnly.value && name != 'status') { + return; + } + modify.set(name, newValue); onEdit.value = true; - if(name == 'start'){ + + // If status is being changed, update read-only state + if (name == 'status') { + isReadOnly.value = (newValue == 'completed' || newValue == 'deleted'); + } + + if (name == 'start') { debugPrint('Start Value Changed to $newValue'); startValue.value = newValue; } diff --git a/lib/app/modules/detailRoute/views/dateTimePicker.dart b/lib/app/modules/detailRoute/views/dateTimePicker.dart index 944c5c7a..72638629 100644 --- a/lib/app/modules/detailRoute/views/dateTimePicker.dart +++ b/lib/app/modules/detailRoute/views/dateTimePicker.dart @@ -15,6 +15,7 @@ class DateTimeWidget extends StatelessWidget { required this.value, required this.callback, required this.globalKey, + this.isEditable = true, }); final String name; @@ -22,15 +23,25 @@ class DateTimeWidget extends StatelessWidget { final dynamic value; final void Function(dynamic) callback; final GlobalKey globalKey; + final bool isEditable; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( key: globalKey, color: AppSettings.isDarkMode ? const Color.fromARGB(255, 57, 57, 57) : Colors.white, child: ListTile( + enabled: isEditable, textColor: AppSettings.isDarkMode ? Colors.white : const Color.fromARGB(255, 48, 46, 46), @@ -54,9 +65,7 @@ class DateTimeWidget extends StatelessWidget { fontFamily: FontFamily.poppins, fontWeight: TaskWarriorFonts.bold, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), TextSpan( @@ -70,9 +79,7 @@ class DateTimeWidget extends StatelessWidget { style: TextStyle( fontFamily: FontFamily.poppins, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), ], @@ -187,7 +194,6 @@ class DateTimeWidget extends StatelessWidget { } } }, - onLongPress: () => callback(null), ), ); @@ -199,20 +205,31 @@ class StartWidget extends StatelessWidget { required this.name, required this.value, required this.callback, + this.isEditable = true, super.key, }); final String name; final dynamic value; + final bool isEditable; final void Function(dynamic) callback; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( color: AppSettings.isDarkMode ? const Color.fromARGB(255, 57, 57, 57) : Colors.white, child: ListTile( + enabled: isEditable, textColor: AppSettings.isDarkMode ? Colors.white : const Color.fromARGB(255, 48, 46, 46), @@ -236,9 +253,7 @@ class StartWidget extends StatelessWidget { fontFamily: FontFamily.poppins, fontWeight: TaskWarriorFonts.bold, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), TextSpan( @@ -252,9 +267,7 @@ class StartWidget extends StatelessWidget { style: TextStyle( fontFamily: FontFamily.poppins, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), ], diff --git a/lib/app/modules/detailRoute/views/description_widget.dart b/lib/app/modules/detailRoute/views/description_widget.dart index e4018a75..d4ff520b 100644 --- a/lib/app/modules/detailRoute/views/description_widget.dart +++ b/lib/app/modules/detailRoute/views/description_widget.dart @@ -8,23 +8,35 @@ import 'package:taskwarrior/app/utils/gen/fonts.gen.dart'; import 'package:taskwarrior/app/utils/app_settings/app_settings.dart'; class DescriptionWidget extends StatelessWidget { - const DescriptionWidget( - {required this.name, - required this.value, - required this.callback, - super.key}); + const DescriptionWidget({ + required this.name, + required this.value, + required this.callback, + this.isEditable = true, + super.key, + }); final String name; final dynamic value; final void Function(dynamic) callback; + final bool isEditable; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( color: AppSettings.isDarkMode ? const Color.fromARGB(255, 57, 57, 57) : Colors.white, child: ListTile( + enabled: isEditable, textColor: AppSettings.isDarkMode ? Colors.white : const Color.fromARGB(255, 48, 46, 46), @@ -48,9 +60,7 @@ class DescriptionWidget extends StatelessWidget { fontFamily: FontFamily.poppins, fontWeight: TaskWarriorFonts.bold, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), TextSpan( @@ -64,9 +74,7 @@ class DescriptionWidget extends StatelessWidget { style: TextStyle( fontFamily: FontFamily.poppins, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), ], @@ -104,7 +112,6 @@ class DescriptionWidget extends StatelessWidget { actions: [ TextButton( onPressed: () { - // Navigator.of(context).pop(); Get.back(); }, child: Text( @@ -120,7 +127,6 @@ class DescriptionWidget extends StatelessWidget { onPressed: () { try { callback(controller.text); - // Navigator.of(context).pop(); Get.back(); } on FormatException catch (e, trace) { logError(e, trace); @@ -145,23 +151,35 @@ class DescriptionWidget extends StatelessWidget { } class ProjectWidget extends StatelessWidget { - const ProjectWidget( - {required this.name, - required this.value, - required this.callback, - super.key}); + const ProjectWidget({ + required this.name, + required this.value, + required this.callback, + this.isEditable = true, + super.key, + }); final String name; final dynamic value; final void Function(dynamic) callback; + final bool isEditable; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( color: AppSettings.isDarkMode ? const Color.fromARGB(255, 57, 57, 57) : Colors.white, child: ListTile( + enabled: isEditable, textColor: AppSettings.isDarkMode ? Colors.white : const Color.fromARGB(255, 48, 46, 46), @@ -185,9 +203,7 @@ class ProjectWidget extends StatelessWidget { fontFamily: FontFamily.poppins, fontWeight: TaskWarriorFonts.bold, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), TextSpan( @@ -201,9 +217,7 @@ class ProjectWidget extends StatelessWidget { style: TextStyle( fontFamily: FontFamily.poppins, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), ], @@ -241,7 +255,6 @@ class ProjectWidget extends StatelessWidget { actions: [ TextButton( onPressed: () { - // Navigator.of(context).pop(); Get.back(); }, child: Text( @@ -258,7 +271,6 @@ class ProjectWidget extends StatelessWidget { try { callback( (controller.text == '') ? null : controller.text); - // Navigator.of(context).pop(); Get.back(); } on FormatException catch (e, trace) { logError(e, trace); diff --git a/lib/app/modules/detailRoute/views/detail_route_view.dart b/lib/app/modules/detailRoute/views/detail_route_view.dart index 478da44f..02814081 100644 --- a/lib/app/modules/detailRoute/views/detail_route_view.dart +++ b/lib/app/modules/detailRoute/views/detail_route_view.dart @@ -252,12 +252,19 @@ class AttributeWidget extends StatelessWidget { ? DateFormat.yMEd().add_jms().format(value.toLocal()) : ((value is BuiltList) ? (value).toBuilder() : value); + // Get the controller to check if the task is read-only + final DetailRouteController controller = Get.find(); + + // Always allow status to be edited, but respect read-only for other attributes + final bool isEditable = !controller.isReadOnly.value || name == 'status'; + switch (name) { case 'description': return DescriptionWidget( name: name, value: localValue, callback: callback, + isEditable: isEditable, ); case 'status': return StatusWidget( @@ -270,6 +277,7 @@ class AttributeWidget extends StatelessWidget { name: name, value: localValue, callback: callback, + isEditable: isEditable, ); case 'due': return DateTimeWidget( @@ -277,6 +285,7 @@ class AttributeWidget extends StatelessWidget { value: localValue, callback: callback, globalKey: dueKey, + isEditable: isEditable, ); case 'wait': return DateTimeWidget( @@ -284,6 +293,7 @@ class AttributeWidget extends StatelessWidget { value: localValue, callback: callback, globalKey: waitKey, + isEditable: isEditable, ); case 'until': return DateTimeWidget( @@ -291,6 +301,7 @@ class AttributeWidget extends StatelessWidget { value: localValue, callback: callback, globalKey: untilKey, + isEditable: isEditable, ); case 'priority': return PriorityWidget( @@ -298,20 +309,27 @@ class AttributeWidget extends StatelessWidget { value: localValue, callback: callback, globalKey: priorityKey, + isEditable: isEditable, ); case 'project': return ProjectWidget( name: name, value: localValue, callback: callback, + isEditable: isEditable, ); case 'tags': return TagsWidget( name: name, value: localValue, callback: callback, + isEditable: isEditable, ); default: + final Color textColor = (isEditable && !['entry', 'modified', 'urgency'].contains(name)) + ? (AppSettings.isDarkMode ? TaskWarriorColors.white : TaskWarriorColors.black) + : (AppSettings.isDarkMode ? TaskWarriorColors.grey : TaskWarriorColors.grey); + return Card( color: AppSettings.isDarkMode ? TaskWarriorColors.ksecondaryBackgroundColor @@ -327,17 +345,13 @@ class AttributeWidget extends StatelessWidget { Text( '$name:'.padRight(13), style: TextStyle( - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), Text( localValue?.toString() ?? "not selected", style: TextStyle( - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, + color: textColor, ), ), ], @@ -347,75 +361,4 @@ class AttributeWidget extends StatelessWidget { ); } } -} - -class TagsWidget extends StatelessWidget { - const TagsWidget({ - required this.name, - required this.value, - required this.callback, - super.key, - }); - - final String name; - final dynamic value; - final void Function(dynamic) callback; - @override - Widget build(BuildContext context) { - return Card( - color: AppSettings.isDarkMode - ? TaskWarriorColors.ksecondaryBackgroundColor - : TaskWarriorColors.kLightSecondaryBackgroundColor, - child: ListTile( - textColor: AppSettings.isDarkMode - ? TaskWarriorColors.kprimaryTextColor - : TaskWarriorColors.ksecondaryTextColor, - title: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - RichText( - text: TextSpan( - children: [ - TextSpan( - text: '$name:'.padRight(13), - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, - ) - // style: GoogleFonts.poppins( - // fontWeight: TaskWarriorFonts.bold, - // fontSize: TaskWarriorFonts.fontSizeMedium, - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.white - // : TaskWarriorColors.black, - // ), - ), - TextSpan( - text: - '${(value as ListBuilder?)?.build() ?? 'not selected'}', - style: TextStyle( - color: AppSettings.isDarkMode - ? TaskWarriorColors.white - : TaskWarriorColors.black, - ), - ), - ], - ), - ), - ], - ), - ), - onTap: () => Get.to( - TagsRoute( - value: value, - callback: callback, - ), - ), - ), - ); - } -} +} \ No newline at end of file diff --git a/lib/app/modules/detailRoute/views/priority_widget.dart b/lib/app/modules/detailRoute/views/priority_widget.dart index 945afec1..176cb31b 100644 --- a/lib/app/modules/detailRoute/views/priority_widget.dart +++ b/lib/app/modules/detailRoute/views/priority_widget.dart @@ -4,26 +4,38 @@ import 'package:taskwarrior/app/utils/constants/constants.dart'; import 'package:taskwarrior/app/utils/app_settings/app_settings.dart'; class PriorityWidget extends StatelessWidget { - const PriorityWidget( - {required this.name, - required this.value, - required this.callback, - required this.globalKey, - super.key}); + const PriorityWidget({ + required this.name, + required this.value, + required this.callback, + required this.globalKey, + this.isEditable = true, + super.key, + }); final String name; final dynamic value; final void Function(dynamic) callback; final GlobalKey globalKey; + final bool isEditable; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( key: globalKey, color: AppSettings.isDarkMode ? const Color.fromARGB(255, 57, 57, 57) : Colors.white, child: ListTile( + enabled: isEditable, textColor: AppSettings.isDarkMode ? Colors.white : const Color.fromARGB(255, 48, 46, 46), @@ -39,18 +51,14 @@ class PriorityWidget extends StatelessWidget { style: GoogleFonts.poppins( fontWeight: TaskWarriorFonts.bold, fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? Colors.white - : Colors.black, + color: textColor, ), ), TextSpan( text: value ?? "not selected", style: GoogleFonts.poppins( fontSize: TaskWarriorFonts.fontSizeMedium, - color: AppSettings.isDarkMode - ? Colors.white - : Colors.black, + color: textColor, ), ), ], diff --git a/lib/app/modules/detailRoute/views/tags_widget.dart b/lib/app/modules/detailRoute/views/tags_widget.dart index c4906d59..3d3f41d6 100644 --- a/lib/app/modules/detailRoute/views/tags_widget.dart +++ b/lib/app/modules/detailRoute/views/tags_widget.dart @@ -18,20 +18,31 @@ class TagsWidget extends StatelessWidget { required this.name, required this.value, required this.callback, + this.isEditable = true, super.key, }); final String name; final dynamic value; final void Function(dynamic) callback; + final bool isEditable; @override Widget build(BuildContext context) { + final Color textColor = isEditable + ? (AppSettings.isDarkMode + ? TaskWarriorColors.white + : TaskWarriorColors.black) + : (AppSettings.isDarkMode + ? TaskWarriorColors.grey + : TaskWarriorColors.grey); + return Card( + color: AppSettings.isDarkMode + ? const Color.fromARGB(255, 55, 54, 54) + : TaskWarriorColors.white, child: ListTile( - tileColor: AppSettings.isDarkMode - ? const Color.fromARGB(255, 55, 54, 54) - : TaskWarriorColors.white, + enabled: isEditable, textColor: AppSettings.isDarkMode ? TaskWarriorColors.white : const Color.fromARGB(255, 48, 46, 46), @@ -41,17 +52,17 @@ class TagsWidget extends StatelessWidget { children: [ Text( '${'$name:'.padRight(13)}${(value as ListBuilder?)?.build()}', + style: TextStyle( + color: textColor, + ), ), ], ), ), - onTap: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TagsRoute( - value: value, - callback: callback, - ), + onTap: () => Get.to( + TagsRoute( + value: value, + callback: callback, ), ), ),