Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class AdvancedFilterController extends BaseController {
final hasAttachment = false.obs;
final isStarred = false.obs;
final isUnread = false.obs;
final hasEvents = false.obs;
final startDate = Rxn<DateTime>();
final endDate = Rxn<DateTime>();
final sortOrderType = SearchEmailFilter.defaultSortOrder.obs;
Expand Down Expand Up @@ -188,10 +189,12 @@ class AdvancedFilterController extends BaseController {

final unreadOption = Some(isUnread.value);

final hasKeywordOption = option(
isStarred.isTrue,
{KeyWordIdentifier.emailFlagged.value},
);
final listKeywords = {
if(isStarred.isTrue) KeyWordIdentifier.emailFlagged.value,
if(hasEvents.isTrue) KeyWordIdentifierExtension.eventsMail.value,
};
final hasKeywordOption =
optionOf(listKeywords.isNotEmpty ? listKeywords : null);

final labelOption = optionOf(selectedLabel.value);

Expand Down Expand Up @@ -296,6 +299,9 @@ class AdvancedFilterController extends BaseController {
isStarred.value = _memorySearchFilter.hasKeyword
.contains(KeyWordIdentifier.emailFlagged.value);

hasEvents.value = _memorySearchFilter.hasKeyword
.contains(KeyWordIdentifierExtension.eventsMail.value);

if (_memorySearchFilter.from.isEmpty) {
listFromEmailAddress.clear();
} else {
Expand Down Expand Up @@ -486,6 +492,7 @@ class AdvancedFilterController extends BaseController {
hasAttachment.value = false;
isUnread.value = false;
isStarred.value = false;
hasEvents.value = false;
selectedFolderName.value = null;
listFromEmailAddress.clear();
listToEmailAddress.clear();
Expand Down Expand Up @@ -568,21 +575,36 @@ class AdvancedFilterController extends BaseController {

void onStarredCheckboxChanged(bool? isChecked) {
isStarred.value = isChecked ?? false;
_updateKeywordsSearchFilter(
isStarred.isTrue,
KeyWordIdentifier.emailFlagged,
);
}

void onUnreadCheckboxChanged(bool? isChecked) {
isUnread.value = isChecked ?? false;
_updateMemorySearchFilter(
unreadOption: isUnread.isTrue ? const Some(true) : const None(),
);
}

void _updateKeywordsSearchFilter(bool isChecked, KeyWordIdentifier keyword) {
final listHasKeywordFiltered = _memorySearchFilter.hasKeyword;
if (isStarred.isTrue) {
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
if (isChecked) {
listHasKeywordFiltered.add(keyword.value);
} else {
listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value);
listHasKeywordFiltered.remove(keyword.value);
}
_updateMemorySearchFilter(
hasKeywordOption: Some(listHasKeywordFiltered),
);
}

void onUnreadCheckboxChanged(bool? isChecked) {
isUnread.value = isChecked ?? false;
_updateMemorySearchFilter(
unreadOption: isStarred.isTrue ? const Some(true) : const None(),
void onEventsCheckboxChanged(bool? isChecked) {
hasEvents.value = isChecked ?? false;
_updateKeywordsSearchFilter(
hasEvents.isTrue,
KeyWordIdentifierExtension.eventsMail,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class InputFieldFocusManager {
late FocusNode attachmentCheckboxFocusNode;
late FocusNode starredCheckboxFocusNode;
late FocusNode unreadCheckboxFocusNode;
late FocusNode eventsCheckboxFocusNode;

InputFieldFocusManager() {
fromFieldFocusNode = FocusNode();
Expand All @@ -23,6 +24,7 @@ class InputFieldFocusManager {
attachmentCheckboxFocusNode = FocusNode();
starredCheckboxFocusNode = FocusNode();
unreadCheckboxFocusNode = FocusNode();
eventsCheckboxFocusNode = FocusNode();
}

factory InputFieldFocusManager.initial() {
Expand All @@ -39,5 +41,6 @@ class InputFieldFocusManager {
attachmentCheckboxFocusNode.dispose();
starredCheckboxFocusNode.dispose();
unreadCheckboxFocusNode.dispose();
eventsCheckboxFocusNode.dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,7 @@ class MailboxDashBoardController extends ReloadableController
case QuickSearchFilter.starred:
case QuickSearchFilter.unread:
case QuickSearchFilter.labels:
case QuickSearchFilter.events:
deleteQuickSearchFilter(filter: searchFilter);
break;
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:labels/model/label.dart';
import 'package:model/extensions/keyword_identifier_extension.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';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart';

extension SelectSearchFilterActionExtension on MailboxDashBoardController {
void selectStarredSearchFilter() {
void selectKeywordSearchFilter(KeyWordIdentifier keyword) {
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
listHasKeywordFiltered.add(keyword.value);
searchController.updateFilterEmail(
hasKeywordOption: Some(listHasKeywordFiltered),
);
Expand All @@ -34,6 +35,15 @@ extension SelectSearchFilterActionExtension on MailboxDashBoardController {
dispatchAction(StartSearchEmailAction());
}

void deleteEventsSearchFilter() {
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
listHasKeywordFiltered.remove(KeyWordIdentifierExtension.eventsMail.value);
searchController.updateFilterEmail(
hasKeywordOption: Some(listHasKeywordFiltered),
);
dispatchAction(StartSearchEmailAction());
}

void deleteQuickSearchFilter({required QuickSearchFilter filter}) {
switch (filter) {
case QuickSearchFilter.labels:
Expand All @@ -45,6 +55,9 @@ extension SelectSearchFilterActionExtension on MailboxDashBoardController {
case QuickSearchFilter.unread:
deleteUnreadSearchFilter();
break;
case QuickSearchFilter.events:
deleteEventsSearchFilter();
break;
default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:model/extensions/keyword_identifier_extension.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';
Expand Down Expand Up @@ -698,6 +699,11 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
_buildQuickSearchFilterButton(context, QuickSearchFilter.starred),
MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin,
_buildQuickSearchFilterButton(context, QuickSearchFilter.unread),
MailboxDashboardViewWebStyle.searchFilterSizeBoxMargin,
_buildQuickSearchFilterButton(
context,
QuickSearchFilter.events,
),
],
),
),
Expand Down Expand Up @@ -833,11 +839,16 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
controller.selectFolderSearchFilter();
break;
case QuickSearchFilter.starred:
controller.selectStarredSearchFilter();
controller.selectKeywordSearchFilter(KeyWordIdentifier.emailFlagged);
break;
case QuickSearchFilter.unread:
controller.selectUnreadSearchFilter();
break;
case QuickSearchFilter.events:
controller.selectKeywordSearchFilter(
KeyWordIdentifierExtension.eventsMail,
);
break;
case QuickSearchFilter.labels:
final listLabels = controller.labelController.labels;
final selectedLabel = controller.searchController.labelFiltered;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:labels/extensions/label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:model/extensions/keyword_identifier_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';
Expand All @@ -20,6 +21,7 @@ enum QuickSearchFilter {
fromMe,
starred,
unread,
events,
sortBy,
dateTime,
from,
Expand Down Expand Up @@ -67,6 +69,8 @@ enum QuickSearchFilter {
return AppLocalizations.of(context).unread;
case QuickSearchFilter.labels:
return label?.safeDisplayName ?? AppLocalizations.of(context).allLabels;
case QuickSearchFilter.events:
return AppLocalizations.of(context).events;
}
}

Expand Down Expand Up @@ -94,6 +98,8 @@ enum QuickSearchFilter {
return isSelected ? imagePaths.icSelectedSB : imagePaths.icUnread;
case QuickSearchFilter.labels:
return imagePaths.icTag;
case QuickSearchFilter.events:
return imagePaths.icCalendarEvent;
}
}

Expand Down Expand Up @@ -162,6 +168,10 @@ enum QuickSearchFilter {
return searchFilter.unread;
case QuickSearchFilter.labels:
return searchFilter.label != null;
case QuickSearchFilter.events:
return searchFilter
.hasKeyword
.contains(KeyWordIdentifierExtension.eventsMail.value) == true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class AdvancedSearchFilterFormBottomView extends GetWidget<AdvancedFilterControl
context,
focusManager.starredCheckboxFocusNode,
),
_buildCheckboxEvents(
context,
focusManager.eventsCheckboxFocusNode,
),
],
),
const SizedBox(height: 25),
Expand Down Expand Up @@ -138,6 +142,23 @@ class AdvancedSearchFilterFormBottomView extends GetWidget<AdvancedFilterControl
);
}

Widget _buildCheckboxEvents(
BuildContext context,
FocusNode currentFocusNode,
) {
return Obx(
() => CustomIconLabeledCheckbox(
label: AppLocalizations.of(context).events,
svgIconPath: controller.imagePaths.icCheckboxUnselected,
selectedSvgIconPath: controller.imagePaths.icCheckboxSelected,
focusNode: currentFocusNode,
gap: 8.0,
value: controller.hasEvents.value,
onChanged: controller.onEventsCheckboxChanged,
),
);
}

void _onClickCancelButton() {
controller.clearSearchFilter();
popBack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension UpdateSearchFilterExtension on SearchEmailController {
updateSimpleSearchFilter(hasAttachmentOption: const None());
break;
case QuickSearchFilter.starred:
case QuickSearchFilter.events:
updateSimpleSearchFilter(hasKeywordOption: const None());
break;
case QuickSearchFilter.unread:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,10 +635,10 @@ class SearchEmailController extends BaseController
_searchEmailAction();
}

void selectStarredSearchFilter() {
void selectKeywordsSearchFilter(KeyWordIdentifier keyword) {
final listKeyword = listHasKeywordFiltered;
if (!listKeyword.contains(KeyWordIdentifier.emailFlagged.value)) {
listKeyword.add(KeyWordIdentifier.emailFlagged.value);
if (!listKeyword.contains(keyword.value)) {
listKeyword.add(keyword.value);
}
_updateSimpleSearchFilter(hasKeywordOption: Some(listKeyword));
_searchEmailAction();
Expand Down Expand Up @@ -1077,6 +1077,9 @@ class SearchEmailController extends BaseController
case QuickSearchFilter.unread:
_deleteUnreadSearchFilter();
break;
case QuickSearchFilter.events:
_deleteEventsSearchFilter();
break;
case QuickSearchFilter.labels:
deleteQuickSearchFilter(filter: QuickSearchFilter.labels);
break;
Expand Down Expand Up @@ -1136,6 +1139,11 @@ class SearchEmailController extends BaseController
_searchEmailAction();
}

void _deleteEventsSearchFilter() {
_updateSimpleSearchFilter(hasKeywordOption: const None());
_searchEmailAction();
}

void clearAllSearchFilterApplied() {
textInputSearchController.clear();
currentSearchText.value = '';
Expand Down
10 changes: 9 additions & 1 deletion lib/features/search/email/presentation/search_email_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:labels/model/label.dart';
import 'package:model/model.dart';
Expand Down Expand Up @@ -302,6 +303,8 @@ class SearchEmailView extends GetWidget<SearchEmailController>
SearchEmailViewStyle.searchFilterSizeBoxMargin,
_buildSearchFilterButton(context, QuickSearchFilter.unread),
SearchEmailViewStyle.searchFilterSizeBoxMargin,
_buildSearchFilterButton(context, QuickSearchFilter.events),
SearchEmailViewStyle.searchFilterSizeBoxMargin,
_buildSearchFilterButton(context, QuickSearchFilter.sortBy),
],
);
Expand Down Expand Up @@ -412,11 +415,16 @@ class SearchEmailView extends GetWidget<SearchEmailController>
controller.selectMailboxForSearchFilter(controller.mailboxFiltered);
break;
case QuickSearchFilter.starred:
controller.selectStarredSearchFilter();
controller.selectKeywordsSearchFilter(KeyWordIdentifier.emailFlagged);
break;
case QuickSearchFilter.unread:
controller.selectUnreadSearchFilter();
break;
case QuickSearchFilter.events:
controller.selectKeywordsSearchFilter(
KeyWordIdentifierExtension.eventsMail,
);
break;
case QuickSearchFilter.labels:
final listLabels = controller.mailboxDashBoardController.labelController.labels;
final selectedLabel = controller.labelFiltered;
Expand Down
8 changes: 7 additions & 1 deletion lib/l10n/intl_messages.arb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@@last_modified": "2026-01-26T09:26:54.654131",
"@@last_modified": "2026-03-03T17:58:48.288160",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
Expand Down Expand Up @@ -5453,5 +5453,11 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"events": "Events",
"@events": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
7 changes: 7 additions & 0 deletions lib/main/localizations/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5769,4 +5769,11 @@ class AppLocalizations {
name: 'deleteALabelFailure',
);
}

String get events {
return Intl.message(
'Events',
name: 'events',
);
}
}
1 change: 1 addition & 0 deletions model/lib/extensions/keyword_identifier_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:model/email/read_actions.dart';
extension KeyWordIdentifierExtension on KeyWordIdentifier {
static final unsubscribeMail = KeyWordIdentifier('\$unsubscribe');
static final needsActionMail = KeyWordIdentifier('needs-action');
static final eventsMail = KeyWordIdentifier('event');

String generatePath() => '${PatchObject.keywordsProperty}/$value';

Expand Down
Loading