From 6c069d69f692043b707c937f803bf32c5da48919 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 5 Aug 2025 13:39:44 +0700 Subject: [PATCH] TF-3939 Display minor action on menu in mobile search view Signed-off-by: dab246 --- .../widgets/top_bar_thread_selection.dart | 115 +++++++-------- .../handle_press_email_selection_action.dart | 91 ++++++++++++ .../presentation/search_email_controller.dart | 7 + .../email/presentation/search_email_view.dart | 53 ++++++- .../widgets/app_bar_selection_mode.dart | 139 ------------------ .../thread/presentation/thread_view.dart | 2 +- .../app_bar/app_bar_thread_widget.dart | 10 +- .../default_mobile_app_bar_thread_widget.dart | 90 +++++------- .../app_bar/mobile_app_bar_thread_widget.dart | 9 +- ...election_mobile_app_bar_thread_widget.dart | 10 +- .../selection_web_app_bar_thread_widget.dart | 15 +- .../app_bar/web_app_bar_thread_widget.dart | 10 +- .../list_presentation_email_extension.dart | 58 +++----- 13 files changed, 280 insertions(+), 329 deletions(-) create mode 100644 lib/features/search/email/presentation/extension/handle_press_email_selection_action.dart delete mode 100644 lib/features/search/email/presentation/widgets/app_bar_selection_mode.dart diff --git a/lib/features/mailbox_dashboard/presentation/widgets/top_bar_thread_selection.dart b/lib/features/mailbox_dashboard/presentation/widgets/top_bar_thread_selection.dart index e9bb1bc96..7ac4d4cb8 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/top_bar_thread_selection.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/top_bar_thread_selection.dart @@ -34,10 +34,8 @@ class TopBarThreadSelection extends StatelessWidget{ @override Widget build(BuildContext context) { - final canDeletePermanently = listEmail.isAllCanDeletePermanently(mapMailbox); - final canSpamAndMove = listEmail.isAllCanSpamAndMove(mapMailbox); - final isAllSpam = listEmail.isAllSpam(mapMailbox); - final isAllBelongToTheSameMailbox = listEmail.isAllBelongToTheSameMailbox(mapMailbox); + final isDeletePermanentlyDisabled = listEmail.isDeletePermanentlyDisabled(mapMailbox); + final isMarkAsSpamEnabled = listEmail.isMarkAsSpamEnabled(mapMailbox); final isAllEmailRead = listEmail.isAllEmailRead; final isAllEmailStarred = listEmail.isAllEmailStarred; @@ -92,68 +90,59 @@ class TopBarThreadSelection extends StatelessWidget{ List.from(listEmail), isAllEmailStarred ? EmailActionType.unMarkAsStarred - : EmailActionType.markAsStarred - ) + : EmailActionType.markAsStarred, + ), ), - if (canSpamAndMove) - ...[ - TMailButtonWidget.fromIcon( - icon: imagePaths.icMoveMailbox, - iconSize: TopBarThreadSelectionStyle.iconSize, - iconColor: TopBarThreadSelectionStyle.iconColor, - tooltipMessage: AppLocalizations.of(context).move, - backgroundColor: Colors.transparent, - onTapActionCallback: () => onEmailActionTypeAction?.call( - List.from(listEmail), - EmailActionType.moveToMailbox - ) - ), - TMailButtonWidget.fromIcon( - icon: isAllSpam ? imagePaths.icNotSpam : imagePaths.icSpam, - backgroundColor: Colors.transparent, - iconSize: TopBarThreadSelectionStyle.iconSize, - iconColor: TopBarThreadSelectionStyle.iconColor, - tooltipMessage: isAllSpam - ? AppLocalizations.of(context).un_spam - : AppLocalizations.of(context).mark_as_spam, - onTapActionCallback: () { - if (isAllSpam) { - onEmailActionTypeAction?.call( - List.from(listEmail), - EmailActionType.unSpam - ); - } else { - onEmailActionTypeAction?.call( - List.from(listEmail.listEmailCanSpam(mapMailbox)), - EmailActionType.moveToSpam - ); - } - } - ) - ], - if (isAllBelongToTheSameMailbox) - TMailButtonWidget.fromIcon( - icon: imagePaths.icDeleteComposer, - backgroundColor: Colors.transparent, - iconSize: TopBarThreadSelectionStyle.iconSize, - iconColor: TopBarThreadSelectionStyle.iconColor, - tooltipMessage: canDeletePermanently + TMailButtonWidget.fromIcon( + icon: imagePaths.icMoveMailbox, + iconSize: TopBarThreadSelectionStyle.iconSize, + iconColor: TopBarThreadSelectionStyle.iconColor, + tooltipMessage: AppLocalizations.of(context).move, + backgroundColor: Colors.transparent, + onTapActionCallback: () => onEmailActionTypeAction?.call( + List.from(listEmail), + EmailActionType.moveToMailbox, + ), + ), + TMailButtonWidget.fromIcon( + icon: !isMarkAsSpamEnabled ? imagePaths.icNotSpam : imagePaths.icSpam, + backgroundColor: Colors.transparent, + iconSize: TopBarThreadSelectionStyle.iconSize, + iconColor: TopBarThreadSelectionStyle.iconColor, + tooltipMessage: !isMarkAsSpamEnabled + ? AppLocalizations.of(context).un_spam + : AppLocalizations.of(context).mark_as_spam, + onTapActionCallback: () { + if (!isMarkAsSpamEnabled) { + onEmailActionTypeAction?.call( + List.from(listEmail), + EmailActionType.unSpam, + ); + } else { + onEmailActionTypeAction?.call( + List.from(listEmail.listEmailCanSpam(mapMailbox)), + EmailActionType.moveToSpam, + ); + } + }, + ), + TMailButtonWidget.fromIcon( + icon: imagePaths.icDeleteComposer, + backgroundColor: Colors.transparent, + iconSize: TopBarThreadSelectionStyle.iconSize, + iconColor: TopBarThreadSelectionStyle.iconColor, + tooltipMessage: !isDeletePermanentlyDisabled ? AppLocalizations.of(context).delete_permanently : AppLocalizations.of(context).move_to_trash, - onTapActionCallback: () { - if (canDeletePermanently) { - onEmailActionTypeAction?.call( - List.from(listEmail), - EmailActionType.deletePermanently - ); - } else { - onEmailActionTypeAction?.call( - List.from(listEmail), - EmailActionType.moveToTrash - ); - } - } - ), + onTapActionCallback: () { + onEmailActionTypeAction?.call( + List.from(listEmail), + isDeletePermanentlyDisabled + ? EmailActionType.moveToTrash + : EmailActionType.deletePermanently, + ); + }, + ), ]); } } \ No newline at end of file diff --git a/lib/features/search/email/presentation/extension/handle_press_email_selection_action.dart b/lib/features/search/email/presentation/extension/handle_press_email_selection_action.dart new file mode 100644 index 000000000..41a5309f3 --- /dev/null +++ b/lib/features/search/email/presentation/extension/handle_press_email_selection_action.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/email/presentation_email.dart'; +import 'package:model/extensions/list_presentation_email_extension.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/context_item_email_action.dart'; +import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart'; +import 'package:tmail_ui_user/features/thread/presentation/extensions/email_selection_action_type_extension.dart'; +import 'package:tmail_ui_user/features/thread/presentation/extensions/list_email_selection_action_type_extension.dart'; +import 'package:tmail_ui_user/features/thread/presentation/model/email_selection_action_type.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; + +extension HandlePressEmailSelectionActionExtension on SearchEmailController { + void handlePressEmailSelectionAction( + BuildContext context, + EmailSelectionActionType type, + List emails, + Map mapMailboxById, + ) { + final emailActionType = type.toEmailActionType(); + if (emailActionType != null) { + handleSelectionEmailAction(emailActionType, emails); + } else if (type == EmailSelectionActionType.moreAction) { + _showMoreActionMenu(context, emails, mapMailboxById); + } else if (type == EmailSelectionActionType.selectAll) { + _showSelectAllEmails(); + } + } + + List _createEmailSelectionActionTypes( + List emails, + Map mapMailboxById, + ) { + return [ + if (emails.isAllEmailRead) + EmailSelectionActionType.markAsUnread + else + EmailSelectionActionType.markAsRead, + if (emails.isAllEmailStarred) + EmailSelectionActionType.unMarkAsStarred + else + EmailSelectionActionType.markAsStarred, + EmailSelectionActionType.moveToFolder, + if (emails.isDeletePermanentlyDisabled(mapMailboxById)) + EmailSelectionActionType.moveToTrash, + if (emails.isMarkAsSpamEnabled(mapMailboxById)) + EmailSelectionActionType.markAsSpam + else + EmailSelectionActionType.markAsNotSpam, + if (emails.isArchiveMessageEnabled(mapMailboxById)) + EmailSelectionActionType.archiveMessage, + if (!emails.isDeletePermanentlyDisabled(mapMailboxById)) + EmailSelectionActionType.deletePermanently, + ]; + } + + Future _showMoreActionMenu( + BuildContext context, + List emails, + Map mapMailboxById, + ) async { + final emailActions = _createEmailSelectionActionTypes( + emails, + mapMailboxById, + ).emailActionTypes; + + final contextMenuActions = emailActions + .map((action) => ContextItemEmailAction( + action, + AppLocalizations.of(context), + imagePaths, + )) + .toList(); + + return openBottomSheetContextMenuAction( + context: context, + itemActions: contextMenuActions, + onContextMenuActionClick: (menuAction) { + popBack(); + handleSelectionEmailAction(menuAction.action, emails); + }, + ); + } + + void _showSelectAllEmails() { + if (listResultSearch.isAnySelectionInActive) { + setSelectAllEmailAction(); + } + } +} diff --git a/lib/features/search/email/presentation/search_email_controller.dart b/lib/features/search/email/presentation/search_email_controller.dart index de16c4323..54899fa44 100644 --- a/lib/features/search/email/presentation/search_email_controller.dart +++ b/lib/features/search/email/presentation/search_email_controller.dart @@ -928,6 +928,13 @@ class SearchEmailController extends BaseController selectionMode.value = SelectMode.INACTIVE; } + void setSelectAllEmailAction() { + listResultSearch.value = listResultSearch + .map((email) => email.toSelectedEmail(selectMode: SelectMode.ACTIVE)) + .toList(); + selectionMode.value = SelectMode.ACTIVE; + } + void handleSelectionEmailAction( EmailActionType actionType, List listEmails diff --git a/lib/features/search/email/presentation/search_email_view.dart b/lib/features/search/email/presentation/search_email_view.dart index 5d0227bb6..3427bafa4 100644 --- a/lib/features/search/email/presentation/search_email_view.dart +++ b/lib/features/search/email/presentation/search_email_view.dart @@ -11,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.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/widget/popup_menu/popup_menu_item_action_widget.dart'; @@ -24,6 +25,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/qu import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/recent_search_item_tile_widget.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart'; import 'package:tmail_ui_user/features/search/email/presentation/extension/handle_email_more_action_extension.dart'; +import 'package:tmail_ui_user/features/search/email/presentation/extension/handle_press_email_selection_action.dart'; import 'package:tmail_ui_user/features/search/email/presentation/model/context_item_receive_time_type_action.dart'; import 'package:tmail_ui_user/features/search/email/presentation/model/context_item_sort_order_type_action.dart'; import 'package:tmail_ui_user/features/search/email/presentation/model/popup_menu_item_date_filter_action.dart'; @@ -32,12 +34,13 @@ import 'package:tmail_ui_user/features/search/email/presentation/model/search_mo import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart'; import 'package:tmail_ui_user/features/search/email/presentation/styles/search_email_view_style.dart'; import 'package:tmail_ui_user/features/search/email/presentation/utils/search_email_utils.dart'; -import 'package:tmail_ui_user/features/search/email/presentation/widgets/app_bar_selection_mode.dart'; import 'package:tmail_ui_user/features/search/email/presentation/widgets/empty_search_email_widget.dart'; import 'package:tmail_ui_user/features/search/email/presentation/widgets/search_email_loading_bar_widget.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/domain/state/search_more_email_state.dart'; +import 'package:tmail_ui_user/features/thread/presentation/model/email_selection_action_type.dart'; import 'package:tmail_ui_user/features/thread/presentation/styles/item_email_tile_styles.dart'; +import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_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'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -77,11 +80,29 @@ class SearchEmailView extends GetWidget ), child: Obx(() { if (controller.selectionMode.value == SelectMode.ACTIVE) { - return AppBarSelectionMode( - controller.listResultSearch.listEmailSelected, - controller.mailboxDashBoardController.mapMailboxById, - onCancelSelection: controller.cancelSelectionMode, - onHandleEmailAction: controller.handleSelectionEmailAction); + final mapMailboxById = controller.mailboxDashBoardController.mapMailboxById; + final selectedEmails = controller.listResultSearch.listEmailSelected; + + final actionTypes = _createEmailSelectionActionTypes( + mapMailboxById, + selectedEmails, + ); + + return SelectionMobileAppBarThreadWidget( + imagePaths: controller.imagePaths, + responsiveUtils: controller.responsiveUtils, + selectedEmails: selectedEmails, + padding: EdgeInsets.zero, + onCancelSelectionAction: controller.cancelSelectionMode, + emailSelectionActionTypes: actionTypes, + onPressEmailSelectionActionClick: (type, emails) => + controller.handlePressEmailSelectionAction( + context, + type, + emails, + mapMailboxById, + ), + ); } else { return _buildSearchInputForm(context); } @@ -135,6 +156,26 @@ class SearchEmailView extends GetWidget ); } + List _createEmailSelectionActionTypes( + Map mapMailboxById, + List selectedEmails, + ) { + return [ + EmailSelectionActionType.selectAll, + if (selectedEmails.isArchiveMessageEnabled(mapMailboxById)) + EmailSelectionActionType.archiveMessage, + if (selectedEmails.isDeletePermanentlyDisabled(mapMailboxById)) + EmailSelectionActionType.moveToTrash + else + EmailSelectionActionType.deletePermanently, + if (selectedEmails.isAllEmailRead) + EmailSelectionActionType.markAsUnread + else + EmailSelectionActionType.markAsRead, + EmailSelectionActionType.moreAction, + ]; + } + Widget _buildSearchInputForm(BuildContext context) { return Row( children: [ diff --git a/lib/features/search/email/presentation/widgets/app_bar_selection_mode.dart b/lib/features/search/email/presentation/widgets/app_bar_selection_mode.dart deleted file mode 100644 index 9a9e31f4d..000000000 --- a/lib/features/search/email/presentation/widgets/app_bar_selection_mode.dart +++ /dev/null @@ -1,139 +0,0 @@ - -import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/resources/image_paths.dart'; -import 'package:core/presentation/utils/theme_utils.dart'; -import 'package:core/presentation/views/button/tmail_button_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; -import 'package:model/email/email_action_type.dart'; -import 'package:model/email/presentation_email.dart'; -import 'package:model/extensions/list_presentation_email_extension.dart'; -import 'package:model/mailbox/presentation_mailbox.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -class AppBarSelectionMode extends StatelessWidget { - - final _imagePaths = Get.find(); - - final List listEmail; - final Map mapMailbox; - final Function()? onCancelSelection; - final Function(EmailActionType actionType, List emails)? onHandleEmailAction; - - AppBarSelectionMode( - this.listEmail, - this.mapMailbox, { - Key? key, - this.onCancelSelection, - this.onHandleEmailAction, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final canDeletePermanently = listEmail.isAllCanDeletePermanently(mapMailbox); - final canSpamAndMove = listEmail.isAllCanSpamAndMove(mapMailbox); - final isAllSpam = listEmail.isAllSpam(mapMailbox); - final isAllBelongToTheSameMailbox = listEmail.isAllBelongToTheSameMailbox(mapMailbox); - - return Row(children: [ - TMailButtonWidget.fromIcon( - icon: _imagePaths.icClose, - iconSize: 25, - iconColor: AppColor.colorTextButton, - backgroundColor: Colors.transparent, - tooltipMessage: AppLocalizations.of(context).cancel, - onTapActionCallback: onCancelSelection, - ), - Expanded( - child: Text( - AppLocalizations.of(context).count_email_selected(listEmail.length), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: ThemeUtils.defaultTextStyleInterFont.copyWith( - fontSize: 17, - fontWeight: FontWeight.w500, - color: AppColor.colorTextButton - ) - ) - ), - TMailButtonWidget.fromIcon( - icon: listEmail.isAllEmailRead - ? _imagePaths.icUnread - : _imagePaths.icRead, - iconSize: 25, - backgroundColor: Colors.transparent, - tooltipMessage: listEmail.isAllEmailRead - ? AppLocalizations.of(context).unread - : AppLocalizations.of(context).read, - onTapActionCallback: () => onHandleEmailAction?.call( - listEmail.isAllEmailRead - ? EmailActionType.markAsUnread - : EmailActionType.markAsRead, - listEmail - ), - ), - const SizedBox(width: 5), - TMailButtonWidget.fromIcon( - icon: listEmail.isAllEmailStarred - ? _imagePaths.icUnStar - : _imagePaths.icStar, - iconSize: 25, - backgroundColor: Colors.transparent, - tooltipMessage: listEmail.isAllEmailStarred - ? AppLocalizations.of(context).not_starred - : AppLocalizations.of(context).starred, - onTapActionCallback: () => onHandleEmailAction?.call( - listEmail.isAllEmailStarred - ? EmailActionType.unMarkAsStarred - : EmailActionType.markAsStarred, - listEmail - ), - ), - const SizedBox(width: 5), - if (canSpamAndMove) - ... [ - TMailButtonWidget.fromIcon( - icon: _imagePaths.icMove, - iconSize: 25, - backgroundColor: Colors.transparent, - tooltipMessage: AppLocalizations.of(context).move, - onTapActionCallback: () => onHandleEmailAction?.call( - EmailActionType.moveToMailbox, - listEmail - ), - ), - const SizedBox(width: 5), - TMailButtonWidget.fromIcon( - icon: isAllSpam - ? _imagePaths.icNotSpam - : _imagePaths.icSpam, - iconSize: 25, - backgroundColor: Colors.transparent, - tooltipMessage: isAllSpam - ? AppLocalizations.of(context).un_spam - : AppLocalizations.of(context).mark_as_spam, - onTapActionCallback: () => isAllSpam - ? onHandleEmailAction?.call(EmailActionType.unSpam, listEmail) - : onHandleEmailAction?.call(EmailActionType.moveToSpam, listEmail.listEmailCanSpam(mapMailbox)), - ), - const SizedBox(width: 5), - ], - if (isAllBelongToTheSameMailbox) - TMailButtonWidget.fromIcon( - icon: _imagePaths.icDeleteComposer, - iconSize: 20, - backgroundColor: Colors.transparent, - iconColor: canDeletePermanently - ? AppColor.colorDeletePermanentlyButton - : AppColor.primaryColor, - tooltipMessage: canDeletePermanently - ? AppLocalizations.of(context).delete_permanently - : AppLocalizations.of(context).move_to_trash, - onTapActionCallback: () => canDeletePermanently - ? onHandleEmailAction?.call(EmailActionType.deletePermanently, listEmail) - : onHandleEmailAction?.call(EmailActionType.moveToTrash, listEmail), - ), - ]); - } -} \ 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 7424dd35f..7aed43b52 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -83,7 +83,7 @@ class ThreadView extends GetWidget selectMode: controller.mailboxDashBoardController.currentSelectMode.value, filterOption: controller.mailboxDashBoardController.filterMessageOption.value, openMailboxAction: controller.openMailboxLeftMenu, - cancelEditThreadAction: controller.cancelSelectEmail, + onCancelSelectionAction: controller.cancelSelectEmail, emailSelectionAction: controller.pressEmailSelectionAction, onContextMenuFilterEmailAction: controller.responsiveUtils.isScreenWithShortestSide(context) ? (filterOption) => controller.handleSelectMessageFilter(context, filterOption) diff --git a/lib/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart index eb1f53bea..b04004426 100644 --- a/lib/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart @@ -19,7 +19,7 @@ typedef OnContextMenuFilterEmailAction = void Function( FilterMessageOption option, ); typedef OnOpenMailboxMenuActionClick = void Function(); -typedef OnCancelEditThreadAction = void Function(); +typedef OnCancelSelectionAction = void Function(); typedef OnEmailSelectionAction = void Function( EmailActionType type, List emails, @@ -35,7 +35,7 @@ class AppBarThreadWidget extends StatelessWidget { final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction; final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction; final OnOpenMailboxMenuActionClick openMailboxAction; - final OnCancelEditThreadAction cancelEditThreadAction; + final OnCancelSelectionAction onCancelSelectionAction; final OnEmailSelectionAction emailSelectionAction; final PresentationMailbox? mailboxSelected; final List listEmailSelected; @@ -52,7 +52,7 @@ class AppBarThreadWidget extends StatelessWidget { required this.selectMode, required this.filterOption, required this.openMailboxAction, - required this.cancelEditThreadAction, + required this.onCancelSelectionAction, required this.emailSelectionAction, this.onPopupMenuFilterEmailAction, this.onContextMenuFilterEmailAction, @@ -71,7 +71,7 @@ class AppBarThreadWidget extends StatelessWidget { selectMode: selectMode, filterOption: filterOption, openMailboxAction: openMailboxAction, - cancelEditThreadAction: cancelEditThreadAction, + onCancelSelectionAction: onCancelSelectionAction, emailSelectionAction: emailSelectionAction, onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction, onContextMenuFilterEmailAction: onContextMenuFilterEmailAction, @@ -86,7 +86,7 @@ class AppBarThreadWidget extends StatelessWidget { selectMode: selectMode, filterOption: filterOption, openMailboxAction: openMailboxAction, - cancelEditThreadAction: cancelEditThreadAction, + onCancelSelectionAction: onCancelSelectionAction, onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction, onContextMenuFilterEmailAction: onContextMenuFilterEmailAction, onPressEmailSelectionActionClick: onPressEmailSelectionActionClick, diff --git a/lib/features/thread/presentation/widgets/app_bar/default_mobile_app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/default_mobile_app_bar_thread_widget.dart index 03315b8e5..b7f5a95f8 100644 --- a/lib/features/thread/presentation/widgets/app_bar/default_mobile_app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/default_mobile_app_bar_thread_widget.dart @@ -3,9 +3,7 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:flutter/material.dart'; -import 'package:model/email/presentation_email.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; -import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart'; import 'package:tmail_ui_user/features/thread/presentation/styles/app_bar/mobile_app_bar_thread_widget_style.dart'; @@ -17,73 +15,65 @@ class DefaultMobileAppBarThreadWidget extends StatelessWidget { final ResponsiveUtils responsiveUtils; final ImagePaths imagePaths; final PresentationMailbox? mailboxSelected; - final List listEmailSelected; - final SelectMode selectMode; final FilterMessageOption filterOption; final OnOpenMailboxMenuActionClick openMailboxAction; final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction; final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction; - final OnCancelEditThreadAction cancelEditThreadAction; const DefaultMobileAppBarThreadWidget({ super.key, required this.responsiveUtils, required this.imagePaths, - required this.listEmailSelected, required this.mailboxSelected, - required this.selectMode, required this.filterOption, required this.openMailboxAction, - required this.cancelEditThreadAction, this.onPopupMenuFilterEmailAction, this.onContextMenuFilterEmailAction, }); @override Widget build(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - return Container( - color: MobileAppBarThreadWidgetStyle.backgroundColor, - padding: MobileAppBarThreadWidgetStyle.getPadding( - context, - responsiveUtils, - ), - height: MobileAppBarThreadWidgetStyle.height, - child: Row( - children: [ - TMailButtonWidget.fromIcon( - key: const Key('mobile_mailbox_menu_button'), - icon: imagePaths.icMenuDrawer, - backgroundColor: Colors.transparent, - padding: MobileAppBarThreadWidgetStyle.mailboxMenuPadding, - maxWidth: MobileAppBarThreadWidgetStyle.buttonMaxWidth, - tooltipMessage: AppLocalizations.of(context).openFolderMenu, - onTapActionCallback: openMailboxAction, - ), - Expanded( - child: Padding( - padding: MobileAppBarThreadWidgetStyle.titlePadding, - child: Text( - mailboxSelected?.getDisplayName(context) ?? '', - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: MobileAppBarThreadWidgetStyle.titleTextStyle - ), + return Container( + color: MobileAppBarThreadWidgetStyle.backgroundColor, + padding: MobileAppBarThreadWidgetStyle.getPadding( + context, + responsiveUtils, + ), + height: MobileAppBarThreadWidgetStyle.height, + child: Row( + children: [ + TMailButtonWidget.fromIcon( + key: const Key('mobile_mailbox_menu_button'), + icon: imagePaths.icMenuDrawer, + backgroundColor: Colors.transparent, + padding: MobileAppBarThreadWidgetStyle.mailboxMenuPadding, + maxWidth: MobileAppBarThreadWidgetStyle.buttonMaxWidth, + tooltipMessage: AppLocalizations.of(context).openFolderMenu, + onTapActionCallback: openMailboxAction, + ), + Expanded( + child: Padding( + padding: MobileAppBarThreadWidgetStyle.titlePadding, + child: Text( + mailboxSelected?.getDisplayName(context) ?? '', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: MobileAppBarThreadWidgetStyle.titleTextStyle, ), ), - TMailButtonWidget.fromIcon( - key: const Key('mobile_filter_message_button'), - icon: imagePaths.icFilter, - iconColor: MobileAppBarThreadWidgetStyle.getFilterButtonColor(filterOption), - backgroundColor: Colors.transparent, - maxWidth: MobileAppBarThreadWidgetStyle.buttonMaxWidth, - tooltipMessage: AppLocalizations.of(context).filter_messages, - onTapActionCallback: () => onContextMenuFilterEmailAction?.call(filterOption), - onTapActionAtPositionCallback: (position) => onPopupMenuFilterEmailAction?.call(filterOption, position), - ), - ] - ), - ); - }); + ), + TMailButtonWidget.fromIcon( + key: const Key('mobile_filter_message_button'), + icon: imagePaths.icFilter, + iconColor: MobileAppBarThreadWidgetStyle.getFilterButtonColor(filterOption), + backgroundColor: Colors.transparent, + maxWidth: MobileAppBarThreadWidgetStyle.buttonMaxWidth, + tooltipMessage: AppLocalizations.of(context).filter_messages, + onTapActionCallback: () => onContextMenuFilterEmailAction?.call(filterOption), + onTapActionAtPositionCallback: (position) => onPopupMenuFilterEmailAction?.call(filterOption, position), + ), + ], + ), + ); } } diff --git a/lib/features/thread/presentation/widgets/app_bar/mobile_app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/mobile_app_bar_thread_widget.dart index b88524459..a4662b764 100644 --- a/lib/features/thread/presentation/widgets/app_bar/mobile_app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/mobile_app_bar_thread_widget.dart @@ -22,7 +22,7 @@ class MobileAppBarThreadWidget extends StatelessWidget { final OnOpenMailboxMenuActionClick openMailboxAction; final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction; final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction; - final OnCancelEditThreadAction cancelEditThreadAction; + final OnCancelSelectionAction onCancelSelectionAction; final OnPressEmailSelectionActionClick? onPressEmailSelectionActionClick; const MobileAppBarThreadWidget({ @@ -34,7 +34,7 @@ class MobileAppBarThreadWidget extends StatelessWidget { required this.selectMode, required this.filterOption, required this.openMailboxAction, - required this.cancelEditThreadAction, + required this.onCancelSelectionAction, this.onPopupMenuFilterEmailAction, this.onContextMenuFilterEmailAction, this.onPressEmailSelectionActionClick, @@ -62,7 +62,7 @@ class MobileAppBarThreadWidget extends StatelessWidget { imagePaths: imagePaths, responsiveUtils: responsiveUtils, selectedEmails: listEmailSelected, - cancelEditThreadAction: cancelEditThreadAction, + onCancelSelectionAction: onCancelSelectionAction, emailSelectionActionTypes: actionTypes, onPressEmailSelectionActionClick: (type, emails) => onPressEmailSelectionActionClick?.call(type, emails), @@ -71,12 +71,9 @@ class MobileAppBarThreadWidget extends StatelessWidget { return DefaultMobileAppBarThreadWidget( imagePaths: imagePaths, responsiveUtils: responsiveUtils, - listEmailSelected: listEmailSelected, mailboxSelected: mailboxSelected, - selectMode: selectMode, filterOption: filterOption, openMailboxAction: openMailboxAction, - cancelEditThreadAction: cancelEditThreadAction, onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction, onContextMenuFilterEmailAction: onContextMenuFilterEmailAction, ); diff --git a/lib/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_widget.dart index 6f0a3aeae..d371634e9 100644 --- a/lib/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_widget.dart @@ -14,7 +14,8 @@ class SelectionMobileAppBarThreadWidget extends StatelessWidget { final List selectedEmails; final List emailSelectionActionTypes; final OnPressEmailSelectionActionClick onPressEmailSelectionActionClick; - final OnCancelEditThreadAction cancelEditThreadAction; + final OnCancelSelectionAction onCancelSelectionAction; + final EdgeInsetsGeometry? padding; const SelectionMobileAppBarThreadWidget({ super.key, @@ -23,14 +24,15 @@ class SelectionMobileAppBarThreadWidget extends StatelessWidget { required this.selectedEmails, required this.emailSelectionActionTypes, required this.onPressEmailSelectionActionClick, - required this.cancelEditThreadAction, + required this.onCancelSelectionAction, + this.padding, }); @override Widget build(BuildContext context) { return Container( color: MobileAppBarThreadWidgetStyle.backgroundColor, - padding: MobileAppBarThreadWidgetStyle.getPadding( + padding: padding ?? MobileAppBarThreadWidgetStyle.getPadding( context, responsiveUtils, ), @@ -54,7 +56,7 @@ class SelectionMobileAppBarThreadWidget extends StatelessWidget { flexibleText: true, mainAxisSize: MainAxisSize.min, maxLines: 1, - onTapActionCallback: cancelEditThreadAction, + onTapActionCallback: onCancelSelectionAction, ), ) ], diff --git a/lib/features/thread/presentation/widgets/app_bar/selection_web_app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/selection_web_app_bar_thread_widget.dart index 05a3b56cc..4da65137a 100644 --- a/lib/features/thread/presentation/widgets/app_bar/selection_web_app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/selection_web_app_bar_thread_widget.dart @@ -9,7 +9,6 @@ import 'package:model/email/presentation_email.dart'; import 'package:model/extensions/list_presentation_email_extension.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; -import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart'; import 'package:tmail_ui_user/features/thread/presentation/styles/app_bar/selection_web_app_bar_thread_widget_style.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -20,12 +19,8 @@ class SelectionWebAppBarThreadWidget extends StatelessWidget { final ImagePaths imagePaths; final PresentationMailbox? mailboxSelected; final List listEmailSelected; - final FilterMessageOption filterOption; - final OnOpenMailboxMenuActionClick openMailboxAction; - final OnCancelEditThreadAction cancelEditThreadAction; + final OnCancelSelectionAction onCancelSelectionAction; final OnEmailSelectionAction emailSelectionAction; - final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction; - final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction; const SelectionWebAppBarThreadWidget({ super.key, @@ -33,12 +28,8 @@ class SelectionWebAppBarThreadWidget extends StatelessWidget { required this.imagePaths, required this.listEmailSelected, required this.mailboxSelected, - required this.filterOption, - required this.openMailboxAction, - required this.cancelEditThreadAction, + required this.onCancelSelectionAction, required this.emailSelectionAction, - this.onPopupMenuFilterEmailAction, - this.onContextMenuFilterEmailAction, }); @override @@ -57,7 +48,7 @@ class SelectionWebAppBarThreadWidget extends StatelessWidget { iconColor: SelectionWebAppBarThreadWidgetStyle.iconColor, iconSize: SelectionWebAppBarThreadWidgetStyle.iconSize, tooltipMessage: AppLocalizations.of(context).cancel, - onTapActionCallback: cancelEditThreadAction, + onTapActionCallback: onCancelSelectionAction, ), Expanded( child: Text( diff --git a/lib/features/thread/presentation/widgets/app_bar/web_app_bar_thread_widget.dart b/lib/features/thread/presentation/widgets/app_bar/web_app_bar_thread_widget.dart index 18a95a40d..fa2173164 100644 --- a/lib/features/thread/presentation/widgets/app_bar/web_app_bar_thread_widget.dart +++ b/lib/features/thread/presentation/widgets/app_bar/web_app_bar_thread_widget.dart @@ -19,7 +19,7 @@ class WebAppBarThreadWidget extends StatelessWidget { final SelectMode selectMode; final FilterMessageOption filterOption; final OnOpenMailboxMenuActionClick openMailboxAction; - final OnCancelEditThreadAction cancelEditThreadAction; + final OnCancelSelectionAction onCancelSelectionAction; final OnEmailSelectionAction emailSelectionAction; final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction; final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction; @@ -33,7 +33,7 @@ class WebAppBarThreadWidget extends StatelessWidget { required this.selectMode, required this.filterOption, required this.openMailboxAction, - required this.cancelEditThreadAction, + required this.onCancelSelectionAction, required this.emailSelectionAction, this.onPopupMenuFilterEmailAction, this.onContextMenuFilterEmailAction, @@ -59,12 +59,8 @@ class WebAppBarThreadWidget extends StatelessWidget { responsiveUtils: responsiveUtils, listEmailSelected: listEmailSelected, mailboxSelected: mailboxSelected, - filterOption: filterOption, - openMailboxAction: openMailboxAction, - cancelEditThreadAction: cancelEditThreadAction, + onCancelSelectionAction: onCancelSelectionAction, emailSelectionAction: emailSelectionAction, - onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction, - onContextMenuFilterEmailAction: onContextMenuFilterEmailAction, ); } } diff --git a/model/lib/extensions/list_presentation_email_extension.dart b/model/lib/extensions/list_presentation_email_extension.dart index 872a24349..36041c7c2 100644 --- a/model/lib/extensions/list_presentation_email_extension.dart +++ b/model/lib/extensions/list_presentation_email_extension.dart @@ -37,45 +37,31 @@ extension ListPresentationEmailExtension on List { return result; } - bool isAllCanDeletePermanently(Map mapMailbox) { - final listMailboxContain = map((email) => email.findMailboxContain(mapMailbox)) - .whereType() - .toList(); - final stateDelete = listMailboxContain.every((mailbox) => mailbox.isTrash) || - listMailboxContain.every((mailbox) => mailbox.isDrafts) || - listMailboxContain.every((mailbox) => mailbox.isSpam); - return stateDelete; + bool isDeletePermanentlyDisabled( + Map mapMailbox, + ) { + return any((email) { + final mailboxContain = email.findMailboxContain(mapMailbox); + return mailboxContain?.isDeletePermanentlyEnabled != true; + }); } - bool isAllCanSpamAndMove(Map mapMailbox) { - final listMailboxContain = map((email) => email.findMailboxContain(mapMailbox)) - .whereType() - .toList(); - return listMailboxContain.every((mailbox) => !mailbox.isDrafts) && - isAllBelongToTheSameMailbox(mapMailbox); + bool isArchiveMessageEnabled( + Map mapMailbox, + ) { + return any((email) { + final mailboxContain = email.findMailboxContain(mapMailbox); + return mailboxContain?.isArchive != true; + }); } - bool isAllSpam(Map mapMailbox) { - final listMailboxContain = map((email) => email.findMailboxContain(mapMailbox)) - .whereType() - .toList(); - return listMailboxContain.every((mailbox) => mailbox.isSpam); - } - - bool isAllBelongToTheSameMailbox(Map mapMailbox) { - if (isEmpty) { - return false; - } - final firstEmail = first; - final firstMailboxContain = firstEmail.findMailboxContain(mapMailbox); - if (firstMailboxContain != null) { - return every((email) { - final mailboxContain = email.findMailboxContain(mapMailbox); - return mailboxContain?.id == firstMailboxContain.id; - }); - } else { - return false; - } + bool isMarkAsSpamEnabled( + Map mapMailbox, + ) { + return any((email) { + final mailboxContain = email.findMailboxContain(mapMailbox); + return mailboxContain?.isSpam != true; + }); } PresentationMailbox? getCurrentMailboxContain(Map mapMailbox) { @@ -85,7 +71,7 @@ extension ListPresentationEmailExtension on List { List listEmailCanSpam(Map mapMailbox) { final newListEmails = map((email) { final mailboxContain = email.findMailboxContain(mapMailbox); - if (mailboxContain?.isSpam == false) { + if (mailboxContain?.isSpam != true) { return email; } else { return null;