diff --git a/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart index 1a0aa73dd..c04c85e1b 100644 --- a/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart +++ b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/email/presentation_email.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.dart'; @@ -119,4 +120,14 @@ class ClearDateRangeToAdvancedSearch extends DashBoardAction { @override List get props => [receiveTime]; -} \ No newline at end of file +} + +class SearchEmailByFromFieldsAction extends DashBoardAction { + + final EmailAddress emailAddress; + + SearchEmailByFromFieldsAction(this.emailAddress); + + @override + List get props => [emailAddress]; +} 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 844c90cf0..41ecf941d 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart @@ -447,10 +447,21 @@ class AdvancedFilterController extends BaseController { ); } else if (action is ClearDateRangeToAdvancedSearch) { _updateDateRangeTime(action.receiveTime); - } else if (action is StartSearchEmailAction) { - if (action.filter == QuickSearchFilter.fromMe) { - _updateFromField(); - } + } else if (action is StartSearchEmailAction && action.filter == QuickSearchFilter.fromMe) { + _updateFromField(); + } else if (action is SearchEmailByFromFieldsAction) { + searchController.clearSearchFilter(); + _resetAllToOriginalValue(); + _clearAllTextFieldInput(); + searchController.searchInputController.clear(); + searchController.deactivateAdvancedSearch(); + searchController.isAdvancedSearchViewOpen.value = false; + + listFromEmailAddress = List.from({action.emailAddress}); + final listAddress = listFromEmailAddress.map((emailAddress) => emailAddress.emailAddress).toSet(); + searchController.updateFilterEmail(fromOption: Some(listAddress)); + + _mailboxDashBoardController.dispatchAction(StartSearchEmailAction()); } } ); 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 cd8406d12..9df0d0a23 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -15,6 +15,7 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/vacation/vacation_response.dart'; import 'package:model/model.dart'; @@ -26,9 +27,11 @@ import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dar import 'package:tmail_ui_user/features/composer/domain/exceptions/set_email_method_exception.dart'; import 'package:tmail_ui_user/features/composer/domain/extensions/email_request_extension.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart'; @@ -184,6 +187,7 @@ class MailboxDashBoardController extends ReloadableController { DeleteEmailStateToRefreshInteractor? _deleteEmailStateToRefreshInteractor; GetMailboxStateToRefreshInteractor? _getMailboxStateToRefreshInteractor; DeleteMailboxStateToRefreshInteractor? _deleteMailboxStateToRefreshInteractor; + GetAutoCompleteInteractor? _getAutoCompleteInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -2174,6 +2178,34 @@ class MailboxDashBoardController extends ReloadableController { } } + Future> getContactSuggestion(String query) async { + _getAutoCompleteInteractor = getBinding(); + + if (_getAutoCompleteInteractor == null || accountId.value == null) { + return []; + } + + final listEmailAddress = await _getAutoCompleteInteractor! + .execute(AutoCompletePattern(word: query, accountId: accountId.value!, limit: 2)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : [] + )); + log('MailboxDashBoardController::getAutoCompleteSuggestion:listEmailAddress: $listEmailAddress'); + return listEmailAddress; + } + + void searchEmailByFromFields(BuildContext context, EmailAddress emailAddress) { + KeyboardUtils.hideKeyboard(context); + clearFilterMessageOption(); + searchController.clearFilterSuggestion(); + if (_searchInsideEmailDetailedViewIsActive(context)) { + _closeEmailDetailedView(); + } + _unSelectedMailbox(); + dispatchAction(SearchEmailByFromFieldsAction(emailAddress)); + } + @override void onClose() { _emailReceiveManager.closeEmailReceiveManagerStream(); diff --git a/lib/features/mailbox_dashboard/presentation/widgets/quick_search/contact_quick_search_item.dart b/lib/features/mailbox_dashboard/presentation/widgets/quick_search/contact_quick_search_item.dart new file mode 100644 index 000000000..141841421 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/widgets/quick_search/contact_quick_search_item.dart @@ -0,0 +1,59 @@ + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/utils/style_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/extensions/email_address_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_suggestion_item_widget.dart'; + +class ContactQuickSearchItem extends StatelessWidget { + final EmailAddress emailAddress; + + const ContactQuickSearchItem({ + super.key, + required this.emailAddress, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( + children: [ + AvatarSuggestionItemWidget(emailAddress: emailAddress), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + emailAddress.asString(), + maxLines: 1, + softWrap: CommonTextStyle.defaultSoftWrap, + overflow: CommonTextStyle.defaultTextOverFlow, + style: const TextStyle( + color: Colors.black, + fontSize: 16, + fontWeight: FontWeight.normal + ) + ), + if (emailAddress.displayName.isNotEmpty) + Text( + emailAddress.emailAddress, + maxLines: 1, + softWrap: CommonTextStyle.defaultSoftWrap, + overflow: CommonTextStyle.defaultTextOverFlow, + style: const TextStyle( + color: AppColor.colorHintSearchBar, + fontSize: 13, + fontWeight: FontWeight.normal + ) + ) + ], + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/email_quick_search_item_tile_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/quick_search/email_quick_search_item_tile_widget.dart similarity index 100% rename from lib/features/mailbox_dashboard/presentation/widgets/email_quick_search_item_tile_widget.dart rename to lib/features/mailbox_dashboard/presentation/widgets/quick_search/email_quick_search_item_tile_widget.dart diff --git a/lib/features/mailbox_dashboard/presentation/widgets/recent_search_item_tile_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/quick_search/recent_search_item_tile_widget.dart similarity index 100% rename from lib/features/mailbox_dashboard/presentation/widgets/recent_search_item_tile_widget.dart rename to lib/features/mailbox_dashboard/presentation/widgets/quick_search/recent_search_item_tile_widget.dart diff --git a/lib/features/mailbox_dashboard/presentation/widgets/search_input_form_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/search_input_form_widget.dart index 7a712bd4e..0553872d7 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/search_input_form_widget.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/search_input_form_widget.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; 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/email_address.dart'; import 'package:model/email/presentation_email.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; @@ -18,8 +19,9 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_overlay.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/icon_open_advanced_search_widget.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/email_quick_search_item_tile_widget.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/recent_search_item_tile_widget.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/contact_quick_search_item.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/email_quick_search_item_tile_widget.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/recent_search_item_tile_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart' as search; @@ -55,7 +57,7 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin { ), ), portalFollower: const AdvancedSearchFilterOverlay(), - child: QuickSearchInputForm( + child: QuickSearchInputForm( maxHeight: 52, suggestionsBoxVerticalOffset: 0.0, textFieldConfiguration: _createConfiguration(context), @@ -105,7 +107,11 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin { onRecentSelected: (recent) => _invokeSelectRecentItem(context, recent), suggestionsCallback: _dashBoardController.quickSearchEmails, itemBuilder: (context, email) => EmailQuickSearchItemTileWidget(email, _dashBoardController.selectedMailbox.value), - onSuggestionSelected: (presentationEmail) => _invokeSelectSuggestionItem(context, presentationEmail)) + onSuggestionSelected: (presentationEmail) => _invokeSelectSuggestionItem(context, presentationEmail), + contactItemBuilder: (context, emailAddress) => ContactQuickSearchItem(emailAddress: emailAddress), + contactSuggestionsCallback: _dashBoardController.getContactSuggestion, + onContactSuggestionSelected: (emailAddress) => _invokeSelectContactSuggestion(context, emailAddress), + ) ), ); }); @@ -246,4 +252,11 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin { ); }); } + + void _invokeSelectContactSuggestion(BuildContext context, EmailAddress emailAddress) { + _searchController.searchInputController.clear(); + _searchController.searchFocus.unfocus(); + _searchController.enableSearch(); + _dashBoardController.searchEmailByFromFields(context, emailAddress); + } } \ No newline at end of file diff --git a/lib/features/search/email/presentation/search_email_view.dart b/lib/features/search/email/presentation/search_email_view.dart index 957670329..3d3a4759f 100644 --- a/lib/features/search/email/presentation/search_email_view.dart +++ b/lib/features/search/email/presentation/search_email_view.dart @@ -16,8 +16,8 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_c import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.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/quick_search_filter.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/email_quick_search_item_tile_widget.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/recent_search_item_tile_widget.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/email_quick_search_item_tile_widget.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/quick_search/recent_search_item_tile_widget.dart'; import 'package:tmail_ui_user/features/search/email/presentation/model/search_more_state.dart'; import 'package:tmail_ui_user/features/search/email/presentation/model/simple_search_filter.dart'; import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart';