TF-4358 Remove mail in trash by default in search result (#4361)

This commit is contained in:
Dat Vu
2026-04-10 15:15:53 +07:00
committed by GitHub
parent bc707b2612
commit c9e2e5db80
17 changed files with 290 additions and 131 deletions
@@ -13,7 +13,6 @@ import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_st
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart';
@@ -25,7 +24,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/sear
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -41,7 +39,7 @@ class AdvancedFilterController extends BaseController {
final startDate = Rxn<DateTime>();
final endDate = Rxn<DateTime>();
final sortOrderType = SearchEmailFilter.defaultSortOrder.obs;
final selectedFolderName = Rxn<String>();
final destinationMailboxSelected = Rxn<PresentationMailbox>();
final selectedLabel = Rxn<Label>();
final GlobalKey<TagsEditorState> keyFromEmailTagEditor = GlobalKey<TagsEditorState>();
@@ -64,8 +62,6 @@ class AdvancedFilterController extends BaseController {
final focusManager = InputFieldFocusManager.initial();
late SearchEmailFilter _memorySearchFilter;
PresentationMailbox? _destinationMailboxSelected;
late Worker _dashboardActionWorker;
@override
@@ -103,7 +99,7 @@ class AdvancedFilterController extends BaseController {
@visibleForTesting
void setDestinationMailboxSelected(PresentationMailbox? presentationMailbox) {
_destinationMailboxSelected = presentationMailbox;
destinationMailboxSelected.value = presentationMailbox;
}
@visibleForTesting
@@ -173,7 +169,7 @@ class AdvancedFilterController extends BaseController {
final sortOrderTypeOption = Some(sortOrderType.value);
final mailboxOption = optionOf(_destinationMailboxSelected);
final mailboxOption = optionOf(destinationMailboxSelected.value);
final subjectOption = option(
subjectFilterInputController.text.trim().isNotEmpty,
@@ -228,7 +224,7 @@ class AdvancedFilterController extends BaseController {
accountId,
MailboxActions.select,
session,
mailboxIdSelected: _destinationMailboxSelected?.id
mailboxIdSelected: destinationMailboxSelected.value?.id
);
final destinationMailbox = PlatformInfo.isWeb
@@ -239,12 +235,8 @@ class AdvancedFilterController extends BaseController {
if (destinationMailbox is! PresentationMailbox) return;
_destinationMailboxSelected = destinationMailbox;
final mailboxName = context.mounted
? _destinationMailboxSelected?.getDisplayName(context)
: _destinationMailboxSelected?.name?.name;
selectedFolderName.value = StringConvert.writeNullToEmpty(mailboxName);
_updateMemorySearchFilter(mailboxOption: optionOf(_destinationMailboxSelected));
destinationMailboxSelected.value = destinationMailbox;
_updateMemorySearchFilter(mailboxOption: optionOf(destinationMailbox));
}
void applyAdvancedSearchFilter() {
@@ -290,7 +282,7 @@ class AdvancedFilterController extends BaseController {
sortOrderType.value = _memorySearchFilter.sortOrderType;
_destinationMailboxSelected = _memorySearchFilter.mailbox;
destinationMailboxSelected.value = _memorySearchFilter.mailbox;
hasAttachment.value = _memorySearchFilter.hasAttachment;
@@ -320,13 +312,6 @@ class AdvancedFilterController extends BaseController {
toAddressExpandMode.value = ExpandMode.COLLAPSE;
}
if (context != null) {
selectedFolderName.value = _memorySearchFilter.mailbox == null
? AppLocalizations.of(context).allFolders
: StringConvert.writeNullToEmpty(
_memorySearchFilter.mailbox?.getDisplayName(context));
}
selectedLabel.value = _memorySearchFilter.label;
}
@@ -493,10 +478,9 @@ class AdvancedFilterController extends BaseController {
isUnread.value = false;
isStarred.value = false;
hasEvents.value = false;
selectedFolderName.value = null;
destinationMailboxSelected.value = null;
listFromEmailAddress.clear();
listToEmailAddress.clear();
_destinationMailboxSelected = null;
selectedLabel.value = null;
}
@@ -976,6 +976,14 @@ class MailboxDashBoardController extends ReloadableController
?? mapDefaultMailboxIdByRole[PresentationMailbox.roleSpam];
}
Set<MailboxId>? get trashSpamMailboxIds {
final ids = mapMailboxById.entries
.where((entry) => entry.value.isTrash || entry.value.isSpam)
.map((entry) => entry.key)
.toSet();
return ids.isEmpty ? null : ids;
}
void setMapDefaultMailboxIdByRole(Map<Role, MailboxId> newMapMailboxId) {
mapDefaultMailboxIdByRole = newMapMailboxId;
}
@@ -2300,12 +2308,7 @@ class MailboxDashBoardController extends ReloadableController
if (destinationMailbox is! PresentationMailbox) return;
searchController.updateFilterEmail(
mailboxOption: destinationMailbox.id == PresentationMailbox.unifiedMailbox.id
? const None()
: Some(destinationMailbox)
);
searchController.updateFilterEmail(mailboxOption: Some(destinationMailbox));
dispatchAction(StartSearchEmailAction());
}
@@ -60,7 +60,7 @@ enum QuickSearchFilter {
case QuickSearchFilter.from:
return AppLocalizations.of(context).from_email_address_prefix;
case QuickSearchFilter.folder:
return mailbox?.getDisplayName(context) ?? AppLocalizations.of(context).all;
return mailbox?.getFolderNameForQuickSearch(AppLocalizations.of(context)) ?? AppLocalizations.of(context).allEmail;
case QuickSearchFilter.to:
return AppLocalizations.of(context).to_email_address_prefix;
case QuickSearchFilter.starred:
@@ -8,14 +8,16 @@ import 'package:jmap_dart_client/jmap/core/filter/operator/logic_filter_operator
import 'package:jmap_dart_client/jmap/core/utc_date.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:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:labels/model/label.dart';
import 'package:model/email/prefix_email_address.dart';
import 'package:model/extensions/email_filter_condition_extension.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class SearchEmailFilter with EquatableMixin, OptionParamMixin {
@@ -109,13 +111,15 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
}
Filter? mappingToEmailFilterCondition({
EmailFilterCondition? moreFilterCondition
EmailFilterCondition? moreFilterCondition,
Set<MailboxId>? trashSpamMailboxIds,
}) {
final emailEmailFilterConditionShared = EmailFilterCondition(
text: text?.value.trim().isNotEmpty == true
? text?.value.trim()
: null,
inMailbox: mailbox?.mailboxId,
inMailbox: _getInMailboxField(),
inMailboxOtherThan: _getInMailboxOtherThanField(trashSpamMailboxIds),
after: emailReceiveTimeType.getAfterDate(startDate),
hasAttachment: !hasAttachment ? null : hasAttachment,
subject: subject?.trim().isNotEmpty == true
@@ -209,7 +213,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
notKeyword.isNotEmpty ||
emailReceiveTimeType != EmailReceiveTimeType.allTime ||
sortOrderType != SearchEmailFilter.defaultSortOrder ||
(mailbox != null && mailbox?.id != PresentationMailbox.unifiedMailbox.id) ||
(mailbox != null && mailbox?.isUnifiedMailbox != true) ||
label != null ||
hasAttachment ||
unread;
@@ -224,11 +228,30 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
notKeyword.isEmpty &&
emailReceiveTimeType == EmailReceiveTimeType.allTime &&
sortOrderType == SearchEmailFilter.defaultSortOrder &&
(mailbox == null || mailbox?.id == PresentationMailbox.unifiedMailbox.id) &&
(mailbox == null || mailbox?.isUnifiedMailbox == true) &&
label == null &&
!hasAttachment &&
!unread;
String getMailboxName(AppLocalizations appLocalizations) {
if (mailbox == null) return appLocalizations.allEmail;
return mailbox!.getFolderNameForQuickSearch(appLocalizations);
}
MailboxId? _getInMailboxField() {
if (mailbox != null && mailbox?.isUnifiedMailbox != true) {
return mailbox?.id;
}
return null;
}
Set<MailboxId>? _getInMailboxOtherThanField(Set<MailboxId>? trashSpamMailboxIds) {
if (mailbox == null || mailbox?.isAllEmail == true) {
return trashSpamMailboxIds;
}
return null;
}
@override
List<Object?> get props => [
from,
@@ -5,6 +5,7 @@ import 'package:tmail_ui_user/features/base/widget/default_field/default_autocom
import 'package:tmail_ui_user/features/base/widget/default_field/default_button_arrow_down_field_with_tab_key_widget.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_date_drop_down_field_widget.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_with_tab_key_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart';
@@ -113,8 +114,7 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController> {
AdvancedSearchFieldWidget(
filterField: FilterField.mailBox,
child: Obx(() => DefaultButtonArrowDownFieldWithTabKeyWidget(
text: controller.selectedFolderName.value ??
AppLocalizations.of(context).allFolders,
text: controller.destinationMailboxSelected.value?.getFolderNameForQuickSearch(appLocalizations) ?? appLocalizations.allEmail,
iconArrowDown: controller.imagePaths.icDropDown,
currentFocusNode: controller.focusManager.mailboxFieldFocusNode,
nextFocusNode: controller.focusManager.attachmentCheckboxFocusNode,