From fafc3ff0c7d422e6bc18a868b2a5a4bc48208457 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 2 Jun 2025 14:09:22 +0700 Subject: [PATCH] TF-3773 Change banner of Trash/Spam folder Signed-off-by: dab246 --- .../extensions/color_extension.dart | 1 + .../base/widget/clean_messages_banner.dart | 51 +++++++++++ .../mailbox_dashboard_view_web.dart | 60 +++++++++---- .../banner_delete_all_spam_emails_styles.dart | 41 --------- .../styles/banner_empty_trash_styles.dart | 41 --------- .../thread/presentation/thread_view.dart | 66 ++++++++++---- .../banner_delete_all_spam_emails_widget.dart | 84 ------------------ .../widgets/banner_empty_trash_widget.dart | 86 ------------------- 8 files changed, 143 insertions(+), 287 deletions(-) create mode 100644 lib/features/base/widget/clean_messages_banner.dart delete mode 100644 lib/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart delete mode 100644 lib/features/thread/presentation/styles/banner_empty_trash_styles.dart delete mode 100644 lib/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart delete mode 100644 lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index b22dbe2fe..29d5819cc 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -250,6 +250,7 @@ extension AppColor on Color { static const m3SurfaceBackground = Color(0xFF1C1B1F); static const warningColor = Color(0xFFFFC107); static const primaryMain = Color(0xFF0A84FF); + static const m3LayerDarkOutline = Color(0xFF938F99); static const mapGradientColor = [ [Color(0xFF21D4FD), Color(0xFFB721FF)], diff --git a/lib/features/base/widget/clean_messages_banner.dart b/lib/features/base/widget/clean_messages_banner.dart new file mode 100644 index 000000000..ed80372be --- /dev/null +++ b/lib/features/base/widget/clean_messages_banner.dart @@ -0,0 +1,51 @@ + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +class CleanMessagesBanner extends StatelessWidget { + final String message; + final String positiveAction; + final VoidCallback onPositiveAction; + final EdgeInsetsGeometry? margin; + + const CleanMessagesBanner({ + super.key, + required this.message, + required this.positiveAction, + required this.onPositiveAction, + this.margin, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.m3LayerDarkOutline.withOpacity(0.08), + borderRadius: const BorderRadius.all(Radius.circular(8)), + ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12), + margin: margin, + alignment: Alignment.center, + child: Text.rich( + TextSpan( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: AppColor.steelGray400, + ), + children: [ + TextSpan(text: '$message '), + TextSpan( + text: positiveAction, + style: ThemeUtils.textStyleInter700( + color: AppColor.blue700, + fontSize: 14, + ), + recognizer: TapGestureRecognizer()..onTap = onPositiveAction, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart index bad9460d6..dd61a86ae 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart @@ -6,6 +6,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/extensions/session_extension.dart'; +import 'package:tmail_ui_user/features/base/widget/clean_messages_banner.dart'; import 'package:tmail_ui_user/features/base/widget/popup_item_no_icon_widget.dart'; import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/web/composer_overlay_view.dart'; @@ -39,8 +40,6 @@ import 'package:tmail_ui_user/features/search/email/presentation/search_email_vi import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_view.dart'; import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart'; -import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart'; -import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_empty_trash_widget.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/spam_banner/spam_report_banner_web_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -113,22 +112,49 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView { QuotasBannerWidget(), _buildVacationNotificationMessage(context), Obx(() { - final presentationMailbox = controller.selectedMailbox.value; - if (controller.isEmptyTrashBannerEnabledOnWeb(context, presentationMailbox)) { - return BannerEmptyTrashWidget( - responsiveUtils: controller.responsiveUtils, - imagePaths: controller.imagePaths, - onTapAction: controller.emptyTrashAction, + final selectedMailbox = controller + .selectedMailbox + .value; + + bool showTrashBanner = controller + .isEmptyTrashBannerEnabledOnWeb( + context, + selectedMailbox, ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - final presentationMailbox = controller.selectedMailbox.value; - if (controller.isEmptySpamBannerEnabledOnWeb(context, presentationMailbox)) { - return BannerDeleteAllSpamEmailsWidget( - onTapAction: () => controller.openDialogEmptySpamFolder(context) + bool showSpamBanner = controller + .isEmptySpamBannerEnabledOnWeb( + context, + selectedMailbox, + ); + + if (showTrashBanner) { + return CleanMessagesBanner( + message: AppLocalizations + .of(context) + .message_delete_all_email_in_trash_button, + positiveAction: AppLocalizations + .of(context) + .empty_trash_now, + onPositiveAction: controller.emptyTrashAction, + margin: const EdgeInsetsDirectional.only( + bottom: 8, + end: 16, + ), + ); + } else if (showSpamBanner) { + return CleanMessagesBanner( + message: AppLocalizations + .of(context) + .bannerDeleteAllSpamEmailsMessage, + positiveAction: AppLocalizations + .of(context) + .deleteAllSpamEmailsNow, + onPositiveAction: () => + controller.openDialogEmptySpamFolder(context), + margin: const EdgeInsetsDirectional.only( + bottom: 8, + end: 16, + ), ); } else { return const SizedBox.shrink(); diff --git a/lib/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart b/lib/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart deleted file mode 100644 index f21f927b4..000000000 --- a/lib/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart +++ /dev/null @@ -1,41 +0,0 @@ - -import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:core/utils/platform_info.dart'; -import 'package:flutter/material.dart'; - -class BannerDeleteAllSpamEmailsStyles { - static const double borderRadius = 14; - static const double buttonBorderRadius = 20; - static const double horizontalPadding = 16; - static const double verticalPadding = 10; - static const double labelTextSize = 13; - static const double buttonTextSize = 17; - static const double iconSize = 20; - static const double space = 8; - static const Color backgroundColor = Colors.white; - static const Color borderStrokeColor = AppColor.colorBorderBodyThread; - static const Color labelTextColor = AppColor.colorSubtitle; - static const Color buttonTextColor = AppColor.toastErrorBackgroundColor; - - static EdgeInsetsGeometry getBannerMargin( - BuildContext context, - ResponsiveUtils responsiveUtils - ) { - if (PlatformInfo.isWeb) { - if (responsiveUtils.isDesktop(context)) { - return const EdgeInsetsDirectional.only(end: 16, bottom: 8); - } else if (responsiveUtils.isTablet(context)) { - return const EdgeInsetsDirectional.only(bottom: 8, start: 24, end: 24); - } else { - return const EdgeInsetsDirectional.only(bottom: 8, start: 12, end: 12); - } - } else { - if (responsiveUtils.isPortraitTablet(context)) { - return const EdgeInsetsDirectional.only(bottom: 8, start: 32, end: 32); - } else { - return const EdgeInsetsDirectional.only(bottom: 8, start: 16, end: 16); - } - } - } -} \ No newline at end of file diff --git a/lib/features/thread/presentation/styles/banner_empty_trash_styles.dart b/lib/features/thread/presentation/styles/banner_empty_trash_styles.dart deleted file mode 100644 index 2a026de6c..000000000 --- a/lib/features/thread/presentation/styles/banner_empty_trash_styles.dart +++ /dev/null @@ -1,41 +0,0 @@ - -import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:core/utils/platform_info.dart'; -import 'package:flutter/material.dart'; - -class BannerEmptyTrashStyles { - static const double borderRadius = 14; - static const double buttonBorderRadius = 20; - static const double horizontalPadding = 16; - static const double verticalPadding = 10; - static const double labelTextSize = 13; - static const double buttonTextSize = 17; - static const double iconSize = 20; - static const double space = 8; - static const Color backgroundColor = Colors.white; - static const Color borderStrokeColor = AppColor.colorBorderBodyThread; - static const Color labelTextColor = AppColor.colorSubtitle; - static const Color buttonTextColor = AppColor.toastErrorBackgroundColor; - - static EdgeInsetsGeometry getBannerMargin( - BuildContext context, - ResponsiveUtils responsiveUtils - ) { - if (PlatformInfo.isWeb) { - if (responsiveUtils.isDesktop(context)) { - return const EdgeInsetsDirectional.only(end: 16, bottom: 8); - } else if (responsiveUtils.isTablet(context)) { - return const EdgeInsetsDirectional.only(bottom: 8, start: 24, end: 24); - } else { - return const EdgeInsetsDirectional.only(bottom: 8, start: 12, end: 12); - } - } else { - if (responsiveUtils.isPortraitTablet(context)) { - return const EdgeInsetsDirectional.only(bottom: 8, start: 32, end: 32); - } else { - return const EdgeInsetsDirectional.only(bottom: 8, start: 16, end: 16); - } - } - } -} \ No newline at end of file diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index ef0777709..8112d670d 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -8,6 +8,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/base/mixin/popup_menu_widget_mixin.dart'; +import 'package:tmail_ui_user/features/base/widget/clean_messages_banner.dart'; import 'package:tmail_ui_user/features/base/widget/compose_floating_button.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart'; @@ -34,8 +35,6 @@ import 'package:tmail_ui_user/features/thread/presentation/styles/scroll_to_top_ import 'package:tmail_ui_user/features/thread/presentation/styles/thread_view_style.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart'; -import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart'; -import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_empty_trash_widget.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/bottom_bar_thread_selection_widget.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart' if (dart.library.html) 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_web_builder.dart'; @@ -149,26 +148,57 @@ class ThreadView extends GetWidget )), ], Obx(() { - final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value; - if (controller.mailboxDashBoardController.isEmptyTrashBannerEnabledOnMobile(context, presentationMailbox)) { - return BannerEmptyTrashWidget( + final dashboardController = controller + .mailboxDashBoardController; + final selectedMailbox = dashboardController + .selectedMailbox + .value; + + bool showTrashBanner = dashboardController + .isEmptyTrashBannerEnabledOnMobile( + context, + selectedMailbox, + ); + bool showSpamBanner = dashboardController + .isEmptySpamBannerEnabledOnMobile( + context, + selectedMailbox, + ); + + if (showTrashBanner) { + return CleanMessagesBanner( key: const Key('empty_trash_banner'), - responsiveUtils: controller.responsiveUtils, - imagePaths: controller.imagePaths, - onTapAction: () => controller.deleteSelectionEmailsPermanently( + message: AppLocalizations + .of(context) + .message_delete_all_email_in_trash_button, + positiveAction: AppLocalizations + .of(context) + .empty_trash_now, + onPositiveAction: () => + controller.deleteSelectionEmailsPermanently( + context, + DeleteActionType.all, + ), + margin: ThreadViewStyle.getBannerMargin( context, - DeleteActionType.all, + controller.responsiveUtils, ), ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value; - if (controller.mailboxDashBoardController.isEmptySpamBannerEnabledOnMobile(context, presentationMailbox)) { - return BannerDeleteAllSpamEmailsWidget( - onTapAction: () => controller.mailboxDashBoardController.openDialogEmptySpamFolder(context) + } else if (showSpamBanner) { + return CleanMessagesBanner( + message: AppLocalizations + .of(context) + .bannerDeleteAllSpamEmailsMessage, + positiveAction: AppLocalizations + .of(context) + .deleteAllSpamEmailsNow, + onPositiveAction: () => controller + .mailboxDashBoardController + .openDialogEmptySpamFolder(context), + margin: ThreadViewStyle.getBannerMargin( + context, + controller.responsiveUtils, + ), ); } else { return const SizedBox.shrink(); diff --git a/lib/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart b/lib/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart deleted file mode 100644 index 79671947f..000000000 --- a/lib/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart +++ /dev/null @@ -1,84 +0,0 @@ - -import 'package:core/presentation/resources/image_paths.dart'; -import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; -import 'package:tmail_ui_user/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart'; -import 'package:tmail_ui_user/features/thread/presentation/styles/banner_empty_trash_styles.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -class BannerDeleteAllSpamEmailsWidget extends StatelessWidget { - - final VoidCallback onTapAction; - - const BannerDeleteAllSpamEmailsWidget({super.key, required this.onTapAction}); - - @override - Widget build(BuildContext context) { - final imagePaths = Get.find(); - final responsiveUtils = Get.find(); - - return Container( - decoration: const ShapeDecoration( - color: BannerDeleteAllSpamEmailsStyles.backgroundColor, - shape: RoundedRectangleBorder( - side: BorderSide( - width: 1, - color: BannerDeleteAllSpamEmailsStyles.borderStrokeColor, - ), - borderRadius: BorderRadius.all(Radius.circular(BannerDeleteAllSpamEmailsStyles.borderRadius)), - ), - ), - margin: BannerEmptyTrashStyles.getBannerMargin(context, responsiveUtils), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: onTapAction, - borderRadius: const BorderRadius.all(Radius.circular(BannerDeleteAllSpamEmailsStyles.borderRadius)), - child: Padding( - padding: const EdgeInsetsDirectional.symmetric( - horizontal: BannerDeleteAllSpamEmailsStyles.horizontalPadding, - vertical: BannerDeleteAllSpamEmailsStyles.verticalPadding - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SvgPicture.asset( - imagePaths.icDeleteRuleMobile, - width: BannerDeleteAllSpamEmailsStyles.iconSize, - height: BannerDeleteAllSpamEmailsStyles.iconSize, - fit: BoxFit.fill - ), - const SizedBox(width: BannerDeleteAllSpamEmailsStyles.space), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context).deleteAllSpamEmailsNow, - style: const TextStyle( - fontSize: BannerDeleteAllSpamEmailsStyles.buttonTextSize, - fontWeight: FontWeight.w500, - color: BannerDeleteAllSpamEmailsStyles.buttonTextColor - ) - ), - Text( - AppLocalizations.of(context).bannerDeleteAllSpamEmailsMessage, - style: const TextStyle( - color: BannerDeleteAllSpamEmailsStyles.labelTextColor, - fontSize: BannerDeleteAllSpamEmailsStyles.labelTextSize, - fontWeight: FontWeight.w400 - ) - ), - ] - ) - ) - ] - ), - ), - ), - ), - ); - } -} diff --git a/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart b/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart deleted file mode 100644 index 9603be014..000000000 --- a/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart +++ /dev/null @@ -1,86 +0,0 @@ - -import 'package:core/presentation/resources/image_paths.dart'; -import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:tmail_ui_user/features/thread/presentation/styles/banner_empty_trash_styles.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -class BannerEmptyTrashWidget extends StatelessWidget { - - final VoidCallback onTapAction; - final ResponsiveUtils responsiveUtils; - final ImagePaths imagePaths; - - const BannerEmptyTrashWidget({ - super.key, - required this.responsiveUtils, - required this.imagePaths, - required this.onTapAction, - }); - - @override - Widget build(BuildContext context) { - return Container( - decoration: const ShapeDecoration( - color: BannerEmptyTrashStyles.backgroundColor, - shape: RoundedRectangleBorder( - side: BorderSide( - width: 1, - color: BannerEmptyTrashStyles.borderStrokeColor, - ), - borderRadius: BorderRadius.all(Radius.circular(BannerEmptyTrashStyles.borderRadius)), - ), - ), - margin: BannerEmptyTrashStyles.getBannerMargin(context, responsiveUtils), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: onTapAction, - borderRadius: const BorderRadius.all(Radius.circular(BannerEmptyTrashStyles.borderRadius)), - child: Padding( - padding: const EdgeInsetsDirectional.symmetric( - horizontal: BannerEmptyTrashStyles.horizontalPadding, - vertical: BannerEmptyTrashStyles.verticalPadding - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SvgPicture.asset( - imagePaths.icDeleteRuleMobile, - width: BannerEmptyTrashStyles.iconSize, - height: BannerEmptyTrashStyles.iconSize, - fit: BoxFit.fill - ), - const SizedBox(width: BannerEmptyTrashStyles.space), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context).empty_trash_now, - style: const TextStyle( - fontSize: BannerEmptyTrashStyles.buttonTextSize, - fontWeight: FontWeight.w500, - color: BannerEmptyTrashStyles.buttonTextColor - ) - ), - Text( - AppLocalizations.of(context).message_delete_all_email_in_trash_button, - style: const TextStyle( - color: BannerEmptyTrashStyles.labelTextColor, - fontSize: BannerEmptyTrashStyles.labelTextSize, - fontWeight: FontWeight.w400 - ) - ), - ] - ) - ) - ] - ), - ), - ), - ), - ); - } -}