From 01052b48636634ed0ce0a54347df8ac5aa2dbef3 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 18 Sep 2024 13:41:17 +0700 Subject: [PATCH] TF-2985 Support easily search mail from me in advanced search --- .../advanced_filter_controller.dart | 3 + ..._autocomplete_email_address_web_style.dart | 16 ++ .../advanced_search_input_form.dart | 2 + ..._field_autocomplete_email_address_web.dart | 222 +++++++++++------- 4 files changed, 161 insertions(+), 82 deletions(-) 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 66c4c830c9..1c55e552b2 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart @@ -3,6 +3,7 @@ import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/model.dart'; import 'package:super_tag_editor/tag_editor.dart'; @@ -63,6 +64,8 @@ class AdvancedFilterController extends BaseController { late Worker _dashboardActionWorker; + UserName? get userName => _mailboxDashBoardController.sessionCurrent?.username; + @override void onInit() { _registerWorkerListener(); diff --git a/lib/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart b/lib/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart index 7a3ac7df98..9b650ef8ae 100644 --- a/lib/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart +++ b/lib/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart @@ -1,17 +1,28 @@ import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/utils/direction_utils.dart'; import 'package:flutter/material.dart'; class TextFieldAutoCompleteEmailAddressWebStyles { static const EdgeInsetsGeometry padding = EdgeInsets.symmetric(vertical: 8); static const EdgeInsetsGeometry textInputContentPadding = EdgeInsetsDirectional.only(top: 16, bottom: 16, start: 12); + static const EdgeInsetsGeometry textInputContentPaddingWithMeButton = EdgeInsetsDirectional.only(top: 16, bottom: 16, start: 12, end: 60); static const EdgeInsetsGeometry textInputContentPaddingWithSomeTag = EdgeInsetsDirectional.symmetric(vertical: 16); static const EdgeInsets tagEditorPadding = EdgeInsets.symmetric(horizontal: 12); + static EdgeInsets getTagEditorPaddingWithMeButton(BuildContext context) { + return EdgeInsets.only( + left: DirectionUtils.isDirectionRTLByLanguage(context) ? 60 : 12, + right: DirectionUtils.isDirectionRTLByLanguage(context) ? 12 : 60, + ); + } + static const double borderRadius = 10.0; static const double suggestionBoxRadius = 20.0; static const double borderWidth = 1.0; static const double minTextFieldWidth = 40.0; + static const double meButtonMaxWidth = 100.0; + static const double meButtonMinWidth = 40.0; static const double suggestionBoxElevation = 20.0; static const double suggestionBoxMaxHeight = 350.0; @@ -43,6 +54,11 @@ class TextFieldAutoCompleteEmailAddressWebStyles { color: Colors.black, fontWeight: FontWeight.w500, ); + static const TextStyle meButtonTextStyle = TextStyle( + fontSize: 15, + color: Colors.white, + fontWeight: FontWeight.w500, + ); static const Duration debounceDuration = Duration(milliseconds: 150); } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart index 87fd5acb7d..74ea82c609 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart @@ -30,6 +30,7 @@ class AdvancedSearchInputForm extends GetWidget Obx(() => TextFieldAutocompleteEmailAddressWeb( field: AdvancedSearchFilterField.from, listEmailAddress: controller.listFromEmailAddress, + userName: controller.userName, expandMode: controller.fromAddressExpandMode.value, controller: controller.fromEmailAddressController, focusNode: controller.focusManager.fromFieldFocusNode, @@ -43,6 +44,7 @@ class AdvancedSearchInputForm extends GetWidget Obx(() => TextFieldAutocompleteEmailAddressWeb( field: AdvancedSearchFilterField.to, listEmailAddress: controller.listToEmailAddress, + userName: controller.userName, expandMode: controller.toAddressExpandMode.value, controller: controller.toEmailAddressController, focusNode: controller.focusManager.toFieldFocusNode, diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart index f6741643b0..be10964982 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart @@ -4,9 +4,11 @@ import 'dart:math'; import 'package:collection/collection.dart'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/utils/app_logger.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/extensions/email_address_extension.dart'; import 'package:model/mailbox/expand_mode.dart'; @@ -17,6 +19,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/adv import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/autocomplete_suggestion_item_widget_web.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/autocomplete_tag_item_widget_web.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart'; typedef OnSuggestionEmailAddress = Future> Function(String word); @@ -29,6 +32,7 @@ class TextFieldAutocompleteEmailAddressWeb extends StatefulWidget { final AdvancedSearchFilterField field; final List listEmailAddress; + final UserName? userName; final ExpandMode expandMode; final FocusNode? focusNode; final GlobalKey? keyTagEditor; @@ -47,6 +51,7 @@ class TextFieldAutocompleteEmailAddressWeb extends StatefulWidget { Key? key, required this.field, required this.listEmailAddress, + this.userName, this.expandMode = ExpandMode.EXPAND, this.focusNode, this.keyTagEditor, @@ -105,89 +110,109 @@ class _TextFieldAutocompleteEmailAddressWebState extends State( - key: widget.keyTagEditor, - length: _collapsedListEmailAddress.length, - controller: widget.controller, - focusNodeKeyboard: widget.focusNode, - keyboardType: TextInputType.emailAddress, - textInputAction: TextInputAction.done, - cursorColor: TextFieldAutoCompleteEmailAddressWebStyles.cursorColor, - debounceDuration: TextFieldAutoCompleteEmailAddressWebStyles.debounceDuration, - inputDecoration: InputDecoration( - filled: true, - fillColor: TextFieldAutoCompleteEmailAddressWebStyles.textInputFillColor, - border: TextFieldAutoCompleteEmailAddressWebStyles.textInputBorder, - hintText: widget.field.getHintText(context), - hintStyle: TextFieldAutoCompleteEmailAddressWebStyles.textInputHintStyle, - isDense: true, - contentPadding: _currentListEmailAddress.isNotEmpty - ? TextFieldAutoCompleteEmailAddressWebStyles.textInputContentPaddingWithSomeTag - : TextFieldAutoCompleteEmailAddressWebStyles.textInputContentPadding - ), - padding: _currentListEmailAddress.isNotEmpty - ? TextFieldAutoCompleteEmailAddressWebStyles.tagEditorPadding - : EdgeInsets.zero, - borderRadius: TextFieldAutoCompleteEmailAddressWebStyles.borderRadius, - borderSize: TextFieldAutoCompleteEmailAddressWebStyles.borderWidth, - focusedBorderColor: TextFieldAutoCompleteEmailAddressWebStyles.focusedBorderColor, - enableBorder: true, - enableBorderColor: AppColor.colorInputBorderCreateMailbox, - minTextFieldWidth: TextFieldAutoCompleteEmailAddressWebStyles.minTextFieldWidth, - resetTextOnSubmitted: true, - autoScrollToInput: false, - suggestionsBoxElevation: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxElevation, - suggestionsBoxBackgroundColor: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxBackgroundColor, - suggestionsBoxRadius: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxRadius, - suggestionsBoxMaxHeight: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxMaxHeight, - suggestionBoxWidth: _getSuggestionBoxWidth(constraints.maxWidth), - textStyle: AdvancedSearchInputFormStyle.inputTextStyle, - onFocusTagAction: (focused) => _handleFocusTagAction.call(focused, setState), - onDeleteTagAction: () => _handleDeleteLatestTagAction.call(setState), - onSelectOptionAction: (item) => _handleSelectOptionAction.call(item, setState), - onSubmitted: (value) => _handleSubmitTagAction.call(value, setState), - tagBuilder: (context, index) { - final currentEmailAddress = _currentListEmailAddress.elementAt(index); - final isLatestEmail = currentEmailAddress == _currentListEmailAddress.last; - return AutoCompleteTagItemWidgetWeb( - field: widget.field, - currentEmailAddress: currentEmailAddress, - currentListEmailAddress: _currentListEmailAddress, - collapsedListEmailAddress: _collapsedListEmailAddress, - isLatestEmail: isLatestEmail, - isCollapsed: _isCollapse, - isLatestTagFocused: _lastTagFocused, - onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, setState), - onShowFullAction: widget.onShowFullListEmailAddressAction, - ); - }, - onTagChanged: (tag) => _handleOnTagChangeAction.call(tag, setState), - findSuggestions: _findSuggestions, - suggestionBuilder: (context, tagEditorState, suggestionEmailAddress, index, length, highlight, suggestionValid) { - return AutoCompleteSuggestionItemWidgetWeb( - suggestionState: suggestionEmailAddress.state, - emailAddress: suggestionEmailAddress.emailAddress, - suggestionValid: suggestionValid, - highlight: highlight, - onSelectedAction: (emailAddress) { - setState(() => _currentListEmailAddress.add(emailAddress)); - _updateListEmailAddressAction(); - tagEditorState.resetTextField(); - tagEditorState.closeSuggestionBox(); + return Stack( + alignment: AlignmentDirectional.center, + children: [ + TagEditor( + key: widget.keyTagEditor, + length: _collapsedListEmailAddress.length, + controller: widget.controller, + focusNodeKeyboard: widget.focusNode, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.done, + cursorColor: TextFieldAutoCompleteEmailAddressWebStyles.cursorColor, + debounceDuration: TextFieldAutoCompleteEmailAddressWebStyles.debounceDuration, + inputDecoration: InputDecoration( + filled: true, + fillColor: TextFieldAutoCompleteEmailAddressWebStyles.textInputFillColor, + border: TextFieldAutoCompleteEmailAddressWebStyles.textInputBorder, + hintText: widget.field.getHintText(context), + hintStyle: TextFieldAutoCompleteEmailAddressWebStyles.textInputHintStyle, + isDense: true, + contentPadding: _getInputFieldPadding() + ), + padding: _getTagEditorPadding(context), + borderRadius: TextFieldAutoCompleteEmailAddressWebStyles.borderRadius, + borderSize: TextFieldAutoCompleteEmailAddressWebStyles.borderWidth, + focusedBorderColor: TextFieldAutoCompleteEmailAddressWebStyles.focusedBorderColor, + enableBorder: true, + enableBorderColor: AppColor.colorInputBorderCreateMailbox, + minTextFieldWidth: TextFieldAutoCompleteEmailAddressWebStyles.minTextFieldWidth, + resetTextOnSubmitted: true, + autoScrollToInput: false, + suggestionsBoxElevation: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxElevation, + suggestionsBoxBackgroundColor: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxBackgroundColor, + suggestionsBoxRadius: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxRadius, + suggestionsBoxMaxHeight: TextFieldAutoCompleteEmailAddressWebStyles.suggestionBoxMaxHeight, + suggestionBoxWidth: _getSuggestionBoxWidth(constraints.maxWidth), + textStyle: AdvancedSearchInputFormStyle.inputTextStyle, + onFocusTagAction: (focused) => _handleFocusTagAction.call(focused, setState), + onDeleteTagAction: () => _handleDeleteLatestTagAction.call(setState), + onSelectOptionAction: (item) => _handleSelectOptionAction.call(item, setState), + onSubmitted: (value) => _handleSubmitTagAction.call(value, setState), + tagBuilder: (context, index) { + final currentEmailAddress = _currentListEmailAddress.elementAt(index); + final isLatestEmail = currentEmailAddress == _currentListEmailAddress.last; + return AutoCompleteTagItemWidgetWeb( + field: widget.field, + currentEmailAddress: currentEmailAddress, + currentListEmailAddress: _currentListEmailAddress, + collapsedListEmailAddress: _collapsedListEmailAddress, + isLatestEmail: isLatestEmail, + isCollapsed: _isCollapse, + isLatestTagFocused: _lastTagFocused, + onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, setState), + onShowFullAction: widget.onShowFullListEmailAddressAction, + ); }, - ); - }, - onHandleKeyEventAction: (event) { - if (event is KeyDownEvent) { - switch (event.logicalKey) { - case LogicalKeyboardKey.tab: - widget.nextFocusNode?.requestFocus(); - break; - default: - break; - } - } - }, + onTagChanged: (tag) => _handleOnTagChangeAction.call(tag, setState), + findSuggestions: _findSuggestions, + suggestionBuilder: (context, tagEditorState, suggestionEmailAddress, index, length, highlight, suggestionValid) { + return AutoCompleteSuggestionItemWidgetWeb( + suggestionState: suggestionEmailAddress.state, + emailAddress: suggestionEmailAddress.emailAddress, + suggestionValid: suggestionValid, + highlight: highlight, + onSelectedAction: (emailAddress) { + setState(() => _currentListEmailAddress.add(emailAddress)); + _updateListEmailAddressAction(); + tagEditorState.resetTextField(); + tagEditorState.closeSuggestionBox(); + }, + ); + }, + onHandleKeyEventAction: (event) { + if (event is KeyDownEvent) { + switch (event.logicalKey) { + case LogicalKeyboardKey.tab: + widget.nextFocusNode?.requestFocus(); + break; + default: + break; + } + } + }, + ), + if (_validateMeButtonDisplayed) + PositionedDirectional( + end: 8, + child: TMailButtonWidget.fromText( + text: AppLocalizations.of(context).me, + borderRadius: TextFieldAutoCompleteEmailAddressWebStyles.borderRadius, + textStyle: TextFieldAutoCompleteEmailAddressWebStyles.meButtonTextStyle, + maxLines: 1, + textAlign: TextAlign.center, + backgroundColor: AppColor.primaryColor, + maxWidth: TextFieldAutoCompleteEmailAddressWebStyles.meButtonMaxWidth, + minWidth: TextFieldAutoCompleteEmailAddressWebStyles.meButtonMinWidth, + onTapActionCallback: () => + _handleOnClickMeButton( + widget.userName!, + setState + ), + ) + ) + ], ); }) ), @@ -340,4 +365,37 @@ class _TextFieldAutocompleteEmailAddressWebState extends State emailAddress.emailAddress == userName.value); + } + + void _handleOnClickMeButton(UserName userName, StateSetter stateSetter) { + stateSetter(() => _currentListEmailAddress.add(EmailAddress(null, userName.value))); + _updateListEmailAddressAction(); + } } \ No newline at end of file