From cc508c210a1ff716be5fc266e43741acbb8698a8 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 5 Jan 2026 12:20:34 +0700 Subject: [PATCH] TF-4229 Add quick search label filter button in dashboard view --- .../popup_context_menu_action_mixin.dart | 11 +++- .../popup_menu_item_action_widget.dart | 11 +++- .../mailbox_dashboard_controller.dart | 7 +- .../controller/search_controller.dart | 5 ++ ...select_search_filter_action_extension.dart | 18 +++++ .../mailbox_dashboard_view_web.dart | 36 +++++++++- .../model/search/quick_search_filter.dart | 4 +- .../model/search/search_email_filter.dart | 2 +- .../search_label_filter_modal_mixin.dart | 3 +- .../email/presentation/search_email_view.dart | 66 +++++++++++-------- 10 files changed, 125 insertions(+), 38 deletions(-) diff --git a/lib/features/base/mixin/popup_context_menu_action_mixin.dart b/lib/features/base/mixin/popup_context_menu_action_mixin.dart index 6fd561daa..d03c6dced 100644 --- a/lib/features/base/mixin/popup_context_menu_action_mixin.dart +++ b/lib/features/base/mixin/popup_context_menu_action_mixin.dart @@ -28,6 +28,7 @@ mixin PopupContextMenuActionMixin { required OnContextMenuActionClick onContextMenuActionClick, Key? key, bool useGroupedActions = false, + double? maxHeight, }) async { return await showModalBottomSheet( context: context, @@ -42,6 +43,9 @@ mixin PopupContextMenuActionMixin { ), backgroundColor: Colors.white, barrierColor: Colors.black.withValues(alpha: 0.2), + constraints: BoxConstraints( + maxHeight: maxHeight ?? double.infinity, + ), builder: (_) { return PointerInterceptor( child: Container( @@ -63,6 +67,7 @@ mixin PopupContextMenuActionMixin { BuildContext context, RelativeRect position, List popupMenuItems, + {double? maxHeight} ) async { return await showMenu( context: context, @@ -74,7 +79,11 @@ mixin PopupContextMenuActionMixin { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(6)), ), - constraints: const BoxConstraints(maxWidth: 300, minWidth: 178), + constraints: BoxConstraints( + maxWidth: 300, + minWidth: 178, + maxHeight: maxHeight ?? double.infinity, + ), items: popupMenuItems, ); } diff --git a/lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart b/lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart index 38078e13e..c86959522 100644 --- a/lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart +++ b/lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart @@ -46,6 +46,7 @@ class _PopupMenuItemActionWidgetState extends State { Widget? iconWidget; Widget? selectedIconWidget; bool isSelected = false; + bool isArrangeRTL = true; if (widget.menuAction is PopupMenuItemActionRequiredIcon) { final specificMenuAction = @@ -75,6 +76,7 @@ class _PopupMenuItemActionWidgetState extends State { ); isSelected = specificMenuAction.selectedAction == widget.menuAction.action; + isArrangeRTL = specificMenuAction.isArrangeRTL; } else if (widget.menuAction is PopupMenuItemActionRequiredFull) { final specificMenuAction = widget.menuAction as PopupMenuItemActionRequiredFull; @@ -100,6 +102,7 @@ class _PopupMenuItemActionWidgetState extends State { ); isSelected = specificMenuAction.selectedAction == widget.menuAction.action; + isArrangeRTL = specificMenuAction.isArrangeRTL; } else if (widget.menuAction is PopupMenuItemActionRequiredIconWithMultipleSelected) { final specificMenuAction = widget.menuAction @@ -126,6 +129,7 @@ class _PopupMenuItemActionWidgetState extends State { ); isSelected = specificMenuAction.selectedActions.contains(widget.menuAction.action); + isArrangeRTL = specificMenuAction.isArrangeRTL; } if (widget.menuAction is PopupMenuItemEmailAction && @@ -217,6 +221,11 @@ class _PopupMenuItemActionWidgetState extends State { child: Row( children: [ if (iconWidget != null) iconWidget, + if (!isArrangeRTL && selectedIconWidget != null) + Padding( + padding: const EdgeInsetsDirectional.only(end: 16), + child: selectedIconWidget, + ), Expanded( child: Text( widget.menuAction.actionName, @@ -227,7 +236,7 @@ class _PopupMenuItemActionWidgetState extends State { overflow: TextOverflow.ellipsis, ), ), - if (isSelected && selectedIconWidget != null) + if (isArrangeRTL && isSelected && selectedIconWidget != null) selectedIconWidget, ], ), diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index db1454e92..c1454e79c 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -177,6 +177,7 @@ import 'package:tmail_ui_user/features/push_notification/presentation/controller import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_manager.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart'; +import 'package:tmail_ui_user/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/state/get_all_sending_email_state.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart'; @@ -226,7 +227,8 @@ class MailboxDashBoardController extends ReloadableController with ContactSupportMixin, OwnEmailAddressMixin, SaaSPremiumMixin, - AiScribeMixin { + AiScribeMixin, + SearchLabelFilterModalMixin { final RemoveEmailDraftsInteractor _removeEmailDraftsInteractor = Get.find(); final EmailReceiveManager _emailReceiveManager = Get.find(); @@ -2363,6 +2365,9 @@ class MailboxDashBoardController extends ReloadableController case QuickSearchFilter.unread: deleteUnreadSearchFilter(); break; + case QuickSearchFilter.labels: + deleteQuickSearchFilter(filter: searchFilter); + break; default: break; } diff --git a/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart index 6a2ddf2d0..7619cc9fa 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart @@ -15,6 +15,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart'; import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; +import 'package:labels/model/label.dart'; import 'package:model/email/presentation_email.dart'; import 'package:model/extensions/email_filter_condition_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; @@ -209,6 +210,7 @@ class SearchController extends BaseController with DateRangePickerMixin { Option? endDateOption, Option? positionOption, Option? sortOrderTypeOption, + Option