From bfdd6af3f75bd8069cfbda3a8e9942fbcb76e37c Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 7 Oct 2025 13:52:03 +0700 Subject: [PATCH] TF-4013 Unified UX between mobile and web (cherry picked from commit 298afd1871aedc3549191b16796241aec9b4552d) --- .../presentation/composer_controller.dart | 115 +----- .../composer/presentation/composer_view.dart | 361 +++++++++--------- .../presentation/composer_view_web.dart | 23 +- .../handle_edit_recipient_extension.dart | 13 +- ...andle_recipients_collapsed_extensions.dart | 6 +- ...ss_between_recipient_fields_extension.dart | 5 - .../setup_email_recipients_extension.dart | 5 - .../list_recipients_collapsed_widget.dart | 29 +- .../widgets/recipient_composer_widget.dart | 174 +++++---- .../widgets/recipient_tag_item_widget.dart | 85 +---- .../recipient_composer_widget_test.dart | 25 +- 11 files changed, 335 insertions(+), 506 deletions(-) diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index bffdebf39..54d9b93d3 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -139,10 +139,6 @@ class ComposerController extends BaseController final isInitialRecipient = false.obs; final subjectEmail = Rxn(); final screenDisplayMode = ScreenDisplayMode.normal.obs; - final toAddressExpandMode = ExpandMode.EXPAND.obs; - final ccAddressExpandMode = ExpandMode.EXPAND.obs; - final bccAddressExpandMode = ExpandMode.EXPAND.obs; - final replyToAddressExpandMode = ExpandMode.EXPAND.obs; final emailContentsViewState = Rxn>(); final hasRequestReadReceipt = false.obs; final fromRecipientState = PrefixRecipientState.disabled.obs; @@ -602,9 +598,8 @@ class ComposerController extends BaseController && !responsiveUtils.isScreenWithShortestSide(currentContext!)) { richTextMobileTabletController?.richTextController.hideRichTextView(); } - _collapseAllRecipient(); autoCreateEmailTag(); - if (PlatformInfo.isWeb && isRecipientsNotEmpty) { + if (isRecipientsNotEmpty) { hideAllRecipients(); } } @@ -725,33 +720,11 @@ class ComposerController extends BaseController listBccEmailAddress = List.from(recipients.bcc); listReplyToEmailAddress = List.from(recipients.replyTo); - if (PlatformInfo.isWeb) { - if (isRecipientsNotEmpty) { - hideAllRecipients(); - isInitialRecipient.value = true; - } else { - toRecipientState.value = PrefixRecipientState.enabled; - } + if (isRecipientsNotEmpty) { + hideAllRecipients(); + isInitialRecipient.value = true; } else { - if (isRecipientsNotEmpty) { - isInitialRecipient.value = true; - toAddressExpandMode.value = ExpandMode.COLLAPSE; - } - - if (listCcEmailAddress.isNotEmpty) { - ccRecipientState.value = PrefixRecipientState.enabled; - ccAddressExpandMode.value = ExpandMode.COLLAPSE; - } - - if (listBccEmailAddress.isNotEmpty) { - bccRecipientState.value = PrefixRecipientState.enabled; - bccAddressExpandMode.value = ExpandMode.COLLAPSE; - } - - if (listReplyToEmailAddress.isNotEmpty) { - replyToRecipientState.value = PrefixRecipientState.enabled; - replyToAddressExpandMode.value = ExpandMode.COLLAPSE; - } + toRecipientState.value = PrefixRecipientState.enabled; } updateStatusEmailSendButton(); } @@ -802,7 +775,6 @@ class ComposerController extends BaseController || ccEmailAddressController.text.isNotEmpty || bccEmailAddressController.text.isNotEmpty || replyToEmailAddressController.text.isNotEmpty) { - _collapseAllRecipient(); autoCreateEmailTag(); } @@ -824,12 +796,7 @@ class ComposerController extends BaseController MessageDialogActionManager().showConfirmDialogAction(context, appLocalizations.message_dialog_send_email_with_email_address_invalid, appLocalizations.fix_email_addresses, - onConfirmAction: () { - toAddressExpandMode.value = ExpandMode.EXPAND; - ccAddressExpandMode.value = ExpandMode.EXPAND; - bccAddressExpandMode.value = ExpandMode.EXPAND; - replyToAddressExpandMode.value = ExpandMode.EXPAND; - }, + onConfirmAction: showFullRecipients, showAsBottomSheet: true, title: appLocalizations.sending_failed, hasCancelButton: false, @@ -1473,8 +1440,7 @@ class ComposerController extends BaseController void clickOutsideComposer(BuildContext context) { clearFocus(context); - if (PlatformInfo.isWeb && isRecipientsNotEmpty) { - _collapseAllRecipient(); + if (isRecipientsNotEmpty) { hideAllRecipients(); } } @@ -1555,13 +1521,6 @@ class ComposerController extends BaseController updatePrefixRootState(); } - void _collapseAllRecipient() { - toAddressExpandMode.value = ExpandMode.COLLAPSE; - ccAddressExpandMode.value = ExpandMode.COLLAPSE; - bccAddressExpandMode.value = ExpandMode.COLLAPSE; - replyToAddressExpandMode.value = ExpandMode.COLLAPSE; - } - void clearFocusRecipients() { toAddressFocusNode?.unfocus(); ccAddressFocusNode?.unfocus(); @@ -1599,47 +1558,8 @@ class ComposerController extends BaseController } } - void showFullEmailAddress(PrefixEmailAddress prefixEmailAddress) { - switch(prefixEmailAddress) { - case PrefixEmailAddress.to: - toAddressExpandMode.value = ExpandMode.EXPAND; - toAddressFocusNode?.requestFocus(); - break; - case PrefixEmailAddress.cc: - ccAddressExpandMode.value = ExpandMode.EXPAND; - ccAddressFocusNode?.requestFocus(); - break; - case PrefixEmailAddress.bcc: - bccAddressExpandMode.value = ExpandMode.EXPAND; - bccAddressFocusNode?.requestFocus(); - break; - case PrefixEmailAddress.replyTo: - replyToAddressExpandMode.value = ExpandMode.EXPAND; - replyToAddressFocusNode?.requestFocus(); - break; - default: - break; - } - } - void onEmailAddressFocusChange(PrefixEmailAddress prefixEmailAddress, bool isFocus) { if (isFocus) { - switch(prefixEmailAddress) { - case PrefixEmailAddress.to: - toAddressExpandMode.value = ExpandMode.EXPAND; - break; - case PrefixEmailAddress.cc: - ccAddressExpandMode.value = ExpandMode.EXPAND; - break; - case PrefixEmailAddress.bcc: - bccAddressExpandMode.value = ExpandMode.EXPAND; - break; - case PrefixEmailAddress.replyTo: - replyToAddressExpandMode.value = ExpandMode.EXPAND; - break; - default: - break; - } _closeSuggestionBox(); if (PlatformInfo.isMobile && currentContext != null @@ -1649,28 +1569,24 @@ class ComposerController extends BaseController } else { switch(prefixEmailAddress) { case PrefixEmailAddress.to: - toAddressExpandMode.value = ExpandMode.COLLAPSE; final inputToEmail = toEmailAddressController.text; if (inputToEmail.trim().isNotEmpty) { autoCreateEmailTagForType(PrefixEmailAddress.to, inputToEmail); } break; case PrefixEmailAddress.cc: - ccAddressExpandMode.value = ExpandMode.COLLAPSE; final inputCcEmail = ccEmailAddressController.text; if (inputCcEmail.trim().isNotEmpty) { autoCreateEmailTagForType(PrefixEmailAddress.cc, inputCcEmail); } break; case PrefixEmailAddress.bcc: - bccAddressExpandMode.value = ExpandMode.COLLAPSE; final inputBccEmail = bccEmailAddressController.text; if (inputBccEmail.trim().isNotEmpty) { autoCreateEmailTagForType(PrefixEmailAddress.bcc, inputBccEmail); } break; case PrefixEmailAddress.replyTo: - replyToAddressExpandMode.value = ExpandMode.COLLAPSE; final inputReplyToEmail = replyToEmailAddressController.text; if (inputReplyToEmail.trim().isNotEmpty) { autoCreateEmailTagForType(PrefixEmailAddress.replyTo, inputReplyToEmail); @@ -1722,10 +1638,6 @@ class ComposerController extends BaseController } else { listBccEmailAddress = listEmailAddress.toList(); } - toAddressExpandMode.value = ExpandMode.COLLAPSE; - ccAddressExpandMode.value = ExpandMode.COLLAPSE; - bccAddressExpandMode.value = ExpandMode.COLLAPSE; - bccAddressExpandMode.refresh(); updateStatusEmailSendButton(); } @@ -1736,9 +1648,6 @@ class ComposerController extends BaseController if (listBccEmailAddress.isEmpty) { bccRecipientState.value = PrefixRecipientState.disabled; } - toAddressExpandMode.value = ExpandMode.COLLAPSE; - ccAddressExpandMode.value = ExpandMode.COLLAPSE; - bccAddressExpandMode.value = ExpandMode.COLLAPSE; updateStatusEmailSendButton(); } @@ -1813,8 +1722,10 @@ class ComposerController extends BaseController const Duration(milliseconds: 300), richTextMobileTabletController?.richTextController.showDeviceKeyboard); } - _collapseAllRecipient(); autoCreateEmailTag(); + if (isRecipientsNotEmpty) { + hideAllRecipients(); + } } void _onChangeCursorOnMobile(List? coordinates, BuildContext context) { @@ -1946,15 +1857,11 @@ class ComposerController extends BaseController popBack(); } autoCreateEmailTag(); - if (PlatformInfo.isWeb && isRecipientsNotEmpty) { + if (isRecipientsNotEmpty) { hideAllRecipients(); } } - void handleOnMouseDownHtmlEditorWeb() { - _collapseAllRecipient(); - } - FocusNode? getNextFocusOfToEmailAddress() { if (ccRecipientState.value == PrefixRecipientState.enabled) { return ccAddressFocusNode; diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index abb7655cc..638c26c18 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -6,12 +6,15 @@ import 'package:flutter/foundation.dart'; 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:model/email/prefix_email_address.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_content_height_exceeded_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_edit_recipient_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_open_context_menu_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart'; @@ -19,6 +22,7 @@ import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_ import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_editor_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/mobile/tablet_container_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/list_recipients_collapsed_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/app_bar_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/from_composer_mobile_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/landscape_app_bar_composer_widget.dart'; @@ -121,58 +125,48 @@ class ComposerView extends GetWidget { return const SizedBox.shrink(); } }), - Obx(() => RecipientComposerWidget( - prefix: PrefixEmailAddress.to, - listEmailAddress: controller.listToEmailAddress, - imagePaths: controller.imagePaths, - maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - fromState: controller.fromRecipientState.value, - ccState: controller.ccRecipientState.value, - bccState: controller.bccRecipientState.value, - replyToState: controller.replyToRecipientState.value, - expandMode: controller.toAddressExpandMode.value, - controller: controller.toEmailAddressController, - focusNode: controller.toAddressFocusNode, - keyTagEditor: controller.keyToEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - nextFocusNode: controller.getNextFocusOfToEmailAddress(), - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onAddEmailAddressTypeAction: controller.addEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, - )), + Obx(() { + if (controller.recipientsCollapsedState.value == PrefixRecipientState.enabled) { + return RecipientsCollapsedComposerWidget( + listEmailAddress: controller.allListEmailAddress, + margin: ComposerStyle.mobileRecipientMargin, + onShowAllRecipientsAction: controller.showFullRecipients, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.toRecipientState.value == PrefixRecipientState.enabled) { + return _buildRecipientComposerWidget( + prefix: PrefixEmailAddress.to, + controller: controller, + maxWidth: constraints.maxWidth, + listEmailAddress: controller.listToEmailAddress, + textController: controller.toEmailAddressController, + focusNode: controller.toAddressFocusNode, + focusNodeKeyboard: controller.toAddressFocusNodeKeyboard, + keyTagEditor: controller.keyToEmailTagEditor, + nextFocusNode: controller.getNextFocusOfToEmailAddress(), + isMobile: true, + ); + } else { + return const SizedBox.shrink(); + } + }), Obx(() { if (controller.ccRecipientState.value == PrefixRecipientState.enabled) { - return RecipientComposerWidget( + return _buildRecipientComposerWidget( prefix: PrefixEmailAddress.cc, - listEmailAddress: controller.listCcEmailAddress, - imagePaths: controller.imagePaths, + controller: controller, maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - expandMode: controller.ccAddressExpandMode.value, - controller: controller.ccEmailAddressController, + listEmailAddress: controller.listCcEmailAddress, + textController: controller.ccEmailAddressController, focusNode: controller.ccAddressFocusNode, + focusNodeKeyboard: controller.ccAddressFocusNodeKeyboard, keyTagEditor: controller.keyCcEmailTagEditor, - isInitial: controller.isInitialRecipient.value, nextFocusNode: controller.getNextFocusOfCcEmailAddress(), - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, + isMobile: true, ); } else { return const SizedBox.shrink(); @@ -180,28 +174,17 @@ class ComposerView extends GetWidget { }), Obx(() { if (controller.bccRecipientState.value == PrefixRecipientState.enabled) { - return RecipientComposerWidget( + return _buildRecipientComposerWidget( prefix: PrefixEmailAddress.bcc, - listEmailAddress: controller.listBccEmailAddress, - imagePaths: controller.imagePaths, + controller: controller, maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - expandMode: controller.bccAddressExpandMode.value, - controller: controller.bccEmailAddressController, + listEmailAddress: controller.listBccEmailAddress, + textController: controller.bccEmailAddressController, focusNode: controller.bccAddressFocusNode, + focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, keyTagEditor: controller.keyBccEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, nextFocusNode: controller.getNextFocusOfBccEmailAddress(), - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, + isMobile: true, ); } else { return const SizedBox.shrink(); @@ -209,28 +192,17 @@ class ComposerView extends GetWidget { }), Obx(() { if (controller.replyToRecipientState.value == PrefixRecipientState.enabled) { - return RecipientComposerWidget( + return _buildRecipientComposerWidget( prefix: PrefixEmailAddress.replyTo, - listEmailAddress: controller.listReplyToEmailAddress, - imagePaths: controller.imagePaths, + controller: controller, maxWidth: constraints.maxWidth, - expandMode: controller.replyToAddressExpandMode.value, - controller: controller.replyToEmailAddressController, + listEmailAddress: controller.listReplyToEmailAddress, + textController: controller.replyToEmailAddressController, focusNode: controller.replyToAddressFocusNode, + focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard, keyTagEditor: controller.keyReplyToEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, nextFocusNode: controller.subjectEmailInputFocusNode, - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onAddEmailAddressTypeAction: controller.addEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, + isMobile: true, ); } else { return const SizedBox.shrink(); @@ -332,105 +304,89 @@ class ComposerView extends GetWidget { margin: ComposerStyle.mobileRecipientMargin, onChangeIdentity: controller.onChangeIdentity, ), - RecipientComposerWidget( - prefix: PrefixEmailAddress.to, - listEmailAddress: controller.listToEmailAddress, - imagePaths: controller.imagePaths, - maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - fromState: controller.fromRecipientState.value, - ccState: controller.ccRecipientState.value, - bccState: controller.bccRecipientState.value, - replyToState: controller.replyToRecipientState.value, - expandMode: controller.toAddressExpandMode.value, - controller: controller.toEmailAddressController, - focusNode: controller.toAddressFocusNode, - keyTagEditor: controller.keyToEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - nextFocusNode: controller.getNextFocusOfToEmailAddress(), - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onAddEmailAddressTypeAction: controller.addEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, - ), - if (controller.ccRecipientState.value == PrefixRecipientState.enabled) - RecipientComposerWidget( - prefix: PrefixEmailAddress.cc, - listEmailAddress: controller.listCcEmailAddress, - imagePaths: controller.imagePaths, - maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - expandMode: controller.ccAddressExpandMode.value, - controller: controller.ccEmailAddressController, - focusNode: controller.ccAddressFocusNode, - keyTagEditor: controller.keyCcEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - nextFocusNode: controller.getNextFocusOfCcEmailAddress(), - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, - ), - if (controller.bccRecipientState.value == PrefixRecipientState.enabled) - RecipientComposerWidget( - prefix: PrefixEmailAddress.bcc, - listEmailAddress: controller.listBccEmailAddress, - imagePaths: controller.imagePaths, - maxWidth: constraints.maxWidth, - minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - expandMode: controller.bccAddressExpandMode.value, - controller: controller.bccEmailAddressController, - focusNode: controller.bccAddressFocusNode, - keyTagEditor: controller.keyBccEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - nextFocusNode: controller.getNextFocusOfBccEmailAddress(), - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, - ), - if (controller.replyToRecipientState.value == PrefixRecipientState.enabled) - RecipientComposerWidget( - prefix: PrefixEmailAddress.replyTo, - listEmailAddress: controller.listReplyToEmailAddress, - imagePaths: controller.imagePaths, - maxWidth: constraints.maxWidth, - expandMode: controller.replyToAddressExpandMode.value, - controller: controller.replyToEmailAddressController, - focusNode: controller.replyToAddressFocusNode, - keyTagEditor: controller.keyReplyToEmailTagEditor, - isInitial: controller.isInitialRecipient.value, - nextFocusNode: controller.subjectEmailInputFocusNode, - padding: ComposerStyle.mobileRecipientPadding, - margin: ComposerStyle.mobileRecipientMargin, - onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, - onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, - onUpdateListEmailAddressAction: controller.updateListEmailAddress, - onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, - onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onEditRecipientAction: controller.onEditRecipient, - onClearFocusAction: controller.onClearFocusAction, - ), + Obx(() { + if (controller.recipientsCollapsedState.value == PrefixRecipientState.enabled) { + return RecipientsCollapsedComposerWidget( + listEmailAddress: controller.allListEmailAddress, + margin: ComposerStyle.mobileRecipientMargin, + onShowAllRecipientsAction: controller.showFullRecipients, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.toRecipientState.value == PrefixRecipientState.enabled) { + return _buildRecipientComposerWidget( + prefix: PrefixEmailAddress.to, + controller: controller, + maxWidth: constraints.maxWidth, + listEmailAddress: controller.listToEmailAddress, + textController: controller.toEmailAddressController, + focusNode: controller.toAddressFocusNode, + focusNodeKeyboard: controller.toAddressFocusNodeKeyboard, + keyTagEditor: controller.keyToEmailTagEditor, + nextFocusNode: controller.getNextFocusOfToEmailAddress(), + isMobile: true, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.ccRecipientState.value == PrefixRecipientState.enabled) { + return _buildRecipientComposerWidget( + prefix: PrefixEmailAddress.cc, + controller: controller, + maxWidth: constraints.maxWidth, + listEmailAddress: controller.listCcEmailAddress, + textController: controller.ccEmailAddressController, + focusNode: controller.ccAddressFocusNode, + focusNodeKeyboard: controller.ccAddressFocusNodeKeyboard, + keyTagEditor: controller.keyCcEmailTagEditor, + nextFocusNode: controller.getNextFocusOfCcEmailAddress(), + isMobile: true, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.bccRecipientState.value == PrefixRecipientState.enabled) { + return _buildRecipientComposerWidget( + prefix: PrefixEmailAddress.bcc, + controller: controller, + maxWidth: constraints.maxWidth, + listEmailAddress: controller.listBccEmailAddress, + textController: controller.bccEmailAddressController, + focusNode: controller.bccAddressFocusNode, + focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, + keyTagEditor: controller.keyBccEmailTagEditor, + nextFocusNode: controller.getNextFocusOfBccEmailAddress(), + isMobile: true, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.replyToRecipientState.value == PrefixRecipientState.enabled) { + return _buildRecipientComposerWidget( + prefix: PrefixEmailAddress.replyTo, + controller: controller, + maxWidth: constraints.maxWidth, + listEmailAddress: controller.listReplyToEmailAddress, + textController: controller.replyToEmailAddressController, + focusNode: controller.replyToAddressFocusNode, + focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard, + keyTagEditor: controller.keyReplyToEmailTagEditor, + nextFocusNode: controller.subjectEmailInputFocusNode, + isMobile: true, + ); + } else { + return const SizedBox.shrink(); + } + }), ], )), SubjectComposerWidget( @@ -525,4 +481,53 @@ class ComposerView extends GetWidget { ..onActionClick((_) => controller.openFilePickerByType(context, FileType.any))) .build(); } + + Widget _buildRecipientComposerWidget({ + required PrefixEmailAddress prefix, + required ComposerController controller, + required double maxWidth, + required List listEmailAddress, + required TextEditingController textController, + required FocusNode? focusNode, + required FocusNode? focusNodeKeyboard, + required GlobalKey keyTagEditor, + required FocusNode? nextFocusNode, + bool isMobile = false, + }) { + return Obx(() => RecipientComposerWidget( + prefix: prefix, + prefixRootState: controller.prefixRootState.value, + fromState: controller.fromRecipientState.value, + toState: controller.toRecipientState.value, + ccState: controller.ccRecipientState.value, + bccState: controller.bccRecipientState.value, + replyToState: controller.replyToRecipientState.value, + listEmailAddress: listEmailAddress, + imagePaths: controller.imagePaths, + maxWidth: maxWidth, + minInputLengthAutocomplete: controller.minInputLengthAutocomplete, + controller: textController, + focusNode: focusNode, + focusNodeKeyboard: focusNodeKeyboard, + keyTagEditor: keyTagEditor, + isInitial: controller.isInitialRecipient.value, + nextFocusNode: nextFocusNode, + padding: isMobile + ? ComposerStyle.mobileRecipientPadding + : ComposerStyle.desktopRecipientPadding, + margin: isMobile + ? ComposerStyle.mobileRecipientMargin + : ComposerStyle.desktopRecipientMargin, + onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, + onUpdateListEmailAddressAction: controller.updateListEmailAddress, + onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, + onFocusNextAddressAction: controller.handleFocusNextAddressAction, + onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress, + onEditRecipientAction: controller.onEditRecipient, + onClearFocusAction: controller.onClearFocusAction, + onAddEmailAddressTypeAction: controller.addEmailAddressType, + onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, + onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction, + )); + } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index 45c237b9a..573dccfc4 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/prefix_email_address.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart'; import 'package:tmail_ui_user/features/base/widget/dialog_picker/color_dialog_picker.dart'; @@ -134,7 +133,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listToEmailAddress, - expandMode: controller.toAddressExpandMode.value, textController: controller.toEmailAddressController, focusNode: controller.toAddressFocusNode, focusNodeKeyboard: controller.toAddressFocusNodeKeyboard, @@ -149,7 +147,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listCcEmailAddress, - expandMode: controller.ccAddressExpandMode.value, textController: controller.ccEmailAddressController, focusNode: controller.ccAddressFocusNode, focusNodeKeyboard: controller.ccAddressFocusNodeKeyboard, @@ -164,7 +161,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listBccEmailAddress, - expandMode: controller.bccAddressExpandMode.value, textController: controller.bccEmailAddressController, focusNode: controller.bccAddressFocusNode, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, @@ -179,7 +175,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listReplyToEmailAddress, - expandMode: controller.replyToAddressExpandMode.value, textController: controller.replyToEmailAddressController, focusNode: controller.replyToAddressFocusNode, focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard, @@ -215,7 +210,6 @@ class ComposerView extends GetWidget { onInitial: controller.handleInitHtmlEditorWeb, onChangeContent: controller.onChangeTextEditorWeb, onFocus: controller.handleOnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, height: constraintsEditor.maxHeight, @@ -366,7 +360,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listToEmailAddress, - expandMode: controller.toAddressExpandMode.value, textController: controller.toEmailAddressController, focusNode: controller.toAddressFocusNode, focusNodeKeyboard: controller.toAddressFocusNodeKeyboard, @@ -380,7 +373,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listCcEmailAddress, - expandMode: controller.ccAddressExpandMode.value, textController: controller.ccEmailAddressController, focusNode: controller.ccAddressFocusNode, focusNodeKeyboard: controller.ccAddressFocusNodeKeyboard, @@ -394,7 +386,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listBccEmailAddress, - expandMode: controller.bccAddressExpandMode.value, textController: controller.bccEmailAddressController, focusNode: controller.bccAddressFocusNode, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, @@ -408,7 +399,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listReplyToEmailAddress, - expandMode: controller.replyToAddressExpandMode.value, textController: controller.replyToEmailAddressController, focusNode: controller.replyToAddressFocusNode, focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard, @@ -457,7 +447,6 @@ class ComposerView extends GetWidget { onInitial: controller.handleInitHtmlEditorWeb, onChangeContent: controller.onChangeTextEditorWeb, onFocus: controller.handleOnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onEditorSettings: controller.richTextWebController?.onEditorSettingsChange, onEditorTextSizeChanged: controller.richTextWebController?.onEditorTextSizeChanged, height: constraintsEditor.maxHeight, @@ -639,7 +628,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listToEmailAddress, - expandMode: controller.toAddressExpandMode.value, textController: controller.toEmailAddressController, focusNode: controller.toAddressFocusNode, focusNodeKeyboard: controller.toAddressFocusNodeKeyboard, @@ -653,7 +641,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listCcEmailAddress, - expandMode: controller.ccAddressExpandMode.value, textController: controller.ccEmailAddressController, focusNode: controller.ccAddressFocusNode, focusNodeKeyboard: controller.ccAddressFocusNodeKeyboard, @@ -667,7 +654,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listBccEmailAddress, - expandMode: controller.bccAddressExpandMode.value, textController: controller.bccEmailAddressController, focusNode: controller.bccAddressFocusNode, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, @@ -681,7 +667,6 @@ class ComposerView extends GetWidget { controller: controller, maxWidth: constraints.maxWidth, listEmailAddress: controller.listReplyToEmailAddress, - expandMode: controller.replyToAddressExpandMode.value, textController: controller.replyToEmailAddressController, focusNode: controller.replyToAddressFocusNode, focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard, @@ -729,7 +714,6 @@ class ComposerView extends GetWidget { onInitial: controller.handleInitHtmlEditorWeb, onChangeContent: controller.onChangeTextEditorWeb, onFocus: controller.handleOnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, height: constraintsBody.maxHeight, @@ -866,7 +850,6 @@ class ComposerView extends GetWidget { required ComposerController controller, required double maxWidth, required List listEmailAddress, - required ExpandMode expandMode, required TextEditingController textController, required FocusNode? focusNode, required FocusNode? focusNodeKeyboard, @@ -887,7 +870,6 @@ class ComposerView extends GetWidget { imagePaths: controller.imagePaths, maxWidth: maxWidth, minInputLengthAutocomplete: controller.minInputLengthAutocomplete, - expandMode: expandMode, controller: textController, focusNode: focusNode, focusNodeKeyboard: focusNodeKeyboard, @@ -901,16 +883,15 @@ class ComposerView extends GetWidget { ? ComposerStyle.mobileRecipientMargin : ComposerStyle.desktopRecipientMargin, onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, - onShowFullListEmailAddressAction: controller.showFullEmailAddress, onUpdateListEmailAddressAction: controller.updateListEmailAddress, onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, onFocusNextAddressAction: controller.handleFocusNextAddressAction, - onRemoveDraggableEmailAddressAction: - controller.removeDraggableEmailAddress, + onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress, onEditRecipientAction: controller.onEditRecipient, onClearFocusAction: controller.onClearFocusAction, onAddEmailAddressTypeAction: controller.addEmailAddressType, onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, + onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction, )); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/handle_edit_recipient_extension.dart b/lib/features/composer/presentation/extensions/handle_edit_recipient_extension.dart index f5f651a93..79247a41f 100644 --- a/lib/features/composer/presentation/extensions/handle_edit_recipient_extension.dart +++ b/lib/features/composer/presentation/extensions/handle_edit_recipient_extension.dart @@ -5,7 +5,6 @@ import 'package:flutter/services.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/prefix_email_address.dart'; import 'package:model/extensions/email_address_extension.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_create_new_rule_filter.dart'; @@ -60,8 +59,7 @@ extension HandleEditRecipientExtension on ComposerController { switch(prefix) { case PrefixEmailAddress.to: listToEmailAddress.remove(emailAddress); - toAddressExpandMode.value = ExpandMode.EXPAND; - toAddressExpandMode.refresh(); + toRecipientState.refresh(); _setTextAndFocus( controller: toEmailAddressController, focusNode: toAddressFocusNode, @@ -70,8 +68,7 @@ extension HandleEditRecipientExtension on ComposerController { break; case PrefixEmailAddress.cc: listCcEmailAddress.remove(emailAddress); - ccAddressExpandMode.value = ExpandMode.EXPAND; - ccAddressExpandMode.refresh(); + ccRecipientState.refresh(); _setTextAndFocus( controller: ccEmailAddressController, focusNode: ccAddressFocusNode, @@ -80,8 +77,7 @@ extension HandleEditRecipientExtension on ComposerController { break; case PrefixEmailAddress.bcc: listBccEmailAddress.remove(emailAddress); - bccAddressExpandMode.value = ExpandMode.EXPAND; - bccAddressExpandMode.refresh(); + bccRecipientState.refresh(); _setTextAndFocus( controller: bccEmailAddressController, focusNode: bccAddressFocusNode, @@ -90,8 +86,7 @@ extension HandleEditRecipientExtension on ComposerController { break; case PrefixEmailAddress.replyTo: listReplyToEmailAddress.remove(emailAddress); - replyToAddressExpandMode.value = ExpandMode.EXPAND; - replyToAddressExpandMode.refresh(); + replyToRecipientState.refresh(); _setTextAndFocus( controller: replyToEmailAddressController, focusNode: replyToAddressFocusNode, diff --git a/lib/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart b/lib/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart index b2f60a023..9bd32e8fb 100644 --- a/lib/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart +++ b/lib/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart @@ -1,7 +1,6 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/prefix_email_address.dart'; import 'package:model/extensions/email_address_extension.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; @@ -31,22 +30,18 @@ extension HandleRecipientsCollapsedExtensions on ComposerController { if (listToEmailAddress.isNotEmpty) { toRecipientState.value = PrefixRecipientState.enabled; - toAddressExpandMode.value = ExpandMode.EXPAND; } if (listCcEmailAddress.isNotEmpty) { ccRecipientState.value = PrefixRecipientState.enabled; - ccAddressExpandMode.value = ExpandMode.EXPAND; } if (listBccEmailAddress.isNotEmpty) { bccRecipientState.value = PrefixRecipientState.enabled; - bccAddressExpandMode.value = ExpandMode.EXPAND; } if (listReplyToEmailAddress.isNotEmpty) { replyToRecipientState.value = PrefixRecipientState.enabled; - replyToAddressExpandMode.value = ExpandMode.EXPAND; } updatePrefixRootState(); @@ -96,6 +91,7 @@ extension HandleRecipientsCollapsedExtensions on ComposerController { } void hideAllRecipients() { + fromRecipientState.value = PrefixRecipientState.disabled; toRecipientState.value = PrefixRecipientState.disabled; ccRecipientState.value = PrefixRecipientState.disabled; bccRecipientState.value = PrefixRecipientState.disabled; diff --git a/lib/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart b/lib/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart index 7bff5d0f1..51a7f0523 100644 --- a/lib/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart +++ b/lib/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart @@ -1,5 +1,4 @@ -import 'package:model/mailbox/expand_mode.dart'; import 'package:tmail_ui_user/features/base/model/filter_filter.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart'; @@ -33,19 +32,15 @@ extension RemoveDraggableEmailAddressBetweenRecipientFieldsExtension on Composer switch(draggableEmailAddress.filterField) { case FilterField.to: controller.listToEmailAddress.remove(draggableEmailAddress.emailAddress); - controller.toAddressExpandMode.value = ExpandMode.EXPAND; break; case FilterField.cc: controller.listCcEmailAddress.remove(draggableEmailAddress.emailAddress); - controller.ccAddressExpandMode.value = ExpandMode.EXPAND; break; case FilterField.bcc: controller.listBccEmailAddress.remove(draggableEmailAddress.emailAddress); - controller.bccAddressExpandMode.value = ExpandMode.EXPAND; break; case FilterField.replyTo: controller.listReplyToEmailAddress.remove(draggableEmailAddress.emailAddress); - controller.replyToAddressExpandMode.value = ExpandMode.EXPAND; break; default: break; diff --git a/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart b/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart index 03dc63bca..4240f41a2 100644 --- a/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart @@ -1,6 +1,5 @@ import 'package:model/email/email_action_type.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; @@ -29,7 +28,6 @@ extension SetupEmailRecipientsExtension on ComposerController { if (emailAddressOfTo.isNotEmpty) { listToEmailAddress.addAll(emailAddressOfTo); isInitialRecipient.value = true; - toAddressExpandMode.value = ExpandMode.COLLAPSE; } break; case EmailActionType.composeFromMailtoUri: @@ -40,19 +38,16 @@ extension SetupEmailRecipientsExtension on ComposerController { if (emailAddressOfTo.isNotEmpty) { listToEmailAddress.addAll(emailAddressOfTo); isInitialRecipient.value = true; - toAddressExpandMode.value = ExpandMode.COLLAPSE; } if (emailAddressOfCc.isNotEmpty) { listCcEmailAddress = emailAddressOfCc; ccRecipientState.value = PrefixRecipientState.enabled; - ccAddressExpandMode.value = ExpandMode.COLLAPSE; } if (emailAddressOfBc.isNotEmpty) { listBccEmailAddress = emailAddressOfBc; bccRecipientState.value = PrefixRecipientState.enabled; - bccAddressExpandMode.value = ExpandMode.COLLAPSE; } break; case EmailActionType.reply: diff --git a/lib/features/composer/presentation/widgets/list_recipients_collapsed_widget.dart b/lib/features/composer/presentation/widgets/list_recipients_collapsed_widget.dart index a52db4aa0..111a2cb95 100644 --- a/lib/features/composer/presentation/widgets/list_recipients_collapsed_widget.dart +++ b/lib/features/composer/presentation/widgets/list_recipients_collapsed_widget.dart @@ -29,20 +29,31 @@ class RecipientsCollapsedComposerWidget extends StatelessWidget { List visibleChips = []; int hiddenCount = 0; - for (var emailAddress in listEmailAddress) { - final textWidth = - _estimateTextWidth(context, emailAddress.asString()) + 80; - if (usedWidth + textWidth > maxWidth - 60) { - hiddenCount = listEmailAddress.length - visibleChips.length; - break; - } - usedWidth += textWidth + spacing; + if (listEmailAddress.length == 1) { visibleChips.add( Padding( padding: const EdgeInsetsDirectional.only(end: spacing), - child: RecipientCollapsedItemWidget(emailAddress: emailAddress), + child: RecipientCollapsedItemWidget( + emailAddress: listEmailAddress.first, + ), ), ); + } else { + for (var emailAddress in listEmailAddress) { + final textWidth = + _estimateTextWidth(context, emailAddress.asString()) + 80; + if (usedWidth + textWidth > maxWidth - 60) { + hiddenCount = listEmailAddress.length - visibleChips.length; + break; + } + usedWidth += textWidth + spacing; + visibleChips.add( + Padding( + padding: const EdgeInsetsDirectional.only(end: spacing), + child: RecipientCollapsedItemWidget(emailAddress: emailAddress), + ), + ); + } } if (hiddenCount > 0) { diff --git a/lib/features/composer/presentation/widgets/recipient_composer_widget.dart b/lib/features/composer/presentation/widgets/recipient_composer_widget.dart index 9869e4111..c01973a3b 100644 --- a/lib/features/composer/presentation/widgets/recipient_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/recipient_composer_widget.dart @@ -16,12 +16,11 @@ import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/prefix_email_address.dart'; import 'package:model/extensions/email_address_extension.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:super_tag_editor/tag_editor.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_address_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_named_address_extension.dart'; -import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; @@ -54,7 +53,6 @@ class RecipientComposerWidget extends StatefulWidget { final List listEmailAddress; final ImagePaths imagePaths; final double maxWidth; - final ExpandMode expandMode; final PrefixRecipientState fromState; final PrefixRecipientState toState; final PrefixRecipientState ccState; @@ -71,7 +69,6 @@ class RecipientComposerWidget extends StatefulWidget { final OnSuggestionEmailAddress? onSuggestionEmailAddress; final OnAddEmailAddressTypeAction? onAddEmailAddressTypeAction; final OnDeleteEmailAddressTypeAction? onDeleteEmailAddressTypeAction; - final OnShowFullListEmailAddressAction? onShowFullListEmailAddressAction; final OnFocusEmailAddressChangeAction? onFocusEmailAddressChangeAction; final OnRemoveDraggableEmailAddressAction? onRemoveDraggableEmailAddressAction; final OnEditRecipientAction? onEditRecipientAction; @@ -101,7 +98,6 @@ class RecipientComposerWidget extends StatefulWidget { this.isInitial, this.controller, this.focusNode, - this.expandMode = ExpandMode.EXPAND, this.keyTagEditor, this.nextFocusNode, this.padding, @@ -111,7 +107,6 @@ class RecipientComposerWidget extends StatefulWidget { this.onSuggestionEmailAddress, this.onAddEmailAddressTypeAction, this.onDeleteEmailAddressTypeAction, - this.onShowFullListEmailAddressAction, this.onFocusEmailAddressChangeAction, this.onFocusNextAddressAction, this.onRemoveDraggableEmailAddressAction, @@ -150,6 +145,8 @@ class _RecipientComposerWidgetState extends State { @override Widget build(BuildContext context) { + bool isMobileResponsive = _responsiveUtils.isMobile(context); + return Container( decoration: const BoxDecoration( border: Border( @@ -226,9 +223,7 @@ class _RecipientComposerWidgetState extends State { onSubmitted: (value) => _handleSubmitTagAction.call(value, stateSetter), onTapOutside: (_) {}, - onFocusTextInput: () { - widget.onShowFullListEmailAddressAction?.call(widget.prefix); - }, + onFocusTextInput: () {}, inputDecoration: const InputDecoration(border: InputBorder.none), tagBuilder: (context, index) { final currentEmailAddress = _currentListEmailAddress[index]; @@ -240,13 +235,10 @@ class _RecipientComposerWidgetState extends State { composerId: widget.composerId, currentEmailAddress: currentEmailAddress, currentListEmailAddress: _currentListEmailAddress, - collapsedListEmailAddress: _collapsedListEmailAddress, - isCollapsed: _isCollapse, isTagFocused: _tagIndexFocused == index, maxWidth: widget.maxWidth, - isMobile: _responsiveUtils.isMobile(context), + isMobile: isMobileResponsive, onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter), - onShowFullAction: widget.onShowFullListEmailAddressAction, onEditRecipientAction: widget.onEditRecipientAction, onClearFocusAction: widget.onClearFocusAction, ); @@ -311,75 +303,11 @@ class _RecipientComposerWidgetState extends State { ) ) ), - const SizedBox(width: RecipientComposerWidgetStyle.space), - if (widget.prefix == widget.prefixRootState) - if (PlatformInfo.isWeb || widget.isTestingForWeb) - ...[ - if (widget.fromState == PrefixRecipientState.disabled) - TMailButtonWidget.fromText( - key: Key('prefix_${widget.prefix.name}_recipient_from_button'), - text: AppLocalizations.of(context).from_email_address_prefix, - textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, - backgroundColor: Colors.transparent, - padding: RecipientComposerWidgetStyle.prefixButtonPadding, - margin: RecipientComposerWidgetStyle.recipientMargin, - onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.from), - ), - if (widget.toState == PrefixRecipientState.disabled) - TMailButtonWidget.fromText( - key: Key('prefix_${widget.prefix.name}_recipient_to_button'), - text: AppLocalizations.of(context).to_email_address_prefix, - textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, - backgroundColor: Colors.transparent, - padding: RecipientComposerWidgetStyle.prefixButtonPadding, - margin: RecipientComposerWidgetStyle.recipientMargin, - onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.to), - ), - if (widget.ccState == PrefixRecipientState.disabled) - TMailButtonWidget.fromText( - key: Key('prefix_${widget.prefix.name}_recipient_cc_button'), - text: AppLocalizations.of(context).cc_email_address_prefix, - textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, - backgroundColor: Colors.transparent, - padding: RecipientComposerWidgetStyle.prefixButtonPadding, - margin: RecipientComposerWidgetStyle.recipientMargin, - onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc), - ), - if (widget.bccState == PrefixRecipientState.disabled) - TMailButtonWidget.fromText( - key: Key('prefix_${widget.prefix.name}_recipient_bcc_button'), - text: AppLocalizations.of(context).bcc_email_address_prefix, - textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, - backgroundColor: Colors.transparent, - padding: RecipientComposerWidgetStyle.prefixButtonPadding, - margin: RecipientComposerWidgetStyle.recipientMargin, - onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc), - ), - if (widget.replyToState == PrefixRecipientState.disabled) - TMailButtonWidget.fromText( - key: Key('prefix_${widget.prefix.name}_recipient_reply_to_button'), - text: AppLocalizations.of(context).reply_to_email_address_prefix, - textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, - backgroundColor: Colors.transparent, - padding: RecipientComposerWidgetStyle.prefixButtonPadding, - margin: RecipientComposerWidgetStyle.recipientMargin, - onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.replyTo), - ), - ] - else - TMailButtonWidget.fromIcon( - key: Key('prefix_${widget.prefix.name}_recipient_expand_button'), - icon: _isAllRecipientInputEnabled - ? widget.imagePaths.icChevronUp - : widget.imagePaths.icChevronDownOutline, - backgroundColor: Colors.transparent, - iconSize: 24, - padding: const EdgeInsets.all(5), - iconColor: AppColor.colorLabelComposer, - margin: RecipientComposerWidgetStyle.enableRecipientButtonMargin, - onTapActionCallback: () => widget.onEnableAllRecipientsInputAction?.call(_isAllRecipientInputEnabled), - ) - else if (PlatformInfo.isWeb || widget.isTestingForWeb) + if (widget.prefix == widget.prefixRootState && _isWeb && !isMobileResponsive) + ..._buildListPrefixWidgets(), + if (widget.prefix == widget.prefixRootState && (isMobileResponsive || widget.isTestingForWeb)) + _buildExpandButton(), + if (widget.prefix != widget.prefixRootState && _isWeb && !isMobileResponsive) TMailButtonWidget.fromIcon( icon: widget.imagePaths.icClose, backgroundColor: Colors.transparent, @@ -394,6 +322,82 @@ class _RecipientComposerWidgetState extends State { ); } + bool get _isWeb => PlatformInfo.isWeb || widget.isTestingForWeb; + + List _buildListPrefixWidgets() { + return [ + const SizedBox(width: RecipientComposerWidgetStyle.space), + if (widget.fromState == PrefixRecipientState.disabled) + TMailButtonWidget.fromText( + key: Key('prefix_${widget.prefix.name}_recipient_from_button'), + text: AppLocalizations.of(context).from_email_address_prefix, + textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, + backgroundColor: Colors.transparent, + padding: RecipientComposerWidgetStyle.prefixButtonPadding, + margin: RecipientComposerWidgetStyle.recipientMargin, + onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.from), + ), + if (widget.toState == PrefixRecipientState.disabled) + TMailButtonWidget.fromText( + key: Key('prefix_${widget.prefix.name}_recipient_to_button'), + text: AppLocalizations.of(context).to_email_address_prefix, + textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, + backgroundColor: Colors.transparent, + padding: RecipientComposerWidgetStyle.prefixButtonPadding, + margin: RecipientComposerWidgetStyle.recipientMargin, + onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.to), + ), + if (widget.ccState == PrefixRecipientState.disabled) + TMailButtonWidget.fromText( + key: Key('prefix_${widget.prefix.name}_recipient_cc_button'), + text: AppLocalizations.of(context).cc_email_address_prefix, + textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, + backgroundColor: Colors.transparent, + padding: RecipientComposerWidgetStyle.prefixButtonPadding, + margin: RecipientComposerWidgetStyle.recipientMargin, + onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc), + ), + if (widget.bccState == PrefixRecipientState.disabled) + TMailButtonWidget.fromText( + key: Key('prefix_${widget.prefix.name}_recipient_bcc_button'), + text: AppLocalizations.of(context).bcc_email_address_prefix, + textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, + backgroundColor: Colors.transparent, + padding: RecipientComposerWidgetStyle.prefixButtonPadding, + margin: RecipientComposerWidgetStyle.recipientMargin, + onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc), + ), + if (widget.replyToState == PrefixRecipientState.disabled) + TMailButtonWidget.fromText( + key: Key('prefix_${widget.prefix.name}_recipient_reply_to_button'), + text: AppLocalizations.of(context).reply_to_email_address_prefix, + textStyle: RecipientComposerWidgetStyle.prefixButtonTextStyle, + backgroundColor: Colors.transparent, + padding: RecipientComposerWidgetStyle.prefixButtonPadding, + margin: RecipientComposerWidgetStyle.recipientMargin, + onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.replyTo), + ), + ]; + } + + Widget _buildExpandButton() { + return TMailButtonWidget.fromIcon( + key: Key('prefix_${widget.prefix.name}_recipient_expand_button'), + icon: _isAllRecipientInputEnabled + ? widget.imagePaths.icChevronUp + : widget.imagePaths.icChevronDownOutline, + backgroundColor: Colors.transparent, + iconSize: 24, + padding: const EdgeInsets.all(5), + iconColor: AppColor.colorLabelComposer, + margin: RecipientComposerWidgetStyle.enableRecipientButtonMargin, + onTapActionCallback: () => + widget.onEnableAllRecipientsInputAction?.call( + _isAllRecipientInputEnabled, + ), + ); + } + KeyEventResult _recipientInputOnKeyListener(FocusNode node, KeyEvent event) { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.tab) { widget.nextFocusNode?.requestFocus(); @@ -403,17 +407,11 @@ class _RecipientComposerWidgetState extends State { return KeyEventResult.ignored; } - bool get _isCollapse => _currentListEmailAddress.length > 1 && widget.expandMode == ExpandMode.COLLAPSE; - bool get _isAllRecipientInputEnabled => widget.fromState == PrefixRecipientState.enabled && widget.ccState == PrefixRecipientState.enabled && widget.bccState == PrefixRecipientState.enabled && widget.replyToState == PrefixRecipientState.enabled; - List get _collapsedListEmailAddress => _isCollapse - ? _currentListEmailAddress.sublist(0, 1) - : _currentListEmailAddress; - FutureOr> _findSuggestions(String query, {int? limit}) async { if (_gapBetweenTagChangedAndFindSuggestion?.isActive ?? false) { return []; diff --git a/lib/features/composer/presentation/widgets/recipient_tag_item_widget.dart b/lib/features/composer/presentation/widgets/recipient_tag_item_widget.dart index aa5cd64cd..4a097a6c8 100644 --- a/lib/features/composer/presentation/widgets/recipient_tag_item_widget.dart +++ b/lib/features/composer/presentation/widgets/recipient_tag_item_widget.dart @@ -21,7 +21,6 @@ import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart class RecipientTagItemWidget extends StatelessWidget { - final bool isCollapsed; final bool isTagFocused; final ImagePaths imagePaths; final double? maxWidth; @@ -29,8 +28,6 @@ class RecipientTagItemWidget extends StatelessWidget { final PrefixEmailAddress prefix; final EmailAddress currentEmailAddress; final List currentListEmailAddress; - final List collapsedListEmailAddress; - final OnShowFullListEmailAddressAction? onShowFullAction; final OnDeleteTagAction? onDeleteTagAction; final OnEditRecipientAction? onEditRecipientAction; final bool isTestingForWeb; @@ -44,13 +41,10 @@ class RecipientTagItemWidget extends StatelessWidget { required this.prefix, required this.currentEmailAddress, required this.currentListEmailAddress, - required this.collapsedListEmailAddress, required this.imagePaths, @visibleForTesting this.isTestingForWeb = false, - this.isCollapsed = false, this.isTagFocused = false, this.isMobile = false, - this.onShowFullAction, this.onDeleteTagAction, this.onEditRecipientAction, this.maxWidth, @@ -95,9 +89,7 @@ class RecipientTagItemWidget extends StatelessWidget { ), onClearFocusAction: onClearFocusAction, child: Container( - key: PlatformInfo.isWeb - ? Key('recipient_tag_item_${prefix.name}_$index') - : null, + key: Key('recipient_tag_item_${prefix.name}_$index'), constraints: const BoxConstraints(maxWidth: 267), decoration: BoxDecoration( borderRadius: const BorderRadius.all( @@ -108,6 +100,9 @@ class RecipientTagItemWidget extends StatelessWidget { ), height: 32, padding: const EdgeInsetsDirectional.only(start: 8, end: 4), + margin: PlatformInfo.isMobile + ? const EdgeInsetsDirectional.only(top: 8) + : null, child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -120,28 +115,20 @@ class RecipientTagItemWidget extends StatelessWidget { ), const SizedBox(width: 4), Flexible( - child: PlatformInfo.isWeb - ? ExtendedText( - key: Key('label_recipient_tag_item_${prefix.name}_$index'), - currentEmailAddress.asString(), - maxLines: 1, - overflowWidget: TextOverflowWidget( - position: TextOverflowPosition.middle, - clearType: TextOverflowClearType.clipRect, - child: Text( - '...', - style: RecipientTagItemWidgetStyle.labelTextStyle, - ), - ), - style: RecipientTagItemWidgetStyle.labelTextStyle, - ) - : Text( - key: Key('label_recipient_tag_item_${prefix.name}_$index'), - currentEmailAddress.asString(), - maxLines: 1, - overflow: TextOverflow.ellipsis, + child: ExtendedText( + key: Key('label_recipient_tag_item_${prefix.name}_$index'), + currentEmailAddress.asString(), + maxLines: 1, + overflowWidget: TextOverflowWidget( + position: TextOverflowPosition.middle, + clearType: TextOverflowClearType.clipRect, + child: Text( + '...', style: RecipientTagItemWidgetStyle.labelTextStyle, ), + ), + style: RecipientTagItemWidgetStyle.labelTextStyle, + ), ), const SizedBox(width: 4), TMailButtonWidget.fromIcon( @@ -186,47 +173,9 @@ class RecipientTagItemWidget extends StatelessWidget { ); } - if (PlatformInfo.isWeb) { - return tagWidget; - } else { - return Container( - key: Key('recipient_tag_item_${prefix.name}_$index'), - constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible(child: tagWidget), - if (isCollapsed) - TMailButtonWidget.fromText( - key: Key('counter_recipient_tag_item_${prefix.name}_$index'), - margin: _counterMargin, - text: '+$countRecipients', - onTapActionCallback: () => onShowFullAction?.call(prefix), - borderRadius: RecipientTagItemWidgetStyle.radius, - textStyle: RecipientTagItemWidgetStyle.labelTextStyle, - padding: PlatformInfo.isWeb || isTestingForWeb - ? RecipientTagItemWidgetStyle.counterPadding - : RecipientTagItemWidgetStyle.mobileCounterPadding, - backgroundColor: AppColor.colorEmailAddressTag, - ), - ], - ), - ); - } + return tagWidget; } - EdgeInsetsGeometry? get _counterMargin { - if (PlatformInfo.isWeb || isTestingForWeb) { - return PlatformInfo.isCanvasKit - ? RecipientTagItemWidgetStyle.webCounterMargin - : RecipientTagItemWidgetStyle.webMobileCounterMargin; - } else { - return RecipientTagItemWidgetStyle.counterMargin; - } - } - - int get countRecipients => currentListEmailAddress.length - collapsedListEmailAddress.length; - Color _getTagBackgroundColor() { if (isTagFocused) { return AppColor.colorItemRecipientSelected; diff --git a/test/features/composer/recipient_composer_widget_test.dart b/test/features/composer/recipient_composer_widget_test.dart index 26b0f5c9d..40fcee624 100644 --- a/test/features/composer/recipient_composer_widget_test.dart +++ b/test/features/composer/recipient_composer_widget_test.dart @@ -8,8 +8,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/email/prefix_email_address.dart'; -import 'package:model/mailbox/expand_mode.dart'; import 'package:super_tag_editor/tag_editor.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_tag_item_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations_delegate.dart'; @@ -86,7 +86,7 @@ void main() { expect(find.text('test2@example.com'), findsOneWidget); }); - testWidgets('RecipientTagItemWidget should have a `maxWidth` equal to the RecipientComposerWidget\'s `maxWidth`', (tester) async { + testWidgets('RecipientTagItemWidget should have a `maxWidth` equal to the default `maxWidth`', (tester) async { final listEmailAddress = [ EmailAddress('test1', 'test1@example.com'), ]; @@ -110,7 +110,7 @@ void main() { final Container recipientTagItemWidget = tester.widget(recipientTagItemWidgetFinder); expect(recipientTagItemWidgetFinder, findsOneWidget); - expect(recipientTagItemWidget.constraints!.maxWidth, 360); + expect(recipientTagItemWidget.constraints!.maxWidth, 267); }); testWidgets('WHEN EmailAddress has address is not empty AND display name is not empty\n' @@ -273,7 +273,7 @@ void main() { }); testWidgets('WHEN To has multiple recipients AND expandMode is COLLAPSE\n' - 'RecipientTagItemWidget should have all the components (AvatarIcon, Label, DeleteIcon, CounterTag)', (tester) async { + 'RecipientTagItemWidget should have all the components (AvatarIcon, Label, DeleteIcon)', (tester) async { final listEmailAddress = [ EmailAddress('test1', 'test1@example.com'), EmailAddress('test2', 'test2@example.com'), @@ -285,7 +285,6 @@ void main() { listEmailAddress: listEmailAddress, imagePaths: imagePaths, maxWidth: 360, - expandMode: ExpandMode.COLLAPSE, keyTagEditor: keyEmailTagEditor, ), ); @@ -312,24 +311,20 @@ void main() { final labelRecipientTagItemWidgetFinder = find.byKey(Key('label_recipient_tag_item_${prefix.name}_0')); final deleteIconRecipientTagItemWidgetFinder = find.byKey(Key('delete_icon_recipient_tag_item_${prefix.name}_0')); final avatarIconRecipientTagItemWidgetFinder = find.byKey(Key('avatar_icon_recipient_tag_item_${prefix.name}_0')); - final counterRecipientTagItemWidgetFinder = find.byKey(Key('counter_recipient_tag_item_${prefix.name}_0')); final Size labelRecipientTagItemWidgetSize = tester.getSize(labelRecipientTagItemWidgetFinder); final Size deleteIconRecipientTagItemWidgetSize = tester.getSize(deleteIconRecipientTagItemWidgetFinder); final Size avatarIconRecipientTagItemWidgetSize = tester.getSize(avatarIconRecipientTagItemWidgetFinder); - final Size counterRecipientTagItemWidgetSize = tester.getSize(counterRecipientTagItemWidgetFinder); - log('recipient_composer_widget_test::main: LabelTagSize = $labelRecipientTagItemWidgetSize | DeleteIconTagSize = $deleteIconRecipientTagItemWidgetSize | AvatarIconTagSize = $avatarIconRecipientTagItemWidgetSize | CounterTagSize = $counterRecipientTagItemWidgetSize'); + log('recipient_composer_widget_test::main: LabelTagSize = $labelRecipientTagItemWidgetSize | DeleteIconTagSize = $deleteIconRecipientTagItemWidgetSize | AvatarIconTagSize = $avatarIconRecipientTagItemWidgetSize'); expect(labelRecipientTagItemWidgetFinder, findsOneWidget); expect(deleteIconRecipientTagItemWidgetFinder, findsOneWidget); expect(avatarIconRecipientTagItemWidgetFinder, findsOneWidget); - expect(counterRecipientTagItemWidgetFinder, findsOneWidget); final totalSizeOfAllComponents = labelRecipientTagItemWidgetSize.width + deleteIconRecipientTagItemWidgetSize.width + avatarIconRecipientTagItemWidgetSize.width; - counterRecipientTagItemWidgetSize.width; expect( totalSizeOfAllComponents, @@ -350,7 +345,6 @@ void main() { listEmailAddress: listEmailAddress, imagePaths: imagePaths, maxWidth: 360, - expandMode: ExpandMode.EXPAND, keyTagEditor: keyEmailTagEditor, ), ); @@ -391,8 +385,6 @@ void main() { final labelRecipientTagItemWidget = tester.widget(labelRecipientTagItemWidgetFinder); final labelTagWidth = tester.getSize(labelRecipientTagItemWidgetFinder).width; - expect(labelRecipientTagItemWidget.overflow, equals(TextOverflow.ellipsis)); - final TextPainter textPainter = TextPainter( maxLines: labelRecipientTagItemWidget.maxLines, textDirection: labelRecipientTagItemWidget.textDirection ?? TextDirection.ltr, @@ -477,10 +469,13 @@ void main() { final widget = makeTestableWidget( child: RecipientComposerWidget( prefix: prefix, + prefixRootState: prefix, listEmailAddress: listEmailAddress, imagePaths: imagePaths, maxWidth: 360, keyTagEditor: keyEmailTagEditor, + isTestingForWeb: true, + toState: PrefixRecipientState.enabled, ), ); @@ -518,7 +513,7 @@ void main() { debugDefaultTargetPlatformOverride = null; }); - testWidgets('ToRecipientComponentWidget should have all the components (PrefixLabel, RecipientTagItemWidget, FromButton, CCButton, BccButton) on web platform', (tester) async { + testWidgets('ToRecipientComponentWidget should have all the components (PrefixLabel, RecipientTagItemWidget, FromButton, CCButton, BccButton, ReplyToButton) on web platform', (tester) async { final listEmailAddress = [ EmailAddress('test1', 'test1@example.com'), ]; @@ -526,11 +521,13 @@ void main() { final widget = makeTestableWidget( child: RecipientComposerWidget( prefix: prefix, + prefixRootState: prefix, listEmailAddress: listEmailAddress, imagePaths: imagePaths, maxWidth: 360, keyTagEditor: keyEmailTagEditor, isTestingForWeb: true, + toState: PrefixRecipientState.enabled, ), );