diff --git a/core/lib/presentation/views/checkbox/labeled_checkbox.dart b/core/lib/presentation/views/checkbox/labeled_checkbox.dart index b3df9c2e5..c27e1fb13 100644 --- a/core/lib/presentation/views/checkbox/labeled_checkbox.dart +++ b/core/lib/presentation/views/checkbox/labeled_checkbox.dart @@ -30,7 +30,7 @@ class LabeledCheckbox extends StatelessWidget { children: [ buildCheckboxWidget, buildGapWidget, - buildLabelWidget, + Flexible(child: buildLabelWidget), ], ), ); @@ -53,5 +53,7 @@ class LabeledCheckbox extends StatelessWidget { Widget get buildLabelWidget => Text( label, style: textStyle ?? ThemeUtils.textStyleM3BodyMedium3, + maxLines: 1, + overflow: TextOverflow.ellipsis, ); } diff --git a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart index d569e5565..b2e9b59a1 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/core/utc_date.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:model/model.dart'; import 'package:super_tag_editor/tag_editor.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; @@ -33,6 +34,8 @@ class AdvancedFilterController extends BaseController { final receiveTimeType = EmailReceiveTimeType.allTime.obs; final hasAttachment = false.obs; + final isStarred = false.obs; + final isUnread = false.obs; final startDate = Rxn(); final endDate = Rxn(); final sortOrderType = SearchEmailFilter.defaultSortOrder.obs; @@ -115,6 +118,7 @@ class AdvancedFilterController extends BaseController { Option>? toOption, Option? textOption, Option? subjectOption, + Option>? hasKeywordOption, Option>? notKeywordOption, Option? mailboxOption, Option? emailReceiveTimeTypeOption, @@ -131,6 +135,7 @@ class AdvancedFilterController extends BaseController { toOption: toOption, textOption: textOption, subjectOption: subjectOption, + hasKeywordOption: hasKeywordOption, notKeywordOption: notKeywordOption, mailboxOption: mailboxOption, emailReceiveTimeTypeOption: emailReceiveTimeTypeOption, @@ -176,6 +181,13 @@ class AdvancedFilterController extends BaseController { final endDateOption = optionOf(endDate.value?.toUTCDate()); + final unreadOption = Some(isUnread.value); + + final hasKeywordOption = option( + isStarred.isTrue, + {KeyWordIdentifier.emailFlagged.value}, + ); + _updateMemorySearchFilter( textOption: textOption, notKeywordOption: notKeywordsOption, @@ -186,6 +198,8 @@ class AdvancedFilterController extends BaseController { subjectOption: subjectOption, emailReceiveTimeTypeOption: emailReceiveTimeTypeOption, hasAttachmentOption: hasAttachmentOption, + unreadOption: unreadOption, + hasKeywordOption: hasKeywordOption, startDateOption: startDateOption, endDateOption: endDateOption ); @@ -269,6 +283,11 @@ class AdvancedFilterController extends BaseController { hasAttachment.value = _memorySearchFilter.hasAttachment; + isUnread.value = _memorySearchFilter.unread; + + isStarred.value = _memorySearchFilter.hasKeyword + .contains(KeyWordIdentifier.emailFlagged.value); + if (_memorySearchFilter.from.isEmpty) { listFromEmailAddress.clear(); } else { @@ -455,6 +474,8 @@ class AdvancedFilterController extends BaseController { endDate.value = null; receiveTimeType.value = EmailReceiveTimeType.allTime; hasAttachment.value = false; + isUnread.value = false; + isStarred.value = false; selectedFolderName.value = null; listFromEmailAddress.clear(); listToEmailAddress.clear(); @@ -534,6 +555,26 @@ class AdvancedFilterController extends BaseController { _updateMemorySearchFilter(hasAttachmentOption: Some(hasAttachment.value)); } + void onStarredCheckboxChanged(bool? isChecked) { + isStarred.value = isChecked ?? false; + final listHasKeywordFiltered = _memorySearchFilter.hasKeyword; + if (isStarred.isTrue) { + listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value); + } else { + listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value); + } + _updateMemorySearchFilter( + hasKeywordOption: Some(listHasKeywordFiltered), + ); + } + + void onUnreadCheckboxChanged(bool? isChecked) { + isUnread.value = isChecked ?? false; + _updateMemorySearchFilter( + unreadOption: isStarred.isTrue ? const Some(true) : const None(), + ); + } + void onTextChanged(FilterField filterField, String value) { switch (filterField) { case FilterField.subject: diff --git a/lib/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart b/lib/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart index 86021a478..c414905a5 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart @@ -10,6 +10,8 @@ class InputFieldFocusManager { late FocusNode notKeywordFieldFocusNode; late FocusNode mailboxFieldFocusNode; late FocusNode attachmentCheckboxFocusNode; + late FocusNode starredCheckboxFocusNode; + late FocusNode unreadCheckboxFocusNode; InputFieldFocusManager() { fromFieldFocusNode = FocusNode(); @@ -19,6 +21,8 @@ class InputFieldFocusManager { notKeywordFieldFocusNode = FocusNode(); mailboxFieldFocusNode = FocusNode(); attachmentCheckboxFocusNode = FocusNode(); + starredCheckboxFocusNode = FocusNode(); + unreadCheckboxFocusNode = FocusNode(); } factory InputFieldFocusManager.initial() { @@ -33,5 +37,7 @@ class InputFieldFocusManager { notKeywordFieldFocusNode.dispose(); mailboxFieldFocusNode.dispose(); attachmentCheckboxFocusNode.dispose(); + starredCheckboxFocusNode.dispose(); + unreadCheckboxFocusNode.dispose(); } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart index 8e0b44214..20d797470 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart @@ -6,9 +6,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller extension SelectSearchFilterActionExtension on MailboxDashBoardController { void selectStarredSearchFilter() { final listHasKeywordFiltered = searchController.listHasKeywordFiltered; - if (!listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) { - listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value); - } + listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value); searchController.updateFilterEmail( hasKeywordOption: Some(listHasKeywordFiltered), ); @@ -22,9 +20,7 @@ extension SelectSearchFilterActionExtension on MailboxDashBoardController { void deleteStarredSearchFilter() { final listHasKeywordFiltered = searchController.listHasKeywordFiltered; - if (listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) { - listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value); - } + listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value); searchController.updateFilterEmail( hasKeywordOption: Some(listHasKeywordFiltered), ); diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart index 54b14bd25..d93c8ed55 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart @@ -23,10 +23,25 @@ class AdvancedSearchFilterFormBottomView extends GetWidget CustomIconLabeledCheckbox( + label: AppLocalizations.of(context).starred, + svgIconPath: controller.imagePaths.icCheckboxUnselected, + selectedSvgIconPath: controller.imagePaths.icCheckboxSelected, + focusNode: currentFocusNode, + gap: 8.0, + value: controller.isStarred.value, + onChanged: controller.onStarredCheckboxChanged, + ), + ); + } + + Widget _buildCheckboxUnread( + BuildContext context, + FocusNode currentFocusNode, + ) { + return Obx( + () => CustomIconLabeledCheckbox( + label: AppLocalizations.of(context).unread, + svgIconPath: controller.imagePaths.icCheckboxUnselected, + selectedSvgIconPath: controller.imagePaths.icCheckboxSelected, + focusNode: currentFocusNode, + gap: 8.0, + value: controller.isUnread.value, + onChanged: controller.onUnreadCheckboxChanged, + ), + ); + } + void _onClickCancelButton() { controller.clearSearchFilter(); popBack();