diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 23749b75..8dc54eeb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -360,6 +360,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 8FEC10D1539C672E7E2B68F4 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/lib/app/modules/detailRoute/controllers/detail_route_controller.dart b/lib/app/modules/detailRoute/controllers/detail_route_controller.dart index 8b65bc1c..5e35ac08 100644 --- a/lib/app/modules/detailRoute/controllers/detail_route_controller.dart +++ b/lib/app/modules/detailRoute/controllers/detail_route_controller.dart @@ -16,6 +16,7 @@ class DetailRouteController extends GetxController { late String uuid; late Modify modify; var onEdit = false.obs; + var isTourActive = false.obs; var isReadOnly = false.obs; // Description Edit State @@ -101,7 +102,7 @@ class DetailRouteController extends GetxController { ); // Navigate back immediately after showing snackbar - Get.back(); + Get.back(result: true); } // 'description': controller.modify.draft.description, @@ -182,6 +183,7 @@ class DetailRouteController extends GetxController { opacityShadow: 1.00, hideSkip: true, onFinish: () { + isTourActive.value = false; SaveTourStatus.saveDetailsTourStatus(true); }, ); @@ -191,9 +193,16 @@ class DetailRouteController extends GetxController { Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getDetailsTourStatus().then((value) => { - if (!value) {tutorialCoachMark.show(context: context)} - }); + SaveTourStatus.getDetailsTourStatus().then((value) { + if (!value) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } + }); }, ); } diff --git a/lib/app/modules/detailRoute/views/detail_route_view.dart b/lib/app/modules/detailRoute/views/detail_route_view.dart index f62c48a7..412ca5e7 100644 --- a/lib/app/modules/detailRoute/views/detail_route_view.dart +++ b/lib/app/modules/detailRoute/views/detail_route_view.dart @@ -25,98 +25,95 @@ class DetailRouteView extends GetView { controller.showDetailsPageTour(context); TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return WillPopScope( - onWillPop: () async { + return PopScope( + canPop: false, + onPopInvoked: (didPop) async { + if (didPop) return; + + if (controller.isTourActive.value) { + return; + } + if (!controller.onEdit.value) { debugPrint( 'DetailRouteView: No edits made, navigating back without prompt.'); // Get.offAll(() => const HomeView()); Navigator.of(context).pop(); - // Get.toNamed(Routes.HOME); - return false; + return; } debugPrint( 'DetailRouteView: Unsaved edits detected, prompting user for action.'); - bool? save = await showDialog( - context: context, - builder: (context) { - return AlertDialog( - backgroundColor: tColors.dialogBackgroundColor, - title: Text( - SentenceManager(currentLanguage: AppSettings.selectedLanguage) - .sentences - .saveChangesConfirmation, - style: TextStyle( - color: tColors.primaryTextColor, - ), + bool? done = await Get.dialog( + AlertDialog( + backgroundColor: tColors.dialogBackgroundColor, + title: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .saveChangesConfirmation, + style: TextStyle( + color: tColors.primaryTextColor, ), - actions: [ - // YES → save and pop - TextButton( - onPressed: () { - // Get.back(); // Close the dialog first - // // Wait for dialog to fully close before showing snackbar - // Future.delayed(const Duration(milliseconds: 100), () { - // controller.saveChanges(); - // }); - - controller.saveChanges(); - Navigator.of(context).pop(true); - }, - child: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .yes, - style: TextStyle( - color: tColors.primaryTextColor, - ), + ), + actions: [ + TextButton( + onPressed: () { + controller.saveChanges(); + Navigator.of(context).pop(false); + }, + child: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .yes, + style: TextStyle( + color: tColors.primaryTextColor, ), ), - - // NO → discard and pop - TextButton( - onPressed: () { - // Get.offAll(() => const HomeView()); - Navigator.of(context).pop(false); - }, - child: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .no, - style: TextStyle( - color: tColors.primaryTextColor, - ), + ), + TextButton( + onPressed: () { + Get.back(result: true); + controller.onEdit.value = false; + }, + child: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .no, + style: TextStyle( + color: tColors.primaryTextColor, ), ), - - // CANCEL → stay on page - TextButton( - onPressed: () { - Navigator.of(context).pop(null); - }, - child: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .cancel, - style: TextStyle( - color: tColors.primaryTextColor, - ), + ), + TextButton( + onPressed: () { + Get.back(result: false); + }, + child: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .cancel, + style: TextStyle( + color: tColors.primaryTextColor, ), ), - ], - ); - }, + ), + ], + ), + barrierDismissible: false, ); - if (save == null) { - // Cancel → stay - return false; + //runs when 'yes' or 'no' is clicked + if (done == true) { + Get.back(); + // only runs when 'yes' is clicked + if (controller.onEdit.value == true) { + controller.onEdit.value = false; + Get.snackbar( + 'Task Updated', + '', + snackPosition: SnackPosition.BOTTOM, + ); + } } - // Yes (true) or No (false) → both allow popping the screen - return true; }, child: Scaffold( backgroundColor: tColors.primaryBackgroundColor, @@ -172,65 +169,62 @@ class DetailRouteView extends GetView { splashColor: tColors.primaryTextColor, heroTag: "btn1", onPressed: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - scrollable: true, - title: Text( - '${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.reviewChanges}:', + Get.dialog( + AlertDialog( + scrollable: true, + title: Text( + '${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.reviewChanges}:', + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + content: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Text( + controller.modify.changes.entries + .map((entry) => '${entry.key}:\n' + ' ${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.oldChanges}: ${entry.value['old']}\n' + ' ${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.newChanges}: ${entry.value['new']}') + .toList() + .join('\n'), style: TextStyle( color: tColors.primaryTextColor, ), ), - content: SingleChildScrollView( - scrollDirection: Axis.horizontal, + ), + actions: [ + TextButton( + onPressed: () { + Get.back(); + }, child: Text( - controller.modify.changes.entries - .map((entry) => '${entry.key}:\n' - ' ${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.oldChanges}: ${entry.value['old']}\n' - ' ${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.newChanges}: ${entry.value['new']}') - .toList() - .join('\n'), + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .cancel, style: TextStyle( color: tColors.primaryTextColor, ), ), ), - actions: [ - TextButton( - onPressed: () { - Get.back(); - }, - child: Text( - SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .cancel, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - ), - TextButton( - onPressed: () { - controller.saveChanges(); - }, - child: Text( - SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .submit, - style: TextStyle( - color: tColors.primaryBackgroundColor, - ), + ElevatedButton( + onPressed: () { + controller.saveChanges(); + }, + child: Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .submit, + style: TextStyle( + color: tColors.primaryBackgroundColor, ), ), - ], - ); - }, + ), + ], + ), ); }, child: const Icon(Icons.save), diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index a7b6d353..991276cd 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -70,6 +70,8 @@ class HomeController extends GetxController { var tasks = [].obs; var tasksFromReplica = [].obs; final RxBool isRefreshing = false.obs; + final RxBool isFilterTourActive = false.obs; + final RxBool isHomeTourActive = false.obs; @override void onInit() { @@ -684,6 +686,7 @@ class HomeController extends GetxController { opacityShadow: 0.8, hideSkip: true, onFinish: () { + isHomeTourActive.value = false; SaveTourStatus.saveInAppTourStatus(true); }); } @@ -692,18 +695,19 @@ class HomeController extends GetxController { Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getInAppTourStatus().then((value) => { - if (value == false) - { - tutorialCoachMark.show(context: context), - } - else - { - // ignore: avoid_print - debugPrint('User has seen this page'), - // User has seen this page - } - }); + SaveTourStatus.getInAppTourStatus().then((value) { + if (value == false) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isHomeTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } else { + // ignore: avoid_print + debugPrint('User has seen this page'); + } + }); }, ); } @@ -728,6 +732,7 @@ class HomeController extends GetxController { opacityShadow: 1.00, hideSkip: true, onFinish: () { + isFilterTourActive.value = false; SaveTourStatus.saveFilterTourStatus(true); }, ); @@ -737,17 +742,19 @@ class HomeController extends GetxController { Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getFilterTourStatus().then((value) => { - if (value == false) - { - tutorialCoachMark.show(context: context), - } - else - { - // ignore: avoid_print - print('User has seen this page'), - } - }); + SaveTourStatus.getFilterTourStatus().then((value) { + if (value == false) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isFilterTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } else { + // ignore: avoid_print + print('User has seen this page'); + } + }); }, ); } @@ -773,7 +780,11 @@ class HomeController extends GetxController { print("tasks is ${tasks.isNotEmpty}"); if (value == false) { initTaskSwipeTutorial(); - tutorialCoachMark.show(context: context); + tutorialCoachMark.targets + .removeWhere((target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + tutorialCoachMark.show(context: context); + } } else { debugPrint('User has already seen the task swipe tutorial'); } 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..12d867ab 100644 --- a/lib/app/modules/home/views/filter_drawer_home_page.dart +++ b/lib/app/modules/home/views/filter_drawer_home_page.dart @@ -1,7 +1,7 @@ // ignore_for_file: unrelated_type_equality_checks import 'package:flutter/material.dart'; -import 'package:get/get_state_manager/get_state_manager.dart'; +import 'package:get/get.dart'; import 'package:taskwarrior/app/models/filters.dart'; import 'package:taskwarrior/app/modules/home/controllers/home_controller.dart'; import 'package:taskwarrior/app/modules/home/views/project_column_home_page.dart'; @@ -29,432 +29,455 @@ class FilterDrawer extends StatelessWidget { var tileColor = AppSettings.isDarkMode ? TaskWarriorColors.ksecondaryBackgroundColor : TaskWarriorColors.kLightPrimaryBackgroundColor; - return Drawer( - backgroundColor: tColors.dialogBackgroundColor, - surfaceTintColor: tColors.primaryBackgroundColor, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.all(8), - child: ListView( - primary: false, - key: const PageStorageKey('tags-filter'), - children: [ - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Container( - height: 45, - alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 0.0), - child: Text( - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerApplyFilters, - // style: GoogleFonts.poppins( - // fontWeight: TaskWarriorFonts.bold, - // color: (AppSettings.isDarkMode - // ? TaskWarriorColors.kprimaryTextColor - // : TaskWarriorColors.kLightPrimaryTextColor), - // fontSize: TaskWarriorFonts.fontSizeExtraLarge), - style: TextStyle( - fontFamily: FontFamily.poppins, - fontWeight: TaskWarriorFonts.bold, - color: tColors.primaryTextColor, - fontSize: TaskWarriorFonts.fontSizeExtraLarge, - ), - ), - ), - ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Container( - // width: MediaQuery.of(context).size.width * 1, - // padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: TaskWarriorColors.borderColor), - ), - child: ListTile( - contentPadding: const EdgeInsets.only( - left: 8, + return Obx(() => PopScope( + canPop: !homeController.isFilterTourActive.value, + onPopInvokedWithResult: (didPop, result) async { + if (homeController.isFilterTourActive.value) { + Get.closeAllSnackbars(); + Get.snackbar( + 'Tour Active', + 'Please complete the tour before navigating back.', + snackPosition: SnackPosition.BOTTOM, + ); + return; + } + }, + child: Drawer( + backgroundColor: tColors.dialogBackgroundColor, + surfaceTintColor: tColors.primaryBackgroundColor, + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(8), + child: ListView( + primary: false, + key: const PageStorageKey('tags-filter'), + children: [ + const Divider( + color: Color.fromARGB(0, 48, 46, 46), ), - title: RichText( - key: homeController.statusKey, - maxLines: 2, - text: TextSpan( - children: [ - TextSpan( - text: - '${SentenceManager(currentLanguage: homeController.selectedLanguage.value).sentences.filterDrawerStatus} : ', - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - )), - TextSpan( - text: filters.pendingFilter - ? SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerPending - : SentenceManager( - currentLanguage: homeController - .selectedLanguage.value) - .sentences - .filterDrawerCompleted, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - )), - ], + Container( + height: 45, + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 0.0), + child: Text( + SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerApplyFilters, + // style: GoogleFonts.poppins( + // fontWeight: TaskWarriorFonts.bold, + // color: (AppSettings.isDarkMode + // ? TaskWarriorColors.kprimaryTextColor + // : TaskWarriorColors.kLightPrimaryTextColor), + // fontSize: TaskWarriorFonts.fontSizeExtraLarge), + style: TextStyle( + fontFamily: FontFamily.poppins, + fontWeight: TaskWarriorFonts.bold, + color: tColors.primaryTextColor, + fontSize: TaskWarriorFonts.fontSizeExtraLarge, + ), + ), ), ), - onTap: filters.togglePendingFilter, - textColor: tColors.primaryTextColor, - ), - ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Visibility( - visible: !homeController.taskReplica.value, - child: Container( - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: TaskWarriorColors.borderColor), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - 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, - )), - Switch( - value: filters.waitingFilter, - onChanged: (_) => filters.toggleWaitingFilter(), - ) - ], + Container( + // width: MediaQuery.of(context).size.width * 1, + // padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: TaskWarriorColors.borderColor), ), - ), - ), - ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Visibility( - visible: !homeController.taskchampion.value && - !homeController.taskReplica.value, - child: Container( - key: homeController.projectsKey, - width: MediaQuery.of(context).size.width * 1, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: TaskWarriorColors.borderColor, + child: ListTile( + contentPadding: const EdgeInsets.only( + left: 8, + ), + title: RichText( + key: homeController.statusKey, + maxLines: 2, + text: TextSpan( + children: [ + TextSpan( + text: + '${SentenceManager(currentLanguage: homeController.selectedLanguage.value).sentences.filterDrawerStatus} : ', + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + )), + TextSpan( + text: filters.pendingFilter + ? SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerPending + : SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerCompleted, + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + )), + ], + ), + ), + onTap: filters.togglePendingFilter, + textColor: AppSettings.isDarkMode + ? TaskWarriorColors.kprimaryTextColor + : TaskWarriorColors.kLightSecondaryTextColor, ), ), - child: ProjectsColumn( - projects: filters.projects, - projectFilter: filters.projectFilter, - callback: filters.toggleProjectFilter, - ), - ), - ), - Visibility( - visible: homeController.taskchampion.value || - homeController.taskReplica.value, - child: FutureBuilder>( - future: homeController.getUniqueProjects(), - builder: (BuildContext context, - AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - return Container( - key: homeController.projectsKeyTaskc, - width: MediaQuery.of(context).size.width * 1, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: - Border.all(color: TaskWarriorColors.borderColor), - ), - child: ProjectColumnTaskc( - callback: filters.toggleProjectFilter, - projects: snapshot.data!, - projectFilter: filters.projectFilter, - ), - ); - } else { - return Center( - child: Text(SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerNoProjectsAvailable)); - } - }, - ), - ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Visibility( - visible: !homeController.taskchampion.value && - !homeController.taskReplica.value, - child: Container( - key: homeController.filterTagKey, - width: MediaQuery.of(context).size.width * 1, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: TaskWarriorColors.borderColor), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Divider( - color: Color.fromARGB(0, 48, 46, 46), + Visibility( + visible: !homeController.taskReplica.value, + child: Container( + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: + Border.all(color: TaskWarriorColors.borderColor), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 0.0), - child: Text( - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerFilterTagBy, - // style: GoogleFonts.poppins( - // color: (AppSettings.isDarkMode - // ? TaskWarriorColors.kprimaryTextColor - // : TaskWarriorColors.kLightSecondaryTextColor), - // // - // fontSize: TaskWarriorFonts.fontSizeLarge), - //textAlign: TextAlign.right, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + 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, + )), + Switch( + value: filters.waitingFilter, + onChanged: (_) => filters.toggleWaitingFilter(), + ) + ], ), ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: TagFiltersWrap(filters.tagFilters), + ), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Visibility( + visible: !homeController.taskchampion.value && + !homeController.taskReplica.value, + child: Container( + key: homeController.projectsKey, + width: MediaQuery.of(context).size.width * 1, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: TaskWarriorColors.borderColor, + ), ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), + child: ProjectsColumn( + projects: filters.projects, + projectFilter: filters.projectFilter, + callback: filters.toggleProjectFilter, ), - ], - ), - ), - ), - Visibility( - visible: !homeController.taskchampion.value && - !homeController.taskReplica.value, - child: const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - ), - Container( - key: homeController.sortByKey, - width: MediaQuery.of(context).size.width * 1, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: TaskWarriorColors.borderColor), - ), - //height: 30, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Divider( - color: Color.fromARGB(0, 48, 46, 46), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 0.0), - child: Text( - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerSortBy, - // style: GoogleFonts.poppins( - // color: (AppSettings.isDarkMode - // ? TaskWarriorColors.kprimaryTextColor - // : TaskWarriorColors.kLightPrimaryTextColor), - // fontSize: TaskWarriorFonts.fontSizeLarge), - // textAlign: TextAlign.right, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - )), ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), + ), + Visibility( + visible: homeController.taskchampion.value || + homeController.taskReplica.value, + child: FutureBuilder>( + future: homeController.getUniqueProjects(), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + return Container( + key: homeController.projectsKeyTaskc, + width: MediaQuery.of(context).size.width * 1, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: TaskWarriorColors.borderColor), + ), + child: ProjectColumnTaskc( + callback: filters.toggleProjectFilter, + projects: snapshot.data!, + projectFilter: filters.projectFilter, + ), + ); + } else { + return Center( + child: Text(SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerNoProjectsAvailable)); + } + }, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Wrap( - spacing: 8, - runSpacing: 4, + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Visibility( + visible: !homeController.taskchampion.value && + !homeController.taskReplica.value, + child: Container( + key: homeController.filterTagKey, + width: MediaQuery.of(context).size.width * 1, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: + Border.all(color: TaskWarriorColors.borderColor), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - for (var sort in [ - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerCreated, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerModified, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerStartTime, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerDueTill, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerPriority, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerProject, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerTags, - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerUrgency, - ]) - Obx( - () => ChoiceChip( - label: (homeController.selectedSort.value - .startsWith(sort)) - ? Text( - homeController.selectedSort.value, - ) - : Text(sort), - selected: false, - onSelected: (_) { - if (homeController.selectedSort == '$sort+') { - homeController.selectSort('$sort-'); - } else if (homeController.selectedSort == - '$sort-') { - homeController.selectSort(sort); - } else { - homeController.selectSort('$sort+'); - } - }, - // labelStyle: GoogleFonts.poppins( - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.black - // : TaskWarriorColors.white), - // backgroundColor: AppSettings.isDarkMode - // ? TaskWarriorColors - // .kLightSecondaryBackgroundColor - // : TaskWarriorColors.ksecondaryBackgroundColor, + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 0.0), + child: Text( + SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerFilterTagBy, + // style: GoogleFonts.poppins( + // color: (AppSettings.isDarkMode + // ? TaskWarriorColors.kprimaryTextColor + // : TaskWarriorColors.kLightSecondaryTextColor), + // // + // fontSize: TaskWarriorFonts.fontSizeLarge), + //textAlign: TextAlign.right, + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, ), - ) + ), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8.0), + child: TagFiltersWrap(filters.tagFilters), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), ], ), ), - const Divider( + ), + Visibility( + visible: !homeController.taskchampion.value && + !homeController.taskReplica.value, + child: const Divider( color: Color.fromARGB(0, 48, 46, 46), ), - Container( - width: 200, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.kLightSecondaryBackgroundColor - // : TaskWarriorColors.ksecondaryBackgroundColor, - ), - child: TextButton( - onPressed: () { - if (homeController.selectedSort.value.endsWith('+') || - homeController.selectedSort.value.endsWith('-')) { - homeController.selectSort( - homeController.selectedSort.value.substring( - 0, - homeController.selectedSort.value.length - - 1)); - } - }, - child: Text( - SentenceManager( - currentLanguage: - homeController.selectedLanguage.value) - .sentences - .filterDrawerResetSort, - // style: GoogleFonts.poppins( - // fontSize: TaskWarriorFonts.fontSizeMedium, - // color: AppSettings.isDarkMode - // ? TaskWarriorColors.kLightSecondaryTextColor - // : TaskWarriorColors.ksecondaryTextColor), - style: TextStyle( - fontFamily: FontFamily.poppins, - fontSize: TaskWarriorFonts.fontSizeMedium, - color: tColors.primaryTextColor, - )), - ), + ), + Container( + key: homeController.sortByKey, + width: MediaQuery.of(context).size.width * 1, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: TaskWarriorColors.borderColor), ), - const Divider( - color: Color.fromARGB(0, 48, 46, 46), + //height: 30, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0.0), + child: Text( + SentenceManager( + currentLanguage: + homeController.selectedLanguage.value) + .sentences + .filterDrawerSortBy, + // style: GoogleFonts.poppins( + // color: (AppSettings.isDarkMode + // ? TaskWarriorColors.kprimaryTextColor + // : TaskWarriorColors.kLightPrimaryTextColor), + // fontSize: TaskWarriorFonts.fontSizeLarge), + // textAlign: TextAlign.right, + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + )), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Wrap( + spacing: 8, + runSpacing: 4, + children: [ + for (var sort in [ + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerCreated, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerModified, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerStartTime, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerDueTill, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerPriority, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerProject, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerTags, + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerUrgency, + ]) + Obx( + () => ChoiceChip( + label: (homeController.selectedSort.value + .startsWith(sort)) + ? Text( + homeController.selectedSort.value, + ) + : Text(sort), + selected: false, + onSelected: (_) { + if (homeController.selectedSort == + '$sort+') { + homeController.selectSort('$sort-'); + } else if (homeController.selectedSort == + '$sort-') { + homeController.selectSort(sort); + } else { + homeController.selectSort('$sort+'); + } + }, + // labelStyle: GoogleFonts.poppins( + // color: AppSettings.isDarkMode + // ? TaskWarriorColors.black + // : TaskWarriorColors.white), + // backgroundColor: AppSettings.isDarkMode + // ? TaskWarriorColors + // .kLightSecondaryBackgroundColor + // : TaskWarriorColors.ksecondaryBackgroundColor, + ), + ) + ], + ), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + Container( + width: 200, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + // color: AppSettings.isDarkMode + // ? TaskWarriorColors.kLightSecondaryBackgroundColor + // : TaskWarriorColors.ksecondaryBackgroundColor, + ), + child: TextButton( + onPressed: () { + if (homeController.selectedSort.value + .endsWith('+') || + homeController.selectedSort.value + .endsWith('-')) { + homeController.selectSort( + homeController.selectedSort.value.substring( + 0, + homeController + .selectedSort.value.length - + 1)); + } + }, + child: Text( + SentenceManager( + currentLanguage: homeController + .selectedLanguage.value) + .sentences + .filterDrawerResetSort, + // style: GoogleFonts.poppins( + // fontSize: TaskWarriorFonts.fontSizeMedium, + // color: AppSettings.isDarkMode + // ? TaskWarriorColors.kLightSecondaryTextColor + // : TaskWarriorColors.ksecondaryTextColor), + style: TextStyle( + fontFamily: FontFamily.poppins, + fontSize: TaskWarriorFonts.fontSizeMedium, + color: tColors.primaryTextColor, + )), + ), + ), + const Divider( + color: Color.fromARGB(0, 48, 46, 46), + ), + ], ), - ], - ), - ) - ], + ) + ], + ), + ), ), - ), - ), - ); + ))); } } diff --git a/lib/app/modules/home/views/home_page_body.dart b/lib/app/modules/home/views/home_page_body.dart index a409e8ee..e03363d1 100644 --- a/lib/app/modules/home/views/home_page_body.dart +++ b/lib/app/modules/home/views/home_page_body.dart @@ -1,5 +1,7 @@ -import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + import 'package:get/get.dart'; import 'package:taskwarrior/app/modules/home/views/show_tasks.dart'; import 'package:taskwarrior/app/modules/home/views/show_tasks_replica.dart'; @@ -9,138 +11,180 @@ import 'package:taskwarrior/app/utils/themes/theme_extension.dart'; import 'package:taskwarrior/app/utils/language/sentence_manager.dart'; import '../controllers/home_controller.dart'; -class HomePageBody extends StatelessWidget { +class HomePageBody extends StatefulWidget { final HomeController controller; const HomePageBody({required this.controller, super.key}); + @override + State createState() => _HomePageBodyState(); +} + +class _HomePageBodyState extends State { + DateTime? _lastBackPressTime; + Timer? _backPressTimer; + + @override + void dispose() { + _backPressTimer?.cancel(); + super.dispose(); + } + @override Widget build(BuildContext context) { - controller.initInAppTour(); - controller.showInAppTour(context); + widget.controller.initInAppTour(); + widget.controller.showInAppTour(context); TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return DoubleBackToCloseApp( - snackBar: SnackBar( - content: Text(SentenceManager( - currentLanguage: controller.selectedLanguage.value) - .sentences - .homePageTapBackToExit)), - child: Container( - color: tColors.dialogBackgroundColor, - child: Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: Obx( - () => Column( - children: [ - if (controller.searchVisible.value) - Container( - margin: const EdgeInsets.symmetric( - horizontal: 10, vertical: 10), - child: SearchBar( - backgroundColor: WidgetStateProperty.all( - (tColors.primaryBackgroundColor!)), - surfaceTintColor: WidgetStateProperty.all( - (tColors.primaryBackgroundColor!)), - controller: controller.searchController, - // shape:, - onChanged: (value) { - controller.search(value); - }, + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) async { + if (widget.controller.isHomeTourActive.value) { + return; + } + + final now = DateTime.now(); + if (_lastBackPressTime != null && + now.difference(_lastBackPressTime!) <= + const Duration(seconds: 2)) { + _backPressTimer?.cancel(); + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + return; + } else { + _lastBackPressTime = now; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(SentenceManager( + currentLanguage: widget.controller.selectedLanguage.value) + .sentences + .homePageTapBackToExit)), + ); - shape: WidgetStateProperty.resolveWith( - (Set states) { - if (states.contains(WidgetState.focused)) { - return RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - side: BorderSide( - color: tColors.primaryTextColor!, - width: 2.0, - ), - ); - } else { - return RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - side: BorderSide( - color: tColors.primaryTextColor!, - width: 1.5, - ), - ); - } + _backPressTimer?.cancel(); + _backPressTimer = Timer(const Duration(seconds: 2), () { + _lastBackPressTime = null; + }); + + return; + } + }, + child: Container( + color: tColors.dialogBackgroundColor, child: Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Obx( + () => Column( + children: [ + if (widget.controller.searchVisible.value) + Container( + margin: const EdgeInsets.symmetric( + horizontal: 10, vertical: 10), + child: SearchBar( + backgroundColor: WidgetStateProperty.all( + (tColors.primaryBackgroundColor!)), + surfaceTintColor: WidgetStateProperty.all( + (tColors.primaryBackgroundColor!)), + controller: widget.controller.searchController, + // shape:, + onChanged: (value) { + widget.controller.search(value); }, - ), - leading: const Icon(Icons.search_rounded), - trailing: [ - (controller.searchController.text.isNotEmpty) - ? IconButton( - key: GlobalKey(), - icon: Icon(Icons.cancel, - color: TaskWarriorColors.black), - onPressed: () { - controller.searchController.clear(); - controller - .search(controller.searchController.text); - }, - ) - : const SizedBox( - width: 0, - height: 0, - ) - ], - hintText: SentenceManager( + shape: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.focused)) { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + side: BorderSide( + color: tColors.primaryTextColor!, + width: 2.0, + ), + ); + } else { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + side: BorderSide( + color: tColors.primaryTextColor!, + width: 1.5, + ), + ); + } + }, + ), + leading: const Icon(Icons.search_rounded), + trailing: [ + (widget.controller.searchController.text.isNotEmpty) + ? IconButton( + key: GlobalKey(), + icon: Icon(Icons.cancel, + color: TaskWarriorColors.black), + onPressed: () { + widget.controller.searchController.clear(); + widget.controller.search(widget + .controller.searchController.text); + }, + ) + : const SizedBox( + width: 0, + height: 0, + ) + ], + + hintText: SentenceManager( currentLanguage: - controller.selectedLanguage.value) + widget.controller.selectedLanguage.value) .sentences .homePageSearchHint, + ), ), - ), - Visibility( - visible: !controller.taskchampion.value && - !controller.taskReplica.value, - child: Expanded( - child: Scrollbar( - child: Obx( - () => TasksBuilder( - // darkmode: AppSettings.isDarkMode, - useDelayTask: controller.useDelayTask.value, - taskData: controller.searchedTasks, - pendingFilter: controller.pendingFilter.value, - waitingFilter: controller.waitingFilter.value, - searchVisible: controller.searchVisible.value, - selectedLanguage: controller.selectedLanguage.value, - scrollController: controller.scrollController, - showbtn: controller.showbtn.value, + Visibility( + visible: !widget.controller.taskchampion.value && + !widget.controller.taskReplica.value, + child: Expanded( + child: Scrollbar( + child: Obx( + () => TasksBuilder( + // darkmode: AppSettings.isDarkMode, + useDelayTask: widget.controller.useDelayTask.value, + taskData: widget.controller.searchedTasks, + pendingFilter: + widget.controller.pendingFilter.value, + waitingFilter: + widget.controller.waitingFilter.value, + searchVisible: + widget.controller.searchVisible.value, + selectedLanguage: + widget.controller.selectedLanguage.value, + scrollController: + widget.controller.scrollController, + showbtn: widget.controller.showbtn.value, + ), ), ), ), ), - ), - Visibility( - visible: controller.taskchampion.value, - child: Expanded( - child: Scrollbar( - child: TaskViewBuilder( - pendingFilter: controller.pendingFilter.value, - selectedSort: controller.selectedSort.value, - project: controller.projectFilter.value, - ), - ))), + Visibility( + visible: widget.controller.taskchampion.value, + child: Expanded( + child: Scrollbar( + child: TaskViewBuilder( + pendingFilter: widget.controller.pendingFilter.value, + selectedSort: widget.controller.selectedSort.value, + project: widget.controller.projectFilter.value, + ), + ))), Visibility( - visible: controller.taskReplica.value, + visible: widget.controller.taskReplica.value, child: Expanded( child: Scrollbar( child: TaskReplicaViewBuilder( - replicaTasks: controller.tasksFromReplica, - pendingFilter: controller.pendingFilter.value, - selectedSort: controller.selectedSort.value, - project: controller.projectFilter.value, - ), - ))) - ], + replicaTasks: widget.controller.tasksFromReplica, + pendingFilter: widget.controller.pendingFilter.value, + selectedSort: widget.controller.selectedSort.value, + project: widget.controller.projectFilter.value, + ),))) + ], + ), ), ), - ), - ), - ); + )); } } 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..4c4e1384 100644 --- a/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart +++ b/lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart @@ -27,6 +27,7 @@ class ManageTaskServerController extends GetxController { final TextEditingController taskrcContentController = TextEditingController(); RxBool isTaskDServerActive = true.obs; RxBool hideKey = true.obs; + final RxBool isManageServerTourActive = false.obs; @override void onInit() { @@ -213,6 +214,7 @@ class ManageTaskServerController extends GetxController { opacityShadow: 1.00, hideSkip: true, onFinish: () { + isManageServerTourActive.value = false; SaveTourStatus.saveManageTaskServerTourStatus(true); }, ); @@ -222,17 +224,19 @@ class ManageTaskServerController extends GetxController { Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getManageTaskServerTourStatus().then((value) => { - if (value == false) - { - tutorialCoachMark.show(context: context), - } - else - { - // ignore: avoid_print - print('User has seen this page'), - } - }); + SaveTourStatus.getManageTaskServerTourStatus().then((value) { + if (value == false) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isManageServerTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } else { + // ignore: avoid_print + print('User has seen this page'); + } + }); }, ); } diff --git a/lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart b/lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart index 24686c30..35623136 100644 --- a/lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart +++ b/lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart @@ -21,349 +21,381 @@ class ManageTaskServerPageBody extends StatelessWidget { Widget build(BuildContext context) { controller.initManageTaskServerPageTour(); controller.showManageTaskServerPageTour(context); - TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return Padding( - padding: const EdgeInsets.only(left: 20, right: 20), - child: ListView( - // mainAxisAlignment: MainAxisAlignment.start, - // crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - key: controller.configureTaskRC, - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - SentenceManager(currentLanguage: AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageConfigureTASKRC, - style: TextStyle( - color: tColors.primaryTextColor, - ), + TaskwarriorColorTheme tColors = + Theme.of(context).extension()!; + return Obx(() => PopScope( + canPop: !controller.isManageServerTourActive.value, + onPopInvokedWithResult: (didPop, result) async { + if (controller.isManageServerTourActive.value) { + Get.closeAllSnackbars(); + Get.snackbar( + 'Tour Active', + 'Please complete the tour before navigating back.', + snackPosition: SnackPosition.BOTTOM, + ); + return; + } + }, + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: ListView( + // mainAxisAlignment: MainAxisAlignment.start, + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + key: controller.configureTaskRC, + padding: const EdgeInsets.only( + top: 10, + bottom: 10, ), - const SizedBox(height: 10), - GestureDetector( - onTap: () { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: tColors.dialogBackgroundColor, - builder: (context) { - return StatefulBuilder( - builder: - (BuildContext context, StateSetter setState) { - // double heightOfModalBottomSheet = - // MediaQuery.of(context).size.height * 0.6; - - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Wrap( - children: [ - Container( - // height: heightOfModalBottomSheet, - padding: const EdgeInsets.all(16.0), - decoration: const BoxDecoration( - // color: tileColor, - borderRadius: BorderRadius.vertical( - top: Radius.circular(16.0)), - ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageConfigureTASKRC, + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + const SizedBox(height: 10), + GestureDetector( + onTap: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: tColors.dialogBackgroundColor, + builder: (context) { + return StatefulBuilder( + builder: + (BuildContext context, StateSetter setState) { + // double heightOfModalBottomSheet = + // MediaQuery.of(context).size.height * 0.6; - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - SentenceManager( - currentLanguage: AppSettings - .selectedLanguage) - .sentences - .manageTaskServerPageConfigureTaskRCDialogueBoxTitle, - style: TextStyle( - fontWeight: TaskWarriorFonts.bold, - color: tColors.primaryTextColor, - ), + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Wrap( + children: [ + Container( + // height: heightOfModalBottomSheet, + padding: const EdgeInsets.all(16.0), + decoration: const BoxDecoration( + // color: tileColor, + borderRadius: BorderRadius.vertical( + top: Radius.circular(16.0)), ), - Text( - SentenceManager( - currentLanguage: AppSettings - .selectedLanguage) - .sentences - .manageTaskServerPageConfigureTaskRCDialogueBoxSubtitle, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - const SizedBox(height: 16.0), - Padding( - padding: const EdgeInsets.all(12.0), - child: SizedBox( - height: Get.height * 0.15, - child: TextField( + + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings + .selectedLanguage) + .sentences + .manageTaskServerPageConfigureTaskRCDialogueBoxTitle, style: TextStyle( - color: tColors.primaryTextColor - ), - controller: controller - .taskrcContentController, - maxLines: 8, - decoration: InputDecoration( - counterStyle: TextStyle( - color: tColors.primaryTextColor + fontWeight: + TaskWarriorFonts.bold, + color: tColors.primaryTextColor, + ), + ), + Text( + SentenceManager( + currentLanguage: + AppSettings + .selectedLanguage) + .sentences + .manageTaskServerPageConfigureTaskRCDialogueBoxSubtitle, + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + const SizedBox(height: 16.0), + Padding( + padding: + const EdgeInsets.all(12.0), + child: SizedBox( + height: Get.height * 0.15, + child: TextField( + style: TextStyle( + color: tColors + .primaryTextColor), + controller: controller + .taskrcContentController, + maxLines: 8, + decoration: InputDecoration( + counterStyle: TextStyle( + color: tColors + .primaryTextColor), + suffixIconConstraints: + const BoxConstraints( + maxHeight: 24, + maxWidth: 24, + ), + isDense: true, + suffix: IconButton( + onPressed: () async { + controller.setContent( + context); + }, + icon: const Icon( + Icons.content_paste), + ), + border: + const OutlineInputBorder(), + labelStyle: + GoogleFonts.poppins( + color: tColors + .primaryTextColor), + labelText: SentenceManager( + currentLanguage: + AppSettings + .selectedLanguage) + .sentences + .manageTaskServerPageConfigureTaskRCDialogueBoxInputFieldText, ), - suffixIconConstraints: - const BoxConstraints( - maxHeight: 24, - maxWidth: 24, - ), - isDense: true, - suffix: IconButton( - onPressed: () async { - controller - .setContent(context); - }, - icon: const Icon( - Icons.content_paste), ), - border: - const OutlineInputBorder(), - labelStyle: GoogleFonts.poppins( - color:tColors.primaryTextColor, - ), - labelText: SentenceManager( + ), + ), + Text( + SentenceManager( + currentLanguage: + AppSettings + .selectedLanguage) + .sentences + .manageTaskServerPageConfigureTaskRCDialogueBoxOr, + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + FilledButton.tonal( + style: ButtonStyle( + backgroundColor: AppSettings + .isDarkMode + ? WidgetStateProperty.all< + Color>( + TaskWarriorColors + .black) + : WidgetStateProperty.all< + Color>( + TaskWarriorColors + .white)), + onPressed: () async { + await setConfig( + storage: controller.storage, + key: 'TASKRC', + ); + setState(() {}); + Get.back(); + }, + child: Text( + SentenceManager( currentLanguage: AppSettings - .selectedLanguage - ) + .selectedLanguage) .sentences - .manageTaskServerPageConfigureTaskRCDialogueBoxInputFieldText, + .manageTaskServerPageConfigureTaskRCDialogueBoxSelectTaskRC, + style: TextStyle( + color: + tColors.primaryTextColor, + ), ), ), - ), - ), - Text( - SentenceManager( - currentLanguage: AppSettings - .selectedLanguage) - .sentences - .manageTaskServerPageConfigureTaskRCDialogueBoxOr, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - FilledButton.tonal( - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(tColors.secondaryBackgroundColor!) - ), - onPressed: () async { - await setConfig( - storage: controller.storage, - key: 'TASKRC', - ); - setState(() {}); - Get.back(); - }, - child: Text( - SentenceManager( - currentLanguage: AppSettings - .selectedLanguage) - .sentences - .manageTaskServerPageConfigureTaskRCDialogueBoxSelectTaskRC, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), + ], ), - ], - ), + ), + ], ), - ], - ), + ); + }, ); }, ); }, - ); - }, - child: Container( - width: MediaQuery.of(context).size.width * 1, - // height: MediaQuery.of(context).size.height * 0.05, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - // color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: TaskWarriorColors.borderColor), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - controller.taskrcContentController.text.isEmpty - ? SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageSetTaskRC - : SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageTaskRCFileIsVerified, - style: TextStyle( - color: tColors.primaryTextColor, - ), + child: Container( + width: MediaQuery.of(context).size.width * 1, + // height: MediaQuery.of(context).size.height * 0.05, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + // color: tileColor, + borderRadius: BorderRadius.circular(8), + border: + Border.all(color: TaskWarriorColors.borderColor), ), - Container( - height: 30, - width: 30, - decoration: BoxDecoration( - color: tColors.secondaryTextColor, - shape: BoxShape.circle, - ), - child: Center( - child: controller - .taskrcContentController.text.isNotEmpty - ? Icon( - Icons.check, - color: TaskWarriorColors.green, - ) - : Icon( - Icons.chevron_right_rounded, - color: tColors.secondaryBackgroundColor, - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + controller.taskrcContentController.text.isEmpty + ? SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageSetTaskRC + : SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageTaskRCFileIsVerified, + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: tColors.secondaryTextColor, + shape: BoxShape.circle, + ), + child: Center( + child: controller + .taskrcContentController.text.isNotEmpty + ? Icon( + Icons.check, + color: TaskWarriorColors.green, + ) + : Icon( + Icons.chevron_right_rounded, + color: tColors.secondaryBackgroundColor, + ), + ), + ), + ], ), - ], + ), ), - ), + ], ), - ], - ), - ), - Offstage( - offstage: controller.isTaskDServerActive.value, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .taskServerInfo, - style: TextStyle( - color: tColors.primaryTextColor, - ), + ), + Offstage( + offstage: controller.isTaskDServerActive.value, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, ), - const SizedBox(height: 10), - GestureDetector( - onTap: () {}, - child: Container( - width: MediaQuery.of(context).size.width * 1, - // height: MediaQuery.of(context).size.height * 0.05, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - // color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: TaskWarriorColors.borderColor, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .taskServerInfo, + style: TextStyle( + color: tColors.primaryTextColor, ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - controller.server == null - ? Text( - SentenceManager( - currentLanguage: AppSettings - .selectedLanguage) - .sentences - .notConfigured, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ) - : Text( - '${controller.server}', - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - Container( - height: 30, - width: 30, - decoration: BoxDecoration( - color: tColors.secondaryTextColor, - shape: BoxShape.circle, + const SizedBox(height: 10), + GestureDetector( + onTap: () {}, + child: Container( + width: MediaQuery.of(context).size.width * 1, + // height: MediaQuery.of(context).size.height * 0.05, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + // color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: TaskWarriorColors.borderColor, ), - child: Center( - child: controller.server != null - ? Icon( - Icons.check, - color: TaskWarriorColors.green, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + controller.server == null + ? Text( + SentenceManager( + currentLanguage: AppSettings + .selectedLanguage) + .sentences + .notConfigured, + style: TextStyle( + color: tColors.primaryTextColor, + ), ) - : Icon( - Icons.chevron_right_rounded, - color: tColors.secondaryBackgroundColor, + : Text( + '${controller.server}', + style: TextStyle( + color: tColors.primaryTextColor, ), ), - ), + Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: tColors.secondaryTextColor, + shape: BoxShape.circle, + ), + child: Center( + child: controller.server != null + ? Icon( + Icons.check, + color: TaskWarriorColors.green, + ) + : Icon( + Icons.chevron_right_rounded, + color: tColors.secondaryBackgroundColor, ), + ), + ), + ], ), - ], + ), ), - ), + ], ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - SentenceManager( + ), + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences .taskServerCredentials, style: TextStyle( color: tColors.primaryTextColor, - ), - ), - const SizedBox(height: 10), - GestureDetector( - onTap: () {}, - child: Container( - width: MediaQuery.of(context).size.width * 1, - // height: MediaQuery.of(context).size.height * 0.05, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - // color: tileColor, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: TaskWarriorColors.borderColor), + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - controller.credentialsString == null - ? Text( - SentenceManager( + const SizedBox(height: 10), + GestureDetector( + onTap: () {}, + child: Container( + width: MediaQuery.of(context).size.width * 1, + // height: MediaQuery.of(context).size.height * 0.05, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + // color: tileColor, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: TaskWarriorColors.borderColor), + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + controller.credentialsString == null + ? Text( + SentenceManager( currentLanguage: AppSettings .selectedLanguage) .sentences @@ -371,126 +403,128 @@ class ManageTaskServerPageBody extends StatelessWidget { style: TextStyle( color: tColors.primaryTextColor, ), - ) - : SizedBox( - width: - MediaQuery.of(context).size.width * + ) + : SizedBox( + width: MediaQuery.of(context) + .size + .width * 0.7, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Text( - controller.credentialsString!.value, - style: TextStyle( - color: tColors.primaryTextColor, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Text( + controller + .credentialsString!.value, + style: TextStyle( + color: tColors.primaryTextColor, ), + ), ), ), + GestureDetector( + onTap: () { + controller.hideKey.value = + !controller.hideKey.value; + }, + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: tColors.primaryTextColor, shape: BoxShape.circle, ), + child: controller.credentials == null + ? Icon( + Icons.chevron_right_rounded, + color: tColors.primaryBackgroundColor, + ) + : Icon( + controller.hideKey.value + ? Icons.visibility_off + : Icons.visibility, + color: TaskWarriorColors.green, + ), ), - GestureDetector( - onTap: () { - controller.hideKey.value = - !controller.hideKey.value; - }, - child: Container( - height: 30, - width: 30, - decoration: BoxDecoration( - color: tColors.primaryTextColor, - shape: BoxShape.circle, ), - child: controller.credentials == null - ? Icon( - Icons.chevron_right_rounded, - color: tColors.primaryBackgroundColor, - ) - : Icon( - controller.hideKey.value - ? Icons.visibility_off - : Icons.visibility, - color: TaskWarriorColors.green, - ), - ), + ], ), - ], + ), ), - ), + ], ), - ], - ), - ), - ], - )), - GetBuilder( - builder: (controller) { - List pemWidgets = []; - for (var pem in [ - 'taskd.certificate', - 'taskd.key', - 'taskd.ca', - if (controller.homeController.serverCertExists.value) - 'server.cert', - ]) { - pemWidgets.add( - PemWidget( - storage: controller.storage, - pem: pem, - optionString: pem == "taskd.certificate" - ? SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageConfigureYourCertificate - : pem == "taskd.key" + ), + ], + )), + GetBuilder( + builder: (controller) { + List pemWidgets = []; + for (var pem in [ + 'taskd.certificate', + 'taskd.key', + 'taskd.ca', + if (controller.homeController.serverCertExists.value) + 'server.cert', + ]) { + pemWidgets.add( + PemWidget( + storage: controller.storage, + pem: pem, + optionString: pem == "taskd.certificate" ? SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .manageTaskServerPageConfigureTaskserverKey - : pem == "taskd.ca" + .manageTaskServerPageConfigureYourCertificate + : pem == "taskd.key" ? SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .manageTaskServerPageConfigureServerCertificate - : SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageConfigureServerCertificate, - listTileTitle: pem == "taskd.certificate" - ? SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageSelectCertificate - : pem == "taskd.key" + .manageTaskServerPageConfigureTaskserverKey + : pem == "taskd.ca" + ? SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageConfigureServerCertificate + : SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageConfigureServerCertificate, + listTileTitle: pem == "taskd.certificate" ? SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .manageTaskServerPageSelectKey - : pem == "taskd.ca" + .manageTaskServerPageSelectCertificate + : pem == "taskd.key" ? SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .manageTaskServerPageSelectCertificate - : SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .manageTaskServerPageSelectCertificate, - onTapCallBack: controller.onTapPEMWidget, - onLongPressCallBack: controller.onLongPressPEMWidget, - globalKey: controller.getGlobalKey(pem), - ), - ); - } - return Column( - children: pemWidgets, - ); - }, - ) - ], - ), - ); + .manageTaskServerPageSelectKey + : pem == "taskd.ca" + ? SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageSelectCertificate + : SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .manageTaskServerPageSelectCertificate, + onTapCallBack: controller.onTapPEMWidget, + onLongPressCallBack: controller.onLongPressPEMWidget, + globalKey: controller.getGlobalKey(pem), + ), + ); + } + return Column( + children: pemWidgets, + ); + }, + ) + ], + ), + ))); } } diff --git a/lib/app/modules/profile/controllers/profile_controller.dart b/lib/app/modules/profile/controllers/profile_controller.dart index 50e6e5cd..055bdb2a 100644 --- a/lib/app/modules/profile/controllers/profile_controller.dart +++ b/lib/app/modules/profile/controllers/profile_controller.dart @@ -10,6 +10,8 @@ class ProfileController extends GetxController { var profilesWidget = Get.find(); late RxMap profilesMap; late RxString currentProfile; + final RxBool isProfileTourActive = false.obs; + @override void onInit() { profilesMap = profilesWidget.profilesMap; @@ -28,7 +30,6 @@ class ProfileController extends GetxController { tutorialCoachMark = TutorialCoachMark( targets: addProfilePage( currentProfileKey: currentProfileKey, - addNewProfileKey: addNewProfileKey, manageSelectedProfileKey: manageSelectedProfileKey, ), @@ -37,6 +38,7 @@ class ProfileController extends GetxController { opacityShadow: 1.00, hideSkip: true, onFinish: () { + isProfileTourActive.value = false; SaveTourStatus.saveProfileTourStatus(true); }, ); @@ -46,17 +48,19 @@ class ProfileController extends GetxController { Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getProfileTourStatus().then((value) => { - if (value == false) - { - tutorialCoachMark.show(context: context), - } - else - { - // ignore: avoid_print - print('User has seen this page'), - } - }); + SaveTourStatus.getProfileTourStatus().then((value) { + if (value == false) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isProfileTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } else { + // ignore: avoid_print + print('User has seen this page'); + } + }); }, ); } diff --git a/lib/app/modules/profile/views/profile_view.dart b/lib/app/modules/profile/views/profile_view.dart index 568b5faf..40ee0fda 100644 --- a/lib/app/modules/profile/views/profile_view.dart +++ b/lib/app/modules/profile/views/profile_view.dart @@ -27,324 +27,352 @@ class ProfileView extends GetView { controller.showProfilePageTour(context); TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return Scaffold( - appBar: AppBar( - backgroundColor: TaskWarriorColors.appBarColor, - title: Obx(() => Text( - controller.profilesMap.length == 1 - ? SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageProfile - : SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageProfiles, - style: GoogleFonts.poppins( + return Obx( + () => PopScope( + canPop: !controller.isProfileTourActive.value, + onPopInvokedWithResult: (didPop, result) async { + if (controller.isProfileTourActive.value) { + Get.closeAllSnackbars(); + Get.snackbar( + 'Tour Active', + 'Please complete the tour before navigating back.', + snackPosition: SnackPosition.BOTTOM, + ); + return; + } + }, + child: Scaffold( + appBar: AppBar( + backgroundColor: TaskWarriorColors.appBarColor, + title: Obx(() => Text( + controller.profilesMap.length == 1 + ? SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageProfile + : SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageProfiles, + style: GoogleFonts.poppins( + color: TaskWarriorColors.white, + ), + )), + leading: IconButton( + onPressed: () { + // Navigator.pushReplacementNamed(context, PageRoutes.home); + // Navigator.of(context).pop(); + Get.back(); + }, + icon: Icon( + Icons.chevron_left, color: TaskWarriorColors.white, + size: 35, ), - )), - leading: IconButton( - onPressed: () { - Get.back(); - }, - icon: Icon( - Icons.chevron_left, - color: TaskWarriorColors.white, - size: 35, - ), - ), - actions: [ - TextButton( - onPressed: controller.profilesWidget.addProfile, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.add, - color: Colors.white, - ), - const SizedBox( - width: 10, - ), - Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageAddNewProfile, - style: TextStyle(color: Colors.white)), - ], ), + actions: [ + TextButton( + onPressed: controller.profilesWidget.addProfile, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.add, + color: Colors.white, + ), + const SizedBox( + width: 10, + ), + Text( + SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageAddNewProfile, + style: TextStyle(color: Colors.white)), + ], + ), + ), + ], ), - ], - ), - backgroundColor: tColors.primaryBackgroundColor, - body: Obx(() => ProfilesList( - currentProfileKey: controller.currentProfileKey, - addNewProfileKey: controller.addNewProfileKey, - manageSelectedProfileKey: controller.manageSelectedProfileKey, - controller.profilesMap, - controller.currentProfile.value, - controller.profilesWidget.addProfile, - controller.profilesWidget.selectProfile, - (profile) => showDialog( - context: context, - builder: (context) => Center( - child: RenameProfileDialog( - profile: profile, - alias: - controller.profilesMap[controller.currentProfile.value], + backgroundColor: tColors.primaryBackgroundColor, + body: Obx(() => ProfilesList( + currentProfileKey: controller.currentProfileKey, + addNewProfileKey: controller.addNewProfileKey, + manageSelectedProfileKey: controller.manageSelectedProfileKey, + controller.profilesMap, + controller.currentProfile.value, + controller.profilesWidget.addProfile, + controller.profilesWidget.selectProfile, + (profile) => showDialog( context: context, + builder: (context) => Center( + child: RenameProfileDialog( + profile: profile, + alias: controller + .profilesMap[controller.currentProfile.value], + context: context, + ), + ), ), - ), - ), - () { - if (controller.profilesWidget - .getMode(controller.currentProfile.value) == - 'TW3' || - controller.profilesWidget - .getMode(controller.currentProfile.value) == - 'TW3C') { - Get.toNamed(Routes.MANAGE_TASK_CHAMPION_CREDS); - return; - } - Get.toNamed(Routes.MANAGE_TASK_SERVER); - }, - (profile) async { - String tasks; - if (controller.profilesWidget.getMode(profile) == "TW2") { - tasks = - controller.profilesWidget.getStorage(profile).data.export(); - } else if (controller.profilesWidget.getMode(profile) == "TW3") { - TaskDatabase db = TaskDatabase(); - await db.openForProfile(profile); - tasks = await db.exportAllTasks(); - } else { - tasks = await Replica.getAllTasksFromReplica().then( - (taskList) => - taskList.map((e) => e.toJson()).toList().toString()); - debugPrint("Exported Tasks from Replica: $tasks"); - } - var now = DateTime.now() - .toIso8601String() - .replaceAll(RegExp(r'[-:]'), '') - .replaceAll(RegExp(r'\..*'), ''); + () { + if (controller.profilesWidget + .getMode(controller.currentProfile.value) == + 'TW3' || + controller.profilesWidget + .getMode(controller.currentProfile.value) == + 'TW3C') { + Get.toNamed(Routes.MANAGE_TASK_CHAMPION_CREDS); + return; + } + Get.toNamed(Routes.MANAGE_TASK_SERVER); + }, + (profile) async { + String tasks; + if (controller.profilesWidget.getMode(profile) == "TW2") { + tasks = controller.profilesWidget + .getStorage(profile) + .data + .export(); + } else if (controller.profilesWidget.getMode(profile) == + "TW3") { + TaskDatabase db = TaskDatabase(); + await db.openForProfile(profile); + tasks = await db.exportAllTasks(); + } else { + tasks = await Replica.getAllTasksFromReplica().then( + (taskList) => taskList + .map((e) => e.toJson()) + .toList() + .toString()); + debugPrint("Exported Tasks from Replica: $tasks"); + } + var now = DateTime.now() + .toIso8601String() + .replaceAll(RegExp(r'[-:]'), '') + .replaceAll(RegExp(r'\..*'), ''); - showDialog( - context: context, - builder: (BuildContext context) { - return Utils.showAlertDialog( - title: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageExportTasksDialogueTitle, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - content: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageExportTasksDialogueSubtitle, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - actions: [ - TextButton( - child: Text( - "JSON", + showDialog( + context: context, + builder: (BuildContext context) { + return Utils.showAlertDialog( + title: Text( + SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageExportTasksDialogueTitle, style: TextStyle( color: tColors.primaryTextColor, ), ), - onPressed: () { - // Navigator.of(context).pop(); - Get.back(); - exportTasks( - contents: tasks, - suggestedName: 'tasks-$now.json', - ); - }, - ), - TextButton( - child: Text( - "TXT", + content: Text( + SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageExportTasksDialogueSubtitle, style: TextStyle( color: tColors.primaryTextColor, ), ), - onPressed: () { - // Navigator.of(context).pop(); - Get.back(); - exportTasks( - contents: tasks, - suggestedName: 'tasks-$now.txt', - ); - }, - ), - ], - ); - }, - ); - }, - (profile) async { - try { - await controller.profilesWidget.copyConfigToNewProfile( - profile, - ); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profileConfigCopied, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - backgroundColor: tColors.secondaryBackgroundColor, - duration: const Duration(seconds: 2))); - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profileConfigCopyFailed, - style: TextStyle( - color: tColors.primaryTextColor, - ), - ), - backgroundColor: tColors.primaryBackgroundColor, - duration: const Duration(seconds: 2))); - } - }, - (profile) { - String? profileName = controller.profilesMap[profile]; - controller.profilesMap.remove(profile); - showDialog( - context: context, - builder: (context) => DeleteProfileDialog( - profile: profile, - context: context, - profiles: controller.profilesMap, - profileName: profileName, - ), - ); - }, - (profile) { - String currentMode = controller.profilesWidget.getMode(profile); - String? selectedMode = currentMode; - showDialog( - context: context, - builder: (BuildContext context) { - return Utils.showAlertDialog( - title: Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .profilePageChangeProfileMode, - ), - // Use StatefulBuilder to manage the state of the radio buttons inside the dialog - content: StatefulBuilder( - builder: (BuildContext context, StateSetter setState) { - return Column( - mainAxisSize: MainAxisSize.min, // Use minimum space - children: [ - RadioListTile( - title: const Text('Taskchampion (v3)'), - value: 'TW3C', - groupValue: selectedMode, - onChanged: (String? value) { - setState(() { - selectedMode = value; - }); - }, + actions: [ + TextButton( + child: Text( + "JSON", + style: TextStyle(color: tColors.primaryTextColor), ), - RadioListTile( - title: const Text('CCSync (v3)'), - value: 'TW3', - groupValue: selectedMode, - onChanged: (String? value) { - setState(() { - selectedMode = value; - }); - }, - ), - RadioListTile( - title: const Text('TaskServer'), - value: 'TW2', - groupValue: selectedMode, - onChanged: (String? value) { - setState(() { - selectedMode = value; - }); - }, + onPressed: () { + // Navigator.of(context).pop(); + Get.back(); + exportTasks( + contents: tasks, + suggestedName: 'tasks-$now.json', + ); + }, + ), + TextButton( + child: Text( + "TXT", + style: TextStyle( + color: tColors.primaryTextColor, + ), ), - ], - ); - }, - ), - actions: [ - // A button to cancel the operation - TextButton( - child: Text( + onPressed: () { + // Navigator.of(context).pop(); + Get.back(); + exportTasks( + contents: tasks, + suggestedName: 'tasks-$now.txt', + ); + }, + ), + ], + ); + }, + ); + }, + (profile) async { + try { + await controller.profilesWidget.copyConfigToNewProfile( + profile, + ); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .cancel, // Assuming you have a 'cancel' string - style: TextStyle(color: tColors.primaryTextColor), + .profileConfigCopied, + style: TextStyle( + color: tColors.primaryTextColor, + ), ), - onPressed: () { - Get.back(); // Dismiss the dialog - }, - ), - // A button to submit the change - TextButton( - child: Text( + backgroundColor: tColors.secondaryBackgroundColor, + duration: const Duration(seconds: 2))); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( SentenceManager( currentLanguage: AppSettings.selectedLanguage) .sentences - .submit, // Or use a translated string - style: TextStyle(color: tColors.primaryTextColor), + .profileConfigCopyFailed, + style: TextStyle( + color: tColors.primaryTextColor, + ), ), - onPressed: () { - Get.back(); - if (selectedMode != null && - selectedMode != currentMode) { - controller.profilesWidget.changeModeTo( - profile, - selectedMode!, - ); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .profilePageSuccessfullyChangedProfileModeTo + - ((selectedMode ?? "") == "TW3" - ? "CCSync" - : "Taskserver"), - style: TextStyle( - color: tColors.primaryTextColor, - ), + backgroundColor: tColors.primaryBackgroundColor, + duration: const Duration(seconds: 2))); + } + }, + (profile) { + String? profileName = controller.profilesMap[profile]; + controller.profilesMap.remove(profile); + showDialog( + context: context, + builder: (context) => DeleteProfileDialog( + profile: profile, + context: context, + profiles: controller.profilesMap, + profileName: profileName, + ), + ); + }, + (profile) { + String currentMode = + controller.profilesWidget.getMode(profile); + String? selectedMode = currentMode; + showDialog( + context: context, + builder: (BuildContext context) { + return Utils.showAlertDialog( + title: Text( + SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .profilePageChangeProfileMode, + ), + // Use StatefulBuilder to manage the state of the radio buttons inside the dialog + content: StatefulBuilder( + builder: + (BuildContext context, StateSetter setState) { + return Column( + mainAxisSize: + MainAxisSize.min, // Use minimum space + children: [ + RadioListTile( + title: const Text('Taskchampion (v3)'), + value: 'TW3C', + groupValue: selectedMode, + onChanged: (String? value) { + setState(() { + selectedMode = value; + }); + }, + ), + RadioListTile( + title: const Text('CCSync (v3)'), + value: 'TW3', + groupValue: selectedMode, + onChanged: (String? value) { + setState(() { + selectedMode = value; + }); + }, ), - backgroundColor: - tColors.secondaryBackgroundColor, - duration: const Duration(seconds: 2))); - } - }, - ), - ], + RadioListTile( + title: const Text('TaskServer'), + value: 'TW2', + groupValue: selectedMode, + onChanged: (String? value) { + setState(() { + selectedMode = value; + }); + }, + ), + ], + ); + }, + ), + actions: [ + // A button to cancel the operation + TextButton( + child: Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .cancel, // Assuming you have a 'cancel' string + style: TextStyle(color: tColors.primaryTextColor), + ), + onPressed: () { + Get.back(); // Dismiss the dialog + }, + ), + // A button to submit the change + TextButton( + child: Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .submit, // Or use a translated string + style: TextStyle(color: tColors.primaryTextColor), + ), + onPressed: () { + Get.back(); + if (selectedMode != null && + selectedMode != currentMode) { + controller.profilesWidget.changeModeTo( + profile, + selectedMode!, + ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + SentenceManager( + currentLanguage: + AppSettings + .selectedLanguage) + .sentences + .profilePageSuccessfullyChangedProfileModeTo + + ((selectedMode ?? "") == "TW3" + ? "CCSync" + : "Taskserver"), + style: TextStyle( + color: tColors.primaryTextColor, + ), + ), + backgroundColor: + tColors.secondaryBackgroundColor, + duration: const Duration(seconds: 2))); + } + }, + ), + ], + ); + }, ); }, - ); - }, - )), + )), + ), + ), ); } } diff --git a/lib/app/modules/reports/controllers/reports_controller.dart b/lib/app/modules/reports/controllers/reports_controller.dart index fd81d97e..b2750648 100644 --- a/lib/app/modules/reports/controllers/reports_controller.dart +++ b/lib/app/modules/reports/controllers/reports_controller.dart @@ -26,6 +26,7 @@ class ReportsController extends GetxController late TaskDatabase taskDatabase; var isSaved = false.obs; late TutorialCoachMark tutorialCoachMark; + final RxBool isReportsTourActive = false.obs; var selectedIndex = 0.obs; var allData = [].obs; @@ -80,6 +81,7 @@ class ReportsController extends GetxController opacityShadow: 0.8, hideSkip: true, onFinish: () { + isReportsTourActive.value = false; SaveTourStatus.saveReportsTourStatus(true); }, ); @@ -89,17 +91,19 @@ class ReportsController extends GetxController Future.delayed( const Duration(milliseconds: 500), () { - SaveTourStatus.getReportsTourStatus().then((value) => { - if (value == false) - { - tutorialCoachMark.show(context: context), - } - else - { - // ignore: avoid_print - print('User has seen this page'), - } - }); + SaveTourStatus.getReportsTourStatus().then((value) { + if (value == false) { + tutorialCoachMark.targets.removeWhere( + (target) => target.keyTarget?.currentContext == null); + if (tutorialCoachMark.targets.isNotEmpty) { + isReportsTourActive.value = true; + tutorialCoachMark.show(context: context); + } + } else { + // ignore: avoid_print + print('User has seen this page'); + } + }); }, ); } diff --git a/lib/app/modules/reports/views/reports_view.dart b/lib/app/modules/reports/views/reports_view.dart index 609c2559..9cb2cd69 100644 --- a/lib/app/modules/reports/views/reports_view.dart +++ b/lib/app/modules/reports/views/reports_view.dart @@ -23,131 +23,151 @@ class ReportsView extends GetView { double height = MediaQuery.of(context).size.height; TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return Scaffold( - appBar: AppBar( - backgroundColor: TaskWarriorColors.kprimaryBackgroundColor, - title: Text( - SentenceManager(currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageTitle, - style: GoogleFonts.poppins(color: TaskWarriorColors.white), - ), - leading: GestureDetector( - onTap: () { - Get.back(); - }, - child: Icon( - Icons.chevron_left, - color: TaskWarriorColors.white, - size: 35, - ), - ), - bottom: PreferredSize( - preferredSize: Size.fromHeight(height * 0.1), - child: TabBar( - controller: controller.tabController, - unselectedLabelStyle: GoogleFonts.poppins( - fontWeight: TaskWarriorFonts.light, - color: TaskWarriorColors.appBarUnSelectedIconsColorForReports), - indicatorColor: tColors.purpleShade, - labelColor: TaskWarriorColors.white, - onTap: (value) { - controller.selectedIndex.value = value; - }, - tabs: [ - Tab( - key: controller.daily, - icon: const Icon(Icons.schedule), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageDaily, - iconMargin: const EdgeInsets.only(bottom: 0.0), - ), - Tab( - key: controller.weekly, - icon: const Icon(Icons.today), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageWeekly, - iconMargin: const EdgeInsets.only(bottom: 0.0), + return Obx(() => PopScope( + canPop: !controller.isReportsTourActive.value, + onPopInvokedWithResult: (didPop, result) async { + if (controller.isReportsTourActive.value) { + Get.closeAllSnackbars(); + Get.snackbar( + 'Tour Active', + 'Please complete the tour before navigating back.', + snackPosition: SnackPosition.BOTTOM, + ); + return; + } + }, + child: Scaffold( + appBar: AppBar( + backgroundColor: TaskWarriorColors.kprimaryBackgroundColor, + title: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageTitle, + style: GoogleFonts.poppins(color: TaskWarriorColors.white), + ), + leading: GestureDetector( + onTap: () { + Get.back(); + }, + child: Icon( + Icons.chevron_left, + color: TaskWarriorColors.white, + size: 35, ), - Tab( - key: controller.monthly, - icon: const Icon(Icons.date_range), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageMonthly, - iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + bottom: PreferredSize( + preferredSize: Size.fromHeight(height * 0.1), + child: TabBar( + controller: controller.tabController, + labelColor: TaskWarriorColors.white, + labelStyle: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.medium, + fontSize: TaskWarriorFonts.fontSizeSmall, + ), + unselectedLabelStyle: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.light, + color: + TaskWarriorColors.appBarUnSelectedIconsColorForReports), + indicatorColor: tColors.purpleShade, + onTap: (value) { + controller.selectedIndex.value = value; + }, + tabs: [ + Tab( + key: controller.daily, + icon: const Icon(Icons.schedule), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageDaily, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + Tab( + key: controller.weekly, + icon: const Icon(Icons.today), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageWeekly, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + Tab( + key: controller.monthly, + icon: const Icon(Icons.date_range), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageMonthly, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + ], ), - ], + ), ), - ), - ), - backgroundColor: tColors.primaryBackgroundColor, - body: Obx( - () => controller.allData.isEmpty - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Icon( - Icons.heart_broken, - color: tColors.primaryTextColor, - ), - Row( + backgroundColor: tColors.primaryBackgroundColor, + body: Obx( + () => controller.allData.isEmpty + ? Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageNoTasksFound, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontWeight: TaskWarriorFonts.medium, - fontSize: TaskWarriorFonts.fontSizeSmall, - color: tColors.primaryTextColor, - ), + Icon( + Icons.heart_broken, + color: tColors.primaryTextColor, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .reportsPageNoTasksFound, + style: TextStyle( + fontFamily: FontFamily.poppins, + fontWeight: TaskWarriorFonts.medium, + fontSize: TaskWarriorFonts.fontSizeSmall, + color: tColors.primaryTextColor, + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .reportsPageAddTasksToSeeReports, + style: TextStyle( + fontFamily: FontFamily.poppins, + fontWeight: TaskWarriorFonts.light, + fontSize: TaskWarriorFonts.fontSizeSmall, + color: tColors.primaryTextColor, + ), + ), + ], ), ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, + ) + : IndexedStack( + index: controller.selectedIndex.value, children: [ - Text( - SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageAddTasksToSeeReports, - style: TextStyle( - fontFamily: FontFamily.poppins, - fontWeight: TaskWarriorFonts.light, - fontSize: TaskWarriorFonts.fontSizeSmall, - color: tColors.primaryTextColor, - ), + BurnDownDaily( + reportsController: controller, + ), + BurnDownWeekly( + reportsController: controller, + ), + BurnDownMonthly( + reportsController: controller, ), ], ), - ], - ) - : IndexedStack( - index: controller.selectedIndex.value, - children: [ - BurnDownDaily( - reportsController: controller, - ), - BurnDownWeekly( - reportsController: controller, - ), - BurnDownMonthly( - reportsController: controller, - ), - ], - ), - ), - ); + ), + ))); } } diff --git a/lib/app/modules/reports/views/reports_view_taskc.dart b/lib/app/modules/reports/views/reports_view_taskc.dart index bdb77374..747691ad 100644 --- a/lib/app/modules/reports/views/reports_view_taskc.dart +++ b/lib/app/modules/reports/views/reports_view_taskc.dart @@ -35,130 +35,144 @@ class ReportsHomeTaskc extends StatelessWidget { List allTasks = snapshot.data ?? []; TaskwarriorColorTheme tColors = Theme.of(context).extension()!; - return Scaffold( - appBar: AppBar( - backgroundColor: TaskWarriorColors.kprimaryBackgroundColor, - title: Text( - SentenceManager(currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageTitle, - style: GoogleFonts.poppins(color: TaskWarriorColors.white), - ), - leading: GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: Icon( - Icons.chevron_left, - color: TaskWarriorColors.white, - ), - ), - bottom: PreferredSize( - preferredSize: Size.fromHeight(height * 0.1), - child: TabBar( - controller: reportsController.tabController, - labelColor: TaskWarriorColors.white, - labelStyle: GoogleFonts.poppins( - fontWeight: TaskWarriorFonts.medium, - fontSize: TaskWarriorFonts.fontSizeSmall, - ), - unselectedLabelStyle: GoogleFonts.poppins( - fontWeight: TaskWarriorFonts.light, + + return Obx(() => PopScope( + canPop: !reportsController.isReportsTourActive.value, + onPopInvokedWithResult: (didPop, result) async { + if (reportsController.isReportsTourActive.value) { + Get.closeAllSnackbars(); + Get.snackbar( + 'Tour Active', + 'Please complete the tour before navigating back.', + snackPosition: SnackPosition.BOTTOM, + ); + return; + } + }, + child: Scaffold( + appBar: AppBar( + backgroundColor: TaskWarriorColors.kprimaryBackgroundColor, + title: Text( + SentenceManager(currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageTitle, + style: GoogleFonts.poppins(color: TaskWarriorColors.white), ), - onTap: (value) { - reportsController.selectedIndex.value = value; - }, - tabs: [ - Tab( - key: reportsController.daily, - icon: const Icon(Icons.schedule), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageDaily, - iconMargin: const EdgeInsets.only(bottom: 0.0), + leading: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Icon( + Icons.chevron_left, + color: TaskWarriorColors.white, ), - Tab( - key: reportsController.weekly, - icon: const Icon(Icons.today), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageWeekly, - iconMargin: const EdgeInsets.only(bottom: 0.0), - ), - Tab( - key: reportsController.monthly, - icon: const Icon(Icons.date_range), - text: SentenceManager( - currentLanguage: AppSettings.selectedLanguage) - .sentences - .reportsPageMonthly, - iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + bottom: PreferredSize( + preferredSize: Size.fromHeight(height * 0.1), + child: TabBar( + controller: reportsController.tabController, + labelColor: TaskWarriorColors.white, + labelStyle: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.medium, + fontSize: TaskWarriorFonts.fontSizeSmall, + ), + unselectedLabelStyle: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.light, + ), + onTap: (value) { + reportsController.selectedIndex.value = value; + }, + tabs: [ + Tab( + key: reportsController.daily, + icon: const Icon(Icons.schedule), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageDaily, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + Tab( + key: reportsController.weekly, + icon: const Icon(Icons.today), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageWeekly, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + Tab( + key: reportsController.monthly, + icon: const Icon(Icons.date_range), + text: SentenceManager( + currentLanguage: AppSettings.selectedLanguage) + .sentences + .reportsPageMonthly, + iconMargin: const EdgeInsets.only(bottom: 0.0), + ), + ], ), - ], + ), ), - ), - ), - backgroundColor: tColors.primaryBackgroundColor, - body: snapshot.connectionState == ConnectionState.waiting - ? const Center(child: CircularProgressIndicator()) - : allTasks.isEmpty - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Icon( - Icons.heart_broken, - color: tColors.primaryTextColor, - ), - Row( + backgroundColor: tColors.primaryBackgroundColor, + body: snapshot.connectionState == ConnectionState.waiting + ? const Center(child: CircularProgressIndicator()) + : allTasks.isEmpty + ? Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( - SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .reportsPageNoTasksFound, - style: GoogleFonts.poppins( - fontWeight: TaskWarriorFonts.medium, - fontSize: TaskWarriorFonts.fontSizeSmall, - color: tColors.primaryTextColor, - ), + Icon( + Icons.heart_broken, + color: tColors.primaryTextColor, ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - SentenceManager( - currentLanguage: - AppSettings.selectedLanguage) - .sentences - .reportsPageAddTasksToSeeReports, - style: GoogleFonts.poppins( - fontWeight: TaskWarriorFonts.light, - fontSize: TaskWarriorFonts.fontSizeSmall, - color: tColors.primaryTextColor, - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .reportsPageNoTasksFound, + style: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.medium, + fontSize: TaskWarriorFonts.fontSizeSmall, + color: tColors.primaryTextColor, + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + SentenceManager( + currentLanguage: + AppSettings.selectedLanguage) + .sentences + .reportsPageAddTasksToSeeReports, + style: GoogleFonts.poppins( + fontWeight: TaskWarriorFonts.light, + fontSize: TaskWarriorFonts.fontSizeSmall, + color: tColors.primaryTextColor, + ), + ), + ], ), ], + ) + : Obx( + () => IndexedStack( + index: reportsController.selectedIndex.value, + children: [ + BurnDownDailyTaskc(), + BurnDownWeeklyTask(), + BurnDownMonthlyTaskc(), + ], + ), ), - ], - ) - : Obx( - () => IndexedStack( - index: reportsController.selectedIndex.value, - children: [ - BurnDownDailyTaskc(), - BurnDownWeeklyTask(), - BurnDownMonthlyTaskc(), - ], - ), - ), - ); + ))); }, ); } diff --git a/lib/app/utils/app_settings/save_tour_status.dart b/lib/app/utils/app_settings/save_tour_status.dart index 11b23689..ef1f7d3f 100644 --- a/lib/app/utils/app_settings/save_tour_status.dart +++ b/lib/app/utils/app_settings/save_tour_status.dart @@ -62,4 +62,14 @@ class SaveTourStatus { static Future getTaskSwipeTutorialStatus() async { return _preferences?.getBool('task_swipe_tutorial_completed') ?? false; } + + static Future resetTourStatus() async { + await _preferences?.remove('reports_tour'); + await _preferences?.remove('tour'); + await _preferences?.remove('filter_tour'); + await _preferences?.remove('profile_tour'); + await _preferences?.remove('details_tour'); + await _preferences?.remove('manage_task_server_tour'); + await _preferences?.remove('task_swipe_tutorial_completed'); + } } diff --git a/pubspec.lock b/pubspec.lock index c7182030..c39eaac9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8" + url: "https://pub.dev" + source: hosted + version: "6.4.1" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" archive: dependency: transitive description: @@ -65,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0" + build_cli_annotations: + dependency: transitive + description: + name: build_cli_annotations + sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 + url: "https://pub.dev" + source: hosted + version: "2.1.1" build_config: dependency: transitive description: @@ -297,14 +337,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - double_back_to_close_app: - dependency: "direct main" - description: - name: double_back_to_close_app - sha256: d19ce4e2f8d2cb9f35bdbc90eecd5c731cc0e6216f5e8f14e7d1e076dafb344a - url: "https://pub.dev" - source: hosted - version: "2.1.0" fake_async: dependency: transitive description: @@ -519,6 +551,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.32" + flutter_rust_bridge: + dependency: "direct main" + description: + name: flutter_rust_bridge + sha256: "37ef40bc6f863652e865f0b2563ea07f0d3c58d8efad803cc01933a4b2ee067e" + url: "https://pub.dev" + source: hosted + version: "2.11.1" flutter_slidable: dependency: "direct main" description: @@ -601,6 +641,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" hashcodes: dependency: transitive description: @@ -813,10 +861,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.16.0" mime: dependency: transitive description: @@ -1141,10 +1189,10 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "3.0.0" sizer: dependency: "direct main" description: @@ -1330,26 +1378,26 @@ packages: dependency: "direct main" description: name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" url: "https://pub.dev" source: hosted - version: "1.26.3" + version: "1.26.2" test_api: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.6" test_core: dependency: transitive description: name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" url: "https://pub.dev" source: hosted - version: "0.6.12" + version: "0.6.11" textfield_tags: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d8646792..a0d5bcb7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,6 @@ dependencies: crypto: ^3.0.1 cupertino_icons: ^1.0.5 date_format: ^2.0.6 - double_back_to_close_app: ^2.1.0 file_picker: ^9.0.2 file_picker_writable: git: