From fdf1e45d66d927de5f2f5b6b9c3bfdaa0589bf2c Mon Sep 17 00:00:00 2001 From: dab246 Date: Thu, 24 Mar 2022 13:07:48 +0700 Subject: [PATCH] TF-390 Apply new ui for suggestion box for email address --- .../views/button/icon_button_web.dart | 19 ++++++- .../contact_datasource_impl.dart | 13 +++-- .../local_autocomplete_datasource_impl.dart | 2 +- .../domain/model/auto_complete_pattern.dart | 6 ++- .../presentation/composer_controller.dart | 11 ++-- .../composer/presentation/composer_view.dart | 16 +++--- .../presentation/composer_view_web.dart | 28 +++++----- .../widgets/email_address_input_builder.dart | 54 ++++++++++--------- .../email/presentation/email_view.dart | 6 +-- .../presentation/mailbox_controller.dart | 2 + .../widgets/mailbox_folder_tile_builder.dart | 3 +- .../presentation/thread_controller.dart | 9 ++++ .../thread/presentation/thread_view.dart | 4 +- lib/main/localizations/app_localizations.dart | 7 --- 14 files changed, 108 insertions(+), 72 deletions(-) diff --git a/core/lib/presentation/views/button/icon_button_web.dart b/core/lib/presentation/views/button/icon_button_web.dart index a83456b83..cba9b9d7e 100644 --- a/core/lib/presentation/views/button/icon_button_web.dart +++ b/core/lib/presentation/views/button/icon_button_web.dart @@ -67,13 +67,30 @@ Widget buildTextCircleButton(String text, { style: ButtonStyle( overlayColor: MaterialStateProperty.resolveWith((Set states) => AppColor.colorFocusButton), shape: MaterialStateProperty.all(CircleBorder()), - padding: MaterialStateProperty.resolveWith((Set states) => EdgeInsets.all(5)), + padding: MaterialStateProperty.resolveWith((Set states) => EdgeInsets.zero), elevation: MaterialStateProperty.resolveWith((Set states) => 0)), onPressed: () => onTap?.call() ) ); } +Widget buildTextIcon(String text, { + TextStyle? textStyle, + EdgeInsets? padding, + IconWebCallback? onTap, +}) { + return Material( + shape: CircleBorder(), + color: Colors.transparent, + child: InkWell( + child: Padding( + padding: padding ?? EdgeInsets.all(10), + child: Text(text, style: textStyle ?? TextStyle(fontWeight: FontWeight.normal, fontSize: 15, color: AppColor.lineItemListColor))), + onTap: () => onTap?.call() + ) + ); +} + Widget buildTextButton(String text, { TextStyle? textStyle, double? width, diff --git a/lib/features/composer/data/datasource_impl/contact_datasource_impl.dart b/lib/features/composer/data/datasource_impl/contact_datasource_impl.dart index 37e583980..6219aa199 100644 --- a/lib/features/composer/data/datasource_impl/contact_datasource_impl.dart +++ b/lib/features/composer/data/datasource_impl/contact_datasource_impl.dart @@ -9,9 +9,16 @@ class ContactDataSourceImpl extends ContactDataSource { @override Future> getContactSuggestions(AutoCompletePattern autoCompletePattern) async { - final suggestedList = await contact_service.ContactsService - .getContactsByEmailOrName(autoCompletePattern.word ?? ''); - return suggestedList.expand((contact) => _toDeviceContact(contact)).toList(); + if (autoCompletePattern.isAll == true) { + return []; + } else { + final suggestedList = await contact_service.ContactsService + .getContactsByEmailOrName(autoCompletePattern.word ?? ''); + if (suggestedList.isNotEmpty) { + return suggestedList.expand((contact) => _toDeviceContact(contact)).toList(); + } + return []; + } } List _toDeviceContact(contact_service.Contact contact) { diff --git a/lib/features/composer/data/datasource_impl/local_autocomplete_datasource_impl.dart b/lib/features/composer/data/datasource_impl/local_autocomplete_datasource_impl.dart index 629cd18f4..84eb82ab6 100644 --- a/lib/features/composer/data/datasource_impl/local_autocomplete_datasource_impl.dart +++ b/lib/features/composer/data/datasource_impl/local_autocomplete_datasource_impl.dart @@ -13,7 +13,7 @@ class LocalAutoCompleteDataSourceImpl extends AutoCompleteDataSource { @override Future> getAutoComplete(AutoCompletePattern autoCompletePattern) { return Future.sync(() async { - if (autoCompletePattern.word == null || autoCompletePattern.word!.isEmpty) { + if (autoCompletePattern.isAll == true) { return await emailAddressDatabaseManager.getListData( word: autoCompletePattern.word, limit: autoCompletePattern.limit, diff --git a/lib/features/composer/domain/model/auto_complete_pattern.dart b/lib/features/composer/domain/model/auto_complete_pattern.dart index f9adf5be5..ce4c591a2 100644 --- a/lib/features/composer/domain/model/auto_complete_pattern.dart +++ b/lib/features/composer/domain/model/auto_complete_pattern.dart @@ -6,14 +6,16 @@ class AutoCompletePattern with EquatableMixin { final String? word; final int? limit; final String? orderBy; + final bool? isAll; AutoCompletePattern({ this.word, this.limit, - this.orderBy + this.orderBy, + this.isAll, }); @override - List get props => [word, limit, orderBy]; + List get props => [word, limit, orderBy, isAll]; } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index df8a9eff2..e287d8d51 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -93,7 +93,6 @@ class ComposerController extends BaseController { final toEmailAddressController = TextEditingController(); final ccEmailAddressController = TextEditingController(); final bccEmailAddressController = TextEditingController(); - final toEmailAddressFocusNode = FocusNode(); List initialAttachments = []; String? _textEditorWeb; @@ -386,7 +385,7 @@ class ComposerController extends BaseController { context, AppLocalizations.of(context).message_dialog_send_email_without_recipient, AppLocalizations.of(context).add_recipients, - () => toEmailAddressFocusNode.requestFocus(), + () => {}, hasCancelButton: false); return; } @@ -468,14 +467,14 @@ class ComposerController extends BaseController { } } - Future> getAutoCompleteSuggestion(String word) async { + Future> getAutoCompleteSuggestion({String? word, bool? isAll}) async { if (_contactSuggestionSource == ContactSuggestionSource.all) { - return await _getAutoCompleteWithDeviceContactInteractor.execute(AutoCompletePattern(word: word)) + return await _getAutoCompleteWithDeviceContactInteractor.execute(AutoCompletePattern(word: word, isAll: isAll)) .then((value) => value.fold( (failure) => [], (success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : [])); } - return await _getAutoCompleteInteractor.execute(AutoCompletePattern(word: word)) + return await _getAutoCompleteInteractor.execute(AutoCompletePattern(word: word, isAll: isAll)) .then((value) => value.fold( (failure) => [], (success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : [])); @@ -695,7 +694,7 @@ class ComposerController extends BaseController { void _updateTextForEditor() async { final textCurrent = await htmlControllerBrowser.getText(); - htmlControllerBrowser.insertText(textCurrent); + htmlControllerBrowser.setText(textCurrent); } void deleteComposer() { diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index dd24e98d7..beb97f43b 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -207,19 +207,19 @@ class ComposerView extends GetWidget { children: [ Obx(() => Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.to, controller.listToEmailAddress, controller.listEmailAddressType, expandMode: controller.toAddressExpandMode.value, controller: controller.toEmailAddressController, - focusNode: controller.toEmailAddressFocusNode, isInitial: controller.isInitialRecipient.value) ..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus)) ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnAddEmailAddressTypeAction((prefixEmailAddress) => controller.addEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build() )), Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true @@ -228,7 +228,7 @@ class ComposerView extends GetWidget { Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true ? Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.cc, controller.listCcEmailAddress, controller.listEmailAddressType, @@ -239,7 +239,8 @@ class ComposerView extends GetWidget { ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build()) : SizedBox.shrink() ), @@ -249,7 +250,7 @@ class ComposerView extends GetWidget { Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true ? Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.bcc, controller.listBccEmailAddress, controller.listEmailAddressType, @@ -260,7 +261,8 @@ class ComposerView extends GetWidget { ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build()) : SizedBox.shrink() ), diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index 0333145ff..4d13b38f7 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -56,8 +56,8 @@ class ComposerView extends GetWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), child: Container( decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), - width: responsiveUtils.getSizeScreenWidth(context) * 0.55, - height: responsiveUtils.getSizeScreenHeight(context) * 0.7, + width: responsiveUtils.getSizeScreenWidth(context) * 0.5, + height: responsiveUtils.getSizeScreenHeight(context) * 0.75, child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(24)), child: LayoutBuilder(builder: (context, constraints) => @@ -310,19 +310,19 @@ class ComposerView extends GetWidget { children: [ Obx(() => Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.to, controller.listToEmailAddress, controller.listEmailAddressType, expandMode: controller.toAddressExpandMode.value, controller: controller.toEmailAddressController, - focusNode: controller.toEmailAddressFocusNode, isInitial: controller.isInitialRecipient.value) ..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus)) ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnAddEmailAddressTypeAction((prefixEmailAddress) => controller.addEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build() )), Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true @@ -331,7 +331,7 @@ class ComposerView extends GetWidget { Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true ? Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.cc, controller.listCcEmailAddress, controller.listEmailAddressType, @@ -342,7 +342,8 @@ class ComposerView extends GetWidget { ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build()) : SizedBox.shrink() ), @@ -352,7 +353,7 @@ class ComposerView extends GetWidget { Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true ? Padding( padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), - child: (EmailAddressInputBuilder(context, imagePaths, responsiveUtils, + child: (EmailAddressInputBuilder(context, imagePaths, PrefixEmailAddress.bcc, controller.listBccEmailAddress, controller.listEmailAddressType, @@ -363,7 +364,8 @@ class ComposerView extends GetWidget { ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) - ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word))) + ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) + ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) .build()) : SizedBox.shrink() ), @@ -477,7 +479,7 @@ class ComposerView extends GetWidget { otherOptions: HtmlEditorBrowser.OtherOptions(height: 550), callbacks: HtmlEditorBrowser.Callbacks( onBeforeCommand: (String? currentHtml) { - log('ComposerView::_buildComposerEditor(): onBeforeCommand'); + log('ComposerView::_buildComposerEditor(): onBeforeCommand : $currentHtml'); controller.setTextEditorWeb(currentHtml); }, onChangeContent: (String? changed) { log('ComposerView::_buildComposerEditor(): onChangeContent : $changed'); @@ -582,11 +584,7 @@ class ComposerView extends GetWidget { double _getMaxHeightEmailAddressWidget(BuildContext context, BoxConstraints constraints) { if (responsiveUtils.isDesktop(context)) { - if (controller.screenDisplayMode == ScreenDisplayMode.normal) { - return constraints.maxHeight > 0 ? constraints.maxHeight * 0.25 : 150.0; - } else { - return constraints.maxHeight > 0 ? constraints.maxHeight * 0.3 : 150.0; - } + return constraints.maxHeight > 0 ? constraints.maxHeight * 0.3 : 150.0; } else { return constraints.maxHeight > 0 ? constraints.maxHeight * 0.4 : 150.0; } diff --git a/lib/features/composer/presentation/widgets/email_address_input_builder.dart b/lib/features/composer/presentation/widgets/email_address_input_builder.dart index 1d9d985a3..cc135d73f 100644 --- a/lib/features/composer/presentation/widgets/email_address_input_builder.dart +++ b/lib/features/composer/presentation/widgets/email_address_input_builder.dart @@ -18,17 +18,16 @@ typedef OnAddEmailAddressTypeAction = void Function(PrefixEmailAddress); typedef OnDeleteEmailAddressTypeAction = void Function(PrefixEmailAddress); typedef OnShowFullListEmailAddressAction = void Function(PrefixEmailAddress); typedef OnFocusEmailAddressChangeAction = void Function(PrefixEmailAddress, bool); +typedef OnOpenSuggestionBoxEmailAddress = Future> Function(); class EmailAddressInputBuilder { final BuildContext _context; final ImagePaths _imagePaths; - final ResponsiveUtils _responsiveUtils; final ExpandMode expandMode; final PrefixEmailAddress _prefixEmailAddress; final List _listEmailAddressType; final TextEditingController? controller; - final FocusNode? focusNode; final bool? isInitial; List _listEmailAddress = []; @@ -39,6 +38,7 @@ class EmailAddressInputBuilder { OnDeleteEmailAddressTypeAction? _onDeleteEmailAddressTypeAction; OnShowFullListEmailAddressAction? _onShowFullListEmailAddressAction; OnFocusEmailAddressChangeAction? _onFocusEmailAddressChangeAction; + OnOpenSuggestionBoxEmailAddress? _onOpenSuggestionBoxEmailAddress; void addOnUpdateListEmailAddressAction(OnUpdateListEmailAddressAction onUpdateListEmailAddressAction) { _onUpdateListEmailAddressAction = onUpdateListEmailAddressAction; @@ -64,17 +64,19 @@ class EmailAddressInputBuilder { _onFocusEmailAddressChangeAction = onFocusEmailAddressChangeAction; } + void addOnOpenSuggestionBoxEmailAddress(OnOpenSuggestionBoxEmailAddress onOpenSuggestionBoxEmailAddress) { + _onOpenSuggestionBoxEmailAddress = onOpenSuggestionBoxEmailAddress; + } + EmailAddressInputBuilder( this._context, this._imagePaths, - this._responsiveUtils, this._prefixEmailAddress, this._listEmailAddress, this._listEmailAddressType, { this.isInitial, this.controller, - this.focusNode, this.expandMode = ExpandMode.EXPAND, } ); @@ -84,35 +86,30 @@ class EmailAddressInputBuilder { children: [ Text('${_prefixEmailAddress.asName(_context)}:', style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput)), - buildIconWeb( - icon: SvgPicture.asset(_imagePaths.icAddEmailAddress, fit: BoxFit.fill), - tooltip: AppLocalizations.of(_context).email_address_suggestion, - onTap: () => {}), Expanded(child: Padding( - padding: EdgeInsets.only(right: _listEmailAddressType.isNotEmpty ? 16 : 0), + padding: EdgeInsets.only(right: _listEmailAddressType.length == 2 ? 8 : 8), child: _buildTagEditor())), if (_prefixEmailAddress == PrefixEmailAddress.to) Row(children: [ if (!_listEmailAddressType.contains(PrefixEmailAddress.cc)) - Transform( - transform: Matrix4.translationValues( - _listEmailAddressType.contains(PrefixEmailAddress.bcc) ? 0.0 : _responsiveUtils.isMobile(_context) ? 24 : 16.0, - 0.0, 0.0), - child: buildTextCircleButton(AppLocalizations.of(_context).cc_email_address_prefix, - textStyle: TextStyle( - fontSize: 15, - fontWeight: FontWeight.normal, - decoration: TextDecoration.underline, - color: AppColor.lineItemListColor), - onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc))), + buildTextIcon(AppLocalizations.of(_context).cc_email_address_prefix, + padding: EdgeInsets.all(5), + textStyle: TextStyle( + fontSize: 15, + fontWeight: FontWeight.normal, + decoration: TextDecoration.underline, + color: AppColor.lineItemListColor), + onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc)), if (!_listEmailAddressType.contains(PrefixEmailAddress.bcc)) - buildTextCircleButton(AppLocalizations.of(_context).bcc_email_address_prefix, + buildTextIcon(AppLocalizations.of(_context).bcc_email_address_prefix, + padding: EdgeInsets.all(5), textStyle: TextStyle( fontSize: 15, fontWeight: FontWeight.normal, decoration: TextDecoration.underline, color: AppColor.lineItemListColor), onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc)), + SizedBox(width: 10), ]), if (_prefixEmailAddress != PrefixEmailAddress.to) buildIconWeb( @@ -130,7 +127,6 @@ class EmailAddressInputBuilder { child: TagEditor( length: newListEmailAddress.length, controller: controller, - focusNode: focusNode, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.done, hasAddButton: false, @@ -138,6 +134,10 @@ class EmailAddressInputBuilder { delimiters: [' '], minTextFieldWidth: 20, resetTextOnSubmitted: true, + suggestionsBoxElevation: 20, + suggestionsBoxBackgroundColor: Colors.white, + suggestionsBoxRadius: 20, + iconSuggestionBox: SvgPicture.asset(_imagePaths.icAddEmailAddress, fit: BoxFit.fill), textStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500), onSubmitted: (value) { setState(() => _listEmailAddress.add(EmailAddress(null, value))); @@ -182,8 +182,14 @@ class EmailAddressInputBuilder { _onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress); }, findSuggestions: (String query) { - if (query.isNotEmpty && _onSuggestionEmailAddress != null) { - return _onSuggestionEmailAddress!(query); + if (query.trim().isNotEmpty && _onSuggestionEmailAddress != null) { + return _onSuggestionEmailAddress!(query.trim()); + } + return []; + }, + searchAllSuggestions: () { + if (_onOpenSuggestionBoxEmailAddress != null) { + return _onOpenSuggestionBoxEmailAddress!(); } return []; }, diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index ff1a2bc1c..a286714f2 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -241,15 +241,15 @@ class EmailView extends GetView with UserSettingPopupMenuMixin { if (email.from.numberEmailAddress() > 0) _buildEmailAddressByPrefix(context, email, PrefixEmailAddress.from, isDisplayFull), if (email.to.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND) - _buildDivider(edgeInsets: EdgeInsets.only(top: 8, bottom: 4)), + _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)), if (email.to.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND) _buildEmailAddressByPrefix(context, email, PrefixEmailAddress.to, isDisplayFull), if (email.cc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull) - _buildDivider(edgeInsets: EdgeInsets.only(top: 8, bottom: 4)), + _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)), if (email.cc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull) _buildEmailAddressByPrefix(context, email, PrefixEmailAddress.cc, isDisplayFull), if (email.bcc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull) - _buildDivider(edgeInsets: EdgeInsets.only(top: 8, bottom: 4)), + _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)), if (email.bcc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull) _buildEmailAddressByPrefix(context, email, PrefixEmailAddress.bcc, isDisplayFull), ], diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index de7a1fd03..41505e946 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -268,6 +268,8 @@ class MailboxController extends BaseMailboxController { if (!responsiveUtils.isDesktop(context) && !responsiveUtils.isTabletLarge(context)) { mailboxDashBoardController.closeDrawer(); + } else { + mailboxDashBoardController.dispatchRoute(AppRoutes.THREAD); } } diff --git a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart index 57e8f27ca..6e453a396 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart @@ -2,6 +2,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displayed.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -138,7 +139,7 @@ class MailBoxFolderTileBuilder { left: allSelectMode == SelectMode.ACTIVE ? 0 : 8, right: allSelectMode == SelectMode.ACTIVE ? 8 : 0), child: SvgPicture.asset( - _imagePaths.icFolderMailbox, + '${_mailboxNode.item.getMailboxIcon(_imagePaths)}', width: 28, height: 28, fit: BoxFit.fill diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index c73f8e9fa..0101d685e 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -396,6 +396,15 @@ class ThreadController extends BaseController { currentSelectMode.value = SelectMode.ACTIVE; } + void setSelectAllEmailAction() { + if (isSearchActive()) { + emailListSearch.value = emailListSearch.map((email) => email.toSelectedEmail(selectMode: SelectMode.ACTIVE)).toList(); + } else { + emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.ACTIVE)).toList(); + } + currentSelectMode.value = SelectMode.ACTIVE; + } + List get listEmailSelected { if (isSearchActive()) { return emailListSearch.where((email) => email.selectMode == SelectMode.ACTIVE).toList(); diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 8b339076b..93e72061d 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -126,7 +126,7 @@ class ThreadView extends GetWidget with UserSettingPopupMenuMi ..radiusSplash(10) ..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8)) ..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread)) - ..onPressActionClick(() => controller.enableSelectionEmail()) + ..onPressActionClick(() => controller.setSelectAllEmailAction()) ..text(AppLocalizations.of(context).select_all, isVertical: false)) .build(), SizedBox(width: 16), @@ -346,7 +346,7 @@ class ThreadView extends GetWidget with UserSettingPopupMenuMi Widget _buildFloatingButtonCompose(BuildContext context) { return Obx(() { - if (!controller.isSearchActive() && !controller.isSelectionEnabled() && !_responsiveUtils.isDesktop(context)) { + if (!controller.isSearchActive() && !_responsiveUtils.isDesktop(context)) { return Container( padding: EdgeInsets.only(bottom: controller.isSelectionEnabled() ? 80 : _responsiveUtils.isMobileDevice(context) ? 0 : 16), child: Align( diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index ad01f0734..b4d5c3f12 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -902,13 +902,6 @@ class AppLocalizations { name: 'hint_compose_email'); } - String get email_address_suggestion { - return Intl.message( - 'Email address suggestion', - name: 'email_address_suggestion', - ); - } - String get attach_file { return Intl.message( 'Attach file',