TF-4066 Display Unread, Starred in list quick search button in dashboard view

This commit is contained in:
dab246
2025-09-26 18:12:27 +07:00
committed by Dat H. Pham
parent efc2d80efc
commit d05904229b
9 changed files with 92 additions and 10 deletions
@@ -224,7 +224,6 @@ extension AppColor on Color {
static const colorFilterMessageButton = Color(0xFFEBEDF0); static const colorFilterMessageButton = Color(0xFFEBEDF0);
static const colorFilterMessageIcon = Color(0xFF686E76); static const colorFilterMessageIcon = Color(0xFF686E76);
static const colorFilterMessageTitle = Color(0xFF686E76); static const colorFilterMessageTitle = Color(0xFF686E76);
static const colorStarredSearchFilterIcon = Color(0xFFFFCC00);
static const colorMobileSearchFilterButton = Color(0xFFEBEDF0); static const colorMobileSearchFilterButton = Color(0xFFEBEDF0);
static const colorContactViewClearFilterButton = Color(0x001C3D0D); static const colorContactViewClearFilterButton = Color(0x001C3D0D);
static const steelGrayA540 = Color(0xFF55687D); static const steelGrayA540 = Color(0xFF55687D);
@@ -119,6 +119,7 @@ class AdvancedFilterController extends BaseController {
Option<PresentationMailbox>? mailboxOption, Option<PresentationMailbox>? mailboxOption,
Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption, Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption,
Option<bool>? hasAttachmentOption, Option<bool>? hasAttachmentOption,
Option<bool>? unreadOption,
Option<UTCDate>? beforeOption, Option<UTCDate>? beforeOption,
Option<UTCDate>? startDateOption, Option<UTCDate>? startDateOption,
Option<UTCDate>? endDateOption, Option<UTCDate>? endDateOption,
@@ -134,6 +135,7 @@ class AdvancedFilterController extends BaseController {
mailboxOption: mailboxOption, mailboxOption: mailboxOption,
emailReceiveTimeTypeOption: emailReceiveTimeTypeOption, emailReceiveTimeTypeOption: emailReceiveTimeTypeOption,
hasAttachmentOption: hasAttachmentOption, hasAttachmentOption: hasAttachmentOption,
unreadOption: unreadOption,
beforeOption: beforeOption, beforeOption: beforeOption,
startDateOption: startDateOption, startDateOption: startDateOption,
endDateOption: endDateOption, endDateOption: endDateOption,
@@ -125,6 +125,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/notify_thread_detail_setting_updated.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/notify_thread_detail_setting_updated.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_paywall_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_paywall_extension.dart';
@@ -2240,6 +2241,12 @@ class MailboxDashBoardController extends ReloadableController
case QuickSearchFilter.folder: case QuickSearchFilter.folder:
_deleteFolderSearchFilter(); _deleteFolderSearchFilter();
break; break;
case QuickSearchFilter.starred:
deleteStarredSearchFilter();
break;
case QuickSearchFilter.unread:
deleteUnreadSearchFilter();
break;
default: default:
break; break;
} }
@@ -183,6 +183,7 @@ class SearchController extends BaseController with DateRangePickerMixin {
Option<PresentationMailbox>? mailboxOption, Option<PresentationMailbox>? mailboxOption,
Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption, Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption,
Option<bool>? hasAttachmentOption, Option<bool>? hasAttachmentOption,
Option<bool>? unreadOption,
Option<UTCDate>? beforeOption, Option<UTCDate>? beforeOption,
Option<UTCDate>? startDateOption, Option<UTCDate>? startDateOption,
Option<UTCDate>? endDateOption, Option<UTCDate>? endDateOption,
@@ -199,6 +200,7 @@ class SearchController extends BaseController with DateRangePickerMixin {
mailboxOption: mailboxOption, mailboxOption: mailboxOption,
emailReceiveTimeTypeOption: emailReceiveTimeTypeOption, emailReceiveTimeTypeOption: emailReceiveTimeTypeOption,
hasAttachmentOption: hasAttachmentOption, hasAttachmentOption: hasAttachmentOption,
unreadOption: unreadOption,
beforeOption: beforeOption, beforeOption: beforeOption,
startDateOption: startDateOption, startDateOption: startDateOption,
endDateOption: endDateOption, endDateOption: endDateOption,
@@ -220,6 +222,10 @@ class SearchController extends BaseController with DateRangePickerMixin {
Set<String> get listAddressOfFromFiltered => searchEmailFilter.value.from; Set<String> get listAddressOfFromFiltered => searchEmailFilter.value.from;
Set<String> get listHasKeywordFiltered => searchEmailFilter.value.hasKeyword;
bool get unreadFiltered => searchEmailFilter.value.unread;
EmailSortOrderType get sortOrderFiltered => searchEmailFilter.value.sortOrderType; EmailSortOrderType get sortOrderFiltered => searchEmailFilter.value.sortOrderType;
bool isSearchActive() => bool isSearchActive() =>
@@ -0,0 +1,38 @@
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
extension SelectSearchFilterActionExtension on MailboxDashBoardController {
void selectStarredSearchFilter() {
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
if (!listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) {
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
}
searchController.updateFilterEmail(
hasKeywordOption: Some(listHasKeywordFiltered),
);
dispatchAction(StartSearchEmailAction());
}
void selectUnreadSearchFilter() {
searchController.updateFilterEmail(unreadOption: const Some(true));
dispatchAction(StartSearchEmailAction());
}
void deleteStarredSearchFilter() {
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
if (listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) {
listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value);
}
searchController.updateFilterEmail(
hasKeywordOption: Some(listHasKeywordFiltered),
);
dispatchAction(StartSearchEmailAction());
}
void deleteUnreadSearchFilter() {
searchController.updateFilterEmail(unreadOption: const None());
dispatchAction(StartSearchEmailAction());
}
}
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/extensions/session_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/clean_messages_banner.dart';
@@ -22,6 +23,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/base_mailb
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_open_context_menu_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_open_context_menu_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_profile_setting_action_type_click_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_profile_setting_action_type_click_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/profile_setting/profile_setting_action_type.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/profile_setting/profile_setting_action_type.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_receive_time_type.dart';
@@ -455,13 +457,14 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColor.colorFilterMessageButton.withValues(alpha: 0.6), backgroundColor: AppColor.colorFilterMessageButton.withValues(alpha: 0.6),
shadowColor: Colors.transparent, shadowColor: Colors.transparent,
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12, vertical: 8), padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)), borderRadius: BorderRadius.all(Radius.circular(10)),
), ),
elevation: 0.0, elevation: 0.0,
foregroundColor: AppColor.colorTextButtonHeaderThread, foregroundColor: AppColor.colorTextButtonHeaderThread,
maximumSize: const Size.fromWidth(250), maximumSize: const Size.fromWidth(250),
fixedSize: const Size.fromHeight(34),
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith( textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
@@ -663,6 +666,10 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
_buildQuickSearchFilterButton(context, QuickSearchFilter.dateTime), _buildQuickSearchFilterButton(context, QuickSearchFilter.dateTime),
MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin, MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin,
_buildQuickSearchFilterButton(context, QuickSearchFilter.hasAttachment), _buildQuickSearchFilterButton(context, QuickSearchFilter.hasAttachment),
MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin,
_buildQuickSearchFilterButton(context, QuickSearchFilter.starred),
MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin,
_buildQuickSearchFilterButton(context, QuickSearchFilter.unread),
], ],
), ),
), ),
@@ -713,6 +720,8 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
final receiveTimeType = controller.searchController.receiveTimeFiltered; final receiveTimeType = controller.searchController.receiveTimeFiltered;
final mailbox = controller.searchController.mailboxFiltered; final mailbox = controller.searchController.mailboxFiltered;
final listAddressOfTo = controller.searchController.listAddressOfToFiltered; final listAddressOfTo = controller.searchController.listAddressOfToFiltered;
final listHasKeywordFiltered = controller.searchController.listHasKeywordFiltered;
final unreadFiltered = controller.searchController.unreadFiltered;
final isSelected = searchFilter.isSelected( final isSelected = searchFilter.isSelected(
context, context,
@@ -730,7 +739,9 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
startDate != null || startDate != null ||
endDate != null || endDate != null ||
receiveTimeType != EmailReceiveTimeType.allTime || receiveTimeType != EmailReceiveTimeType.allTime ||
mailbox != null; mailbox != null ||
listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value) ||
unreadFiltered;
return SearchFilterButton( return SearchFilterButton(
key: Key('${searchFilter.name}_search_filter_button'), key: Key('${searchFilter.name}_search_filter_button'),
@@ -790,6 +801,12 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
case QuickSearchFilter.folder: case QuickSearchFilter.folder:
controller.selectFolderSearchFilter(); controller.selectFolderSearchFilter();
break; break;
case QuickSearchFilter.starred:
controller.selectStarredSearchFilter();
break;
case QuickSearchFilter.unread:
controller.selectUnreadSearchFilter();
break;
default: default:
break; break;
} }
@@ -17,6 +17,7 @@ enum QuickSearchFilter {
last7Days, last7Days,
fromMe, fromMe,
starred, starred,
unread,
sortBy, sortBy,
dateTime, dateTime,
from, from,
@@ -58,6 +59,8 @@ enum QuickSearchFilter {
return AppLocalizations.of(context).to_email_address_prefix; return AppLocalizations.of(context).to_email_address_prefix;
case QuickSearchFilter.starred: case QuickSearchFilter.starred:
return AppLocalizations.of(context).starred; return AppLocalizations.of(context).starred;
case QuickSearchFilter.unread:
return AppLocalizations.of(context).unread;
} }
} }
@@ -80,7 +83,9 @@ enum QuickSearchFilter {
case QuickSearchFilter.folder: case QuickSearchFilter.folder:
return imagePaths.icFolderMailbox; return imagePaths.icFolderMailbox;
case QuickSearchFilter.starred: case QuickSearchFilter.starred:
return isSelected ? imagePaths.icSelectedSB : imagePaths.icStar; return isSelected ? imagePaths.icSelectedSB : imagePaths.icUnStar;
case QuickSearchFilter.unread:
return isSelected ? imagePaths.icSelectedSB : imagePaths.icUnread;
} }
} }
@@ -112,11 +117,7 @@ enum QuickSearchFilter {
if (isSelected) { if (isSelected) {
return AppColor.primaryColor; return AppColor.primaryColor;
} else { } else {
if (this == QuickSearchFilter.starred) { return AppColor.colorSearchFilterIcon;
return AppColor.colorStarredSearchFilterIcon;
} else {
return AppColor.colorSearchFilterIcon;
}
} }
} }
@@ -149,6 +150,8 @@ enum QuickSearchFilter {
return searchFilter.mailbox != null; return searchFilter.mailbox != null;
case QuickSearchFilter.starred: case QuickSearchFilter.starred:
return searchFilter.hasKeyword.contains(KeyWordIdentifier.emailFlagged.value) == true; return searchFilter.hasKeyword.contains(KeyWordIdentifier.emailFlagged.value) == true;
case QuickSearchFilter.unread:
return searchFilter.unread;
} }
} }
@@ -29,6 +29,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
final PresentationMailbox? mailbox; final PresentationMailbox? mailbox;
final EmailReceiveTimeType emailReceiveTimeType; final EmailReceiveTimeType emailReceiveTimeType;
final bool hasAttachment; final bool hasAttachment;
final bool unread;
final UTCDate? before; final UTCDate? before;
final UTCDate? startDate; final UTCDate? startDate;
final UTCDate? endDate; final UTCDate? endDate;
@@ -52,6 +53,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
Set<String>? to, Set<String>? to,
EmailReceiveTimeType? emailReceiveTimeType, EmailReceiveTimeType? emailReceiveTimeType,
bool? hasAttachment, bool? hasAttachment,
bool? unread,
Set<String>? notKeyword, Set<String>? notKeyword,
Set<String>? hasKeyword, Set<String>? hasKeyword,
EmailSortOrderType? sortOrderType, EmailSortOrderType? sortOrderType,
@@ -60,6 +62,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
notKeyword = notKeyword ?? <String>{}, notKeyword = notKeyword ?? <String>{},
hasKeyword = hasKeyword ?? <String>{}, hasKeyword = hasKeyword ?? <String>{},
hasAttachment = hasAttachment ?? false, hasAttachment = hasAttachment ?? false,
unread = unread ?? false,
emailReceiveTimeType = emailReceiveTimeType =
emailReceiveTimeType ?? EmailReceiveTimeType.allTime, emailReceiveTimeType ?? EmailReceiveTimeType.allTime,
sortOrderType = sortOrderType ?? defaultSortOrder; sortOrderType = sortOrderType ?? defaultSortOrder;
@@ -74,6 +77,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
Option<PresentationMailbox>? mailboxOption, Option<PresentationMailbox>? mailboxOption,
Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption, Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption,
Option<bool>? hasAttachmentOption, Option<bool>? hasAttachmentOption,
Option<bool>? unreadOption,
Option<UTCDate>? beforeOption, Option<UTCDate>? beforeOption,
Option<UTCDate>? startDateOption, Option<UTCDate>? startDateOption,
Option<UTCDate>? endDateOption, Option<UTCDate>? endDateOption,
@@ -90,6 +94,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
mailbox: getOptionParam(mailboxOption, mailbox), mailbox: getOptionParam(mailboxOption, mailbox),
emailReceiveTimeType: getOptionParam(emailReceiveTimeTypeOption, emailReceiveTimeType), emailReceiveTimeType: getOptionParam(emailReceiveTimeTypeOption, emailReceiveTimeType),
hasAttachment: getOptionParam(hasAttachmentOption, hasAttachment), hasAttachment: getOptionParam(hasAttachmentOption, hasAttachment),
unread: getOptionParam(unreadOption, unread),
before: getOptionParam(beforeOption, before), before: getOptionParam(beforeOption, before),
startDate: getOptionParam(startDateOption, startDate), startDate: getOptionParam(startDateOption, startDate),
endDate: getOptionParam(endDateOption, endDate), endDate: getOptionParam(endDateOption, endDate),
@@ -118,6 +123,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
hasKeyword: hasKeyword.length == 1 hasKeyword: hasKeyword.length == 1
? hasKeyword.first ? hasKeyword.first
: null, : null,
notKeyword: unread ? KeyWordIdentifier.emailSeen.value : null,
); );
final listEmailCondition = { final listEmailCondition = {
@@ -197,7 +203,8 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
emailReceiveTimeType != EmailReceiveTimeType.allTime || emailReceiveTimeType != EmailReceiveTimeType.allTime ||
sortOrderType != SearchEmailFilter.defaultSortOrder || sortOrderType != SearchEmailFilter.defaultSortOrder ||
(mailbox != null && mailbox?.id != PresentationMailbox.unifiedMailbox.id) || (mailbox != null && mailbox?.id != PresentationMailbox.unifiedMailbox.id) ||
hasAttachment; hasAttachment ||
unread;
bool get isContainFlagged => hasKeyword.contains(KeyWordIdentifier.emailFlagged.value); bool get isContainFlagged => hasKeyword.contains(KeyWordIdentifier.emailFlagged.value);
@@ -212,6 +219,7 @@ class SearchEmailFilter with EquatableMixin, OptionParamMixin {
mailbox, mailbox,
emailReceiveTimeType, emailReceiveTimeType,
hasAttachment, hasAttachment,
unread,
before, before,
startDate, startDate,
endDate, endDate,
@@ -769,6 +769,7 @@ class SearchEmailController extends BaseController
Option<PresentationMailbox>? mailboxOption, Option<PresentationMailbox>? mailboxOption,
Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption, Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption,
Option<bool>? hasAttachmentOption, Option<bool>? hasAttachmentOption,
Option<bool>? unreadOption,
Option<UTCDate>? beforeOption, Option<UTCDate>? beforeOption,
Option<UTCDate>? startDateOption, Option<UTCDate>? startDateOption,
Option<UTCDate>? endDateOption, Option<UTCDate>? endDateOption,
@@ -783,6 +784,7 @@ class SearchEmailController extends BaseController
mailboxOption: mailboxOption, mailboxOption: mailboxOption,
emailReceiveTimeTypeOption: emailReceiveTimeTypeOption, emailReceiveTimeTypeOption: emailReceiveTimeTypeOption,
hasAttachmentOption: hasAttachmentOption, hasAttachmentOption: hasAttachmentOption,
unreadOption: unreadOption,
beforeOption: beforeOption, beforeOption: beforeOption,
startDateOption: startDateOption, startDateOption: startDateOption,
endDateOption: endDateOption, endDateOption: endDateOption,