TF-3189 new reply to field in the mail composer

This commit is contained in:
Florent Azavant
2024-10-30 16:02:00 +01:00
committed by Dat H. Pham
parent 78be3e4d79
commit 74fc8d5d72
20 changed files with 354 additions and 31 deletions
@@ -58,6 +58,7 @@ mixin ScenarioUtilsMixin {
toRecipients: {EmailAddress(null, provisioningEmail.toEmail)}, toRecipients: {EmailAddress(null, provisioningEmail.toEmail)},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId, outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
identity: identity, identity: identity,
@@ -126,11 +126,13 @@ class ComposerController extends BaseController
final toAddressExpandMode = ExpandMode.EXPAND.obs; final toAddressExpandMode = ExpandMode.EXPAND.obs;
final ccAddressExpandMode = ExpandMode.EXPAND.obs; final ccAddressExpandMode = ExpandMode.EXPAND.obs;
final bccAddressExpandMode = ExpandMode.EXPAND.obs; final bccAddressExpandMode = ExpandMode.EXPAND.obs;
final replyToAddressExpandMode = ExpandMode.EXPAND.obs;
final emailContentsViewState = Rxn<Either<Failure, Success>>(); final emailContentsViewState = Rxn<Either<Failure, Success>>();
final hasRequestReadReceipt = false.obs; final hasRequestReadReceipt = false.obs;
final fromRecipientState = PrefixRecipientState.disabled.obs; final fromRecipientState = PrefixRecipientState.disabled.obs;
final ccRecipientState = PrefixRecipientState.disabled.obs; final ccRecipientState = PrefixRecipientState.disabled.obs;
final bccRecipientState = PrefixRecipientState.disabled.obs; final bccRecipientState = PrefixRecipientState.disabled.obs;
final replyToRecipientState = PrefixRecipientState.disabled.obs;
final identitySelected = Rxn<Identity>(); final identitySelected = Rxn<Identity>();
final listFromIdentities = RxList<Identity>(); final listFromIdentities = RxList<Identity>();
final isEmailChanged = Rx<bool>(false); final isEmailChanged = Rx<bool>(false);
@@ -157,17 +159,20 @@ class ComposerController extends BaseController
List<EmailAddress> listToEmailAddress = <EmailAddress>[]; List<EmailAddress> listToEmailAddress = <EmailAddress>[];
List<EmailAddress> listCcEmailAddress = <EmailAddress>[]; List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
List<EmailAddress> listBccEmailAddress = <EmailAddress>[]; List<EmailAddress> listBccEmailAddress = <EmailAddress>[];
List<EmailAddress> listReplyToEmailAddress = <EmailAddress>[];
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact; ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact;
final subjectEmailInputController = TextEditingController(); final subjectEmailInputController = TextEditingController();
final toEmailAddressController = TextEditingController(); final toEmailAddressController = TextEditingController();
final ccEmailAddressController = TextEditingController(); final ccEmailAddressController = TextEditingController();
final bccEmailAddressController = TextEditingController(); final bccEmailAddressController = TextEditingController();
final replyToEmailAddressController = TextEditingController();
final searchIdentitiesInputController = TextEditingController(); final searchIdentitiesInputController = TextEditingController();
final GlobalKey<TagsEditorState> keyToEmailTagEditor = GlobalKey<TagsEditorState>(); final GlobalKey<TagsEditorState> keyToEmailTagEditor = GlobalKey<TagsEditorState>();
final GlobalKey<TagsEditorState> keyCcEmailTagEditor = GlobalKey<TagsEditorState>(); final GlobalKey<TagsEditorState> keyCcEmailTagEditor = GlobalKey<TagsEditorState>();
final GlobalKey<TagsEditorState> keyBccEmailTagEditor = GlobalKey<TagsEditorState>(); final GlobalKey<TagsEditorState> keyBccEmailTagEditor = GlobalKey<TagsEditorState>();
final GlobalKey<TagsEditorState> keyReplyToEmailTagEditor = GlobalKey<TagsEditorState>();
final GlobalKey headerEditorMobileWidgetKey = GlobalKey(); final GlobalKey headerEditorMobileWidgetKey = GlobalKey();
final GlobalKey<DropdownButton2State> identityDropdownKey = GlobalKey<DropdownButton2State>(); final GlobalKey<DropdownButton2State> identityDropdownKey = GlobalKey<DropdownButton2State>();
final double defaultPaddingCoordinateYCursorEditor = 8; final double defaultPaddingCoordinateYCursorEditor = 8;
@@ -176,10 +181,12 @@ class ComposerController extends BaseController
FocusNode? toAddressFocusNode; FocusNode? toAddressFocusNode;
FocusNode? ccAddressFocusNode; FocusNode? ccAddressFocusNode;
FocusNode? bccAddressFocusNode; FocusNode? bccAddressFocusNode;
FocusNode? replyToAddressFocusNode;
FocusNode? searchIdentitiesFocusNode; FocusNode? searchIdentitiesFocusNode;
FocusNode? toAddressFocusNodeKeyboard; FocusNode? toAddressFocusNodeKeyboard;
FocusNode? ccAddressFocusNodeKeyboard; FocusNode? ccAddressFocusNodeKeyboard;
FocusNode? bccAddressFocusNodeKeyboard; FocusNode? bccAddressFocusNodeKeyboard;
FocusNode? replyToAddressFocusNodeKeyboard;
StreamSubscription<html.Event>? _subscriptionOnDragEnter; StreamSubscription<html.Event>? _subscriptionOnDragEnter;
StreamSubscription<html.Event>? _subscriptionOnDragOver; StreamSubscription<html.Event>? _subscriptionOnDragOver;
@@ -305,18 +312,23 @@ class ComposerController extends BaseController
ccAddressFocusNode = null; ccAddressFocusNode = null;
bccAddressFocusNode?.dispose(); bccAddressFocusNode?.dispose();
bccAddressFocusNode = null; bccAddressFocusNode = null;
replyToAddressFocusNode?.dispose();
replyToAddressFocusNode = null;
toAddressFocusNodeKeyboard?.dispose(); toAddressFocusNodeKeyboard?.dispose();
toAddressFocusNodeKeyboard = null; toAddressFocusNodeKeyboard = null;
ccAddressFocusNodeKeyboard?.dispose(); ccAddressFocusNodeKeyboard?.dispose();
ccAddressFocusNodeKeyboard = null; ccAddressFocusNodeKeyboard = null;
bccAddressFocusNodeKeyboard?.dispose(); bccAddressFocusNodeKeyboard?.dispose();
bccAddressFocusNodeKeyboard = null; bccAddressFocusNodeKeyboard = null;
replyToAddressFocusNodeKeyboard?.dispose();
replyToAddressFocusNodeKeyboard = null;
searchIdentitiesFocusNode?.dispose(); searchIdentitiesFocusNode?.dispose();
searchIdentitiesFocusNode = null; searchIdentitiesFocusNode = null;
subjectEmailInputController.dispose(); subjectEmailInputController.dispose();
toEmailAddressController.dispose(); toEmailAddressController.dispose();
ccEmailAddressController.dispose(); ccEmailAddressController.dispose();
bccEmailAddressController.dispose(); bccEmailAddressController.dispose();
replyToEmailAddressController.dispose();
uploadInlineImageWorker.dispose(); uploadInlineImageWorker.dispose();
dashboardViewStateWorker.dispose(); dashboardViewStateWorker.dispose();
scrollController.dispose(); scrollController.dispose();
@@ -480,6 +492,7 @@ class ComposerController extends BaseController
toRecipients: listToEmailAddress.toSet(), toRecipients: listToEmailAddress.toSet(),
ccRecipients: listCcEmailAddress.toSet(), ccRecipients: listCcEmailAddress.toSet(),
bccRecipients: listBccEmailAddress.toSet(), bccRecipients: listBccEmailAddress.toSet(),
replyToRecipients: listReplyToEmailAddress.toSet(),
hasRequestReadReceipt: hasRequestReadReceipt.value, hasRequestReadReceipt: hasRequestReadReceipt.value,
identity: identitySelected.value, identity: identitySelected.value,
attachments: uploadController.attachmentsUploaded, attachments: uploadController.attachmentsUploaded,
@@ -507,16 +520,21 @@ class ComposerController extends BaseController
if (bccEmailAddressController.text.isNotEmpty) { if (bccEmailAddressController.text.isNotEmpty) {
keyBccEmailTagEditor.currentState?.closeSuggestionBox(); keyBccEmailTagEditor.currentState?.closeSuggestionBox();
} }
if (replyToEmailAddressController.text.isNotEmpty) {
keyReplyToEmailTagEditor.currentState?.closeSuggestionBox();
}
} }
void createFocusNodeInput() { void createFocusNodeInput() {
toAddressFocusNode = FocusNode(); toAddressFocusNode = FocusNode();
ccAddressFocusNode = FocusNode(); ccAddressFocusNode = FocusNode();
bccAddressFocusNode = FocusNode(); bccAddressFocusNode = FocusNode();
replyToAddressFocusNode = FocusNode();
searchIdentitiesFocusNode = FocusNode(); searchIdentitiesFocusNode = FocusNode();
toAddressFocusNodeKeyboard = FocusNode(); toAddressFocusNodeKeyboard = FocusNode();
ccAddressFocusNodeKeyboard = FocusNode(); ccAddressFocusNodeKeyboard = FocusNode();
bccAddressFocusNodeKeyboard = FocusNode(); bccAddressFocusNodeKeyboard = FocusNode();
replyToAddressFocusNodeKeyboard = FocusNode();
subjectEmailInputFocusNode = FocusNode( subjectEmailInputFocusNode = FocusNode(
onKeyEvent: PlatformInfo.isWeb ? _subjectEmailInputOnKeyListener : null, onKeyEvent: PlatformInfo.isWeb ? _subjectEmailInputOnKeyListener : null,
@@ -851,7 +869,7 @@ class ComposerController extends BaseController
listCcEmailAddress = List.from(recipients.value2); listCcEmailAddress = List.from(recipients.value2);
listBccEmailAddress = List.from(recipients.value3); listBccEmailAddress = List.from(recipients.value3);
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) { if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty || listReplyToEmailAddress.isNotEmpty) {
isInitialRecipient.value = true; isInitialRecipient.value = true;
toAddressExpandMode.value = ExpandMode.COLLAPSE; toAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
@@ -866,6 +884,11 @@ class ComposerController extends BaseController
bccAddressExpandMode.value = ExpandMode.COLLAPSE; bccAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
if (listReplyToEmailAddress.isNotEmpty) {
replyToRecipientState.value = PrefixRecipientState.enabled;
replyToAddressExpandMode.value = ExpandMode.COLLAPSE;
}
_updateStatusEmailSendButton(); _updateStatusEmailSendButton();
} }
@@ -883,6 +906,9 @@ class ComposerController extends BaseController
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
listBccEmailAddress = List.from(newListEmailAddress); listBccEmailAddress = List.from(newListEmailAddress);
break; break;
case PrefixEmailAddress.replyTo:
listReplyToEmailAddress = List.from(newListEmailAddress);
break;
default: default:
break; break;
} }
@@ -891,8 +917,9 @@ class ComposerController extends BaseController
void _updateStatusEmailSendButton() { void _updateStatusEmailSendButton() {
if (listToEmailAddress.isNotEmpty if (listToEmailAddress.isNotEmpty
|| listCcEmailAddress.isNotEmpty
|| listBccEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty
|| listCcEmailAddress.isNotEmpty) { || listReplyToEmailAddress.isNotEmpty) {
isEnableEmailSendButton.value = true; isEnableEmailSendButton.value = true;
} else { } else {
isEnableEmailSendButton.value = false; isEnableEmailSendButton.value = false;
@@ -910,7 +937,8 @@ class ComposerController extends BaseController
if (toEmailAddressController.text.isNotEmpty if (toEmailAddressController.text.isNotEmpty
|| ccEmailAddressController.text.isNotEmpty || ccEmailAddressController.text.isNotEmpty
|| bccEmailAddressController.text.isNotEmpty) { || bccEmailAddressController.text.isNotEmpty
|| replyToEmailAddressController.text.isNotEmpty) {
_collapseAllRecipient(); _collapseAllRecipient();
_autoCreateEmailTag(); _autoCreateEmailTag();
} }
@@ -927,7 +955,7 @@ class ComposerController extends BaseController
return; return;
} }
final allListEmailAddress = listToEmailAddress + listCcEmailAddress + listBccEmailAddress; final allListEmailAddress = listToEmailAddress + listCcEmailAddress + listBccEmailAddress + listReplyToEmailAddress;
final listEmailAddressInvalid = allListEmailAddress final listEmailAddressInvalid = allListEmailAddress
.where((emailAddress) => !EmailUtils.isEmailAddressValid(emailAddress.emailAddress)) .where((emailAddress) => !EmailUtils.isEmailAddressValid(emailAddress.emailAddress))
.toList(); .toList();
@@ -939,6 +967,7 @@ class ComposerController extends BaseController
toAddressExpandMode.value = ExpandMode.EXPAND; toAddressExpandMode.value = ExpandMode.EXPAND;
ccAddressExpandMode.value = ExpandMode.EXPAND; ccAddressExpandMode.value = ExpandMode.EXPAND;
bccAddressExpandMode.value = ExpandMode.EXPAND; bccAddressExpandMode.value = ExpandMode.EXPAND;
replyToAddressExpandMode.value = ExpandMode.EXPAND;
}, },
showAsBottomSheet: true, showAsBottomSheet: true,
title: AppLocalizations.of(context).sending_failed, title: AppLocalizations.of(context).sending_failed,
@@ -1058,6 +1087,7 @@ class ComposerController extends BaseController
toRecipients: listToEmailAddress.toSet(), toRecipients: listToEmailAddress.toSet(),
ccRecipients: listCcEmailAddress.toSet(), ccRecipients: listCcEmailAddress.toSet(),
bccRecipients: listBccEmailAddress.toSet(), bccRecipients: listBccEmailAddress.toSet(),
replyToRecipients: listReplyToEmailAddress.toSet(),
hasRequestReadReceipt: hasRequestReadReceipt.value, hasRequestReadReceipt: hasRequestReadReceipt.value,
identity: identitySelected.value, identity: identitySelected.value,
attachments: uploadController.attachmentsUploaded, attachments: uploadController.attachmentsUploaded,
@@ -1276,6 +1306,7 @@ class ComposerController extends BaseController
toRecipients: listToEmailAddress.toSet(), toRecipients: listToEmailAddress.toSet(),
ccRecipients: listCcEmailAddress.toSet(), ccRecipients: listCcEmailAddress.toSet(),
bccRecipients: listBccEmailAddress.toSet(), bccRecipients: listBccEmailAddress.toSet(),
replyToRecipients: listReplyToEmailAddress.toSet(),
identity: identitySelected.value, identity: identitySelected.value,
attachments: uploadController.attachmentsUploaded, attachments: uploadController.attachmentsUploaded,
hasReadReceipt: hasRequestReadReceipt.value, hasReadReceipt: hasRequestReadReceipt.value,
@@ -1560,6 +1591,9 @@ class ComposerController extends BaseController
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
bccRecipientState.value = PrefixRecipientState.enabled; bccRecipientState.value = PrefixRecipientState.enabled;
break; break;
case PrefixEmailAddress.replyTo:
replyToRecipientState.value = PrefixRecipientState.enabled;
break;
default: default:
break; break;
} }
@@ -1578,6 +1612,11 @@ class ComposerController extends BaseController
bccAddressFocusNode = FocusNode(); bccAddressFocusNode = FocusNode();
bccEmailAddressController.clear(); bccEmailAddressController.clear();
break; break;
case PrefixEmailAddress.replyTo:
replyToRecipientState.value = PrefixRecipientState.disabled;
replyToAddressFocusNode = FocusNode();
replyToEmailAddressController.clear();
break;
default: default:
break; break;
} }
@@ -1587,12 +1626,14 @@ class ComposerController extends BaseController
toAddressExpandMode.value = ExpandMode.COLLAPSE; toAddressExpandMode.value = ExpandMode.COLLAPSE;
ccAddressExpandMode.value = ExpandMode.COLLAPSE; ccAddressExpandMode.value = ExpandMode.COLLAPSE;
bccAddressExpandMode.value = ExpandMode.COLLAPSE; bccAddressExpandMode.value = ExpandMode.COLLAPSE;
replyToAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
void _autoCreateEmailTag() { void _autoCreateEmailTag() {
final inputToEmail = toEmailAddressController.text; final inputToEmail = toEmailAddressController.text;
final inputCcEmail = ccEmailAddressController.text; final inputCcEmail = ccEmailAddressController.text;
final inputBccEmail = bccEmailAddressController.text; final inputBccEmail = bccEmailAddressController.text;
final inputReplyToEmail = replyToEmailAddressController.text;
log('ComposerController::_autoCreateEmailTag:inputToEmail = $inputToEmail | inputCcEmail = $inputCcEmail | inputBccEmail = $inputBccEmail'); log('ComposerController::_autoCreateEmailTag:inputToEmail = $inputToEmail | inputCcEmail = $inputCcEmail | inputBccEmail = $inputBccEmail');
if (inputToEmail.trim().isNotEmpty) { if (inputToEmail.trim().isNotEmpty) {
_autoCreateEmailTagForRecipientField( _autoCreateEmailTagForRecipientField(
@@ -1618,6 +1659,9 @@ class ComposerController extends BaseController
keyEmailTagEditor: keyBccEmailTagEditor, keyEmailTagEditor: keyBccEmailTagEditor,
); );
} }
if (inputReplyToEmail.isNotEmpty) {
_autoCreateReplyToEmailTag(inputReplyToEmail);
}
} }
bool _isDuplicatedRecipient(String inputEmail, List<EmailAddress> listEmailAddress) { bool _isDuplicatedRecipient(String inputEmail, List<EmailAddress> listEmailAddress) {
@@ -1676,6 +1720,20 @@ class ComposerController extends BaseController
} }
} }
void _autoCreateReplyToEmailTag(String inputEmail) {
if (!_isDuplicatedRecipient(inputEmail, listReplyToEmailAddress)) {
final emailAddress = EmailAddress(null, inputEmail);
listReplyToEmailAddress.add(emailAddress);
isInitialRecipient.value = true;
isInitialRecipient.refresh();
_updateStatusEmailSendButton();
}
keyReplyToEmailTagEditor.currentState?.resetTextField();
Future.delayed(const Duration(milliseconds: 300), () {
keyReplyToEmailTagEditor.currentState?.closeSuggestionBox();
});
}
void _closeSuggestionBox() { void _closeSuggestionBox() {
if (toEmailAddressController.text.isEmpty) { if (toEmailAddressController.text.isEmpty) {
keyToEmailTagEditor.currentState?.closeSuggestionBox(); keyToEmailTagEditor.currentState?.closeSuggestionBox();
@@ -1686,6 +1744,9 @@ class ComposerController extends BaseController
if (bccEmailAddressController.text.isEmpty) { if (bccEmailAddressController.text.isEmpty) {
keyBccEmailTagEditor.currentState?.closeSuggestionBox(); keyBccEmailTagEditor.currentState?.closeSuggestionBox();
} }
if (replyToEmailAddressController.text.isEmpty) {
keyReplyToEmailTagEditor.currentState?.closeSuggestionBox();
}
} }
void showFullEmailAddress(PrefixEmailAddress prefixEmailAddress) { void showFullEmailAddress(PrefixEmailAddress prefixEmailAddress) {
@@ -1702,6 +1763,10 @@ class ComposerController extends BaseController
bccAddressExpandMode.value = ExpandMode.EXPAND; bccAddressExpandMode.value = ExpandMode.EXPAND;
bccAddressFocusNode?.requestFocus(); bccAddressFocusNode?.requestFocus();
break; break;
case PrefixEmailAddress.replyTo:
replyToAddressExpandMode.value = ExpandMode.EXPAND;
replyToAddressFocusNode?.requestFocus();
break;
default: default:
break; break;
} }
@@ -1719,6 +1784,9 @@ class ComposerController extends BaseController
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
bccAddressExpandMode.value = ExpandMode.EXPAND; bccAddressExpandMode.value = ExpandMode.EXPAND;
break; break;
case PrefixEmailAddress.replyTo:
replyToAddressExpandMode.value = ExpandMode.EXPAND;
break;
default: default:
break; break;
} }
@@ -1766,6 +1834,13 @@ class ComposerController extends BaseController
); );
} }
break; break;
case PrefixEmailAddress.replyTo:
replyToAddressExpandMode.value = ExpandMode.COLLAPSE;
final inputReplyToEmail = replyToEmailAddressController.text;
if (inputReplyToEmail.isNotEmpty) {
_autoCreateReplyToEmailTag(inputReplyToEmail);
}
break;
default: default:
break; break;
} }
@@ -2003,12 +2078,14 @@ class ComposerController extends BaseController
return toAddressFocusNode?.hasFocus == true || return toAddressFocusNode?.hasFocus == true ||
ccAddressFocusNode?.hasFocus == true || ccAddressFocusNode?.hasFocus == true ||
bccAddressFocusNode?.hasFocus == true || bccAddressFocusNode?.hasFocus == true ||
replyToAddressFocusNode?.hasFocus == true ||
subjectEmailInputFocusNode?.hasFocus == true; subjectEmailInputFocusNode?.hasFocus == true;
} else if (PlatformInfo.isMobile) { } else if (PlatformInfo.isMobile) {
final isEditorFocused = (await richTextMobileTabletController?.isEditorFocused) ?? false; final isEditorFocused = (await richTextMobileTabletController?.isEditorFocused) ?? false;
return toAddressFocusNode?.hasFocus == true || return toAddressFocusNode?.hasFocus == true ||
ccAddressFocusNode?.hasFocus == true || ccAddressFocusNode?.hasFocus == true ||
bccAddressFocusNode?.hasFocus == true || bccAddressFocusNode?.hasFocus == true ||
replyToAddressFocusNode?.hasFocus == true ||
subjectEmailInputFocusNode?.hasFocus == true || subjectEmailInputFocusNode?.hasFocus == true ||
isEditorFocused; isEditorFocused;
} }
@@ -2052,6 +2129,8 @@ class ComposerController extends BaseController
return ccAddressFocusNode; return ccAddressFocusNode;
} else if (bccRecipientState.value == PrefixRecipientState.enabled) { } else if (bccRecipientState.value == PrefixRecipientState.enabled) {
return bccAddressFocusNode; return bccAddressFocusNode;
} else if (replyToRecipientState.value == PrefixRecipientState.enabled) {
return replyToAddressFocusNode;
} else { } else {
return subjectEmailInputFocusNode; return subjectEmailInputFocusNode;
} }
@@ -2060,6 +2139,16 @@ class ComposerController extends BaseController
FocusNode? getNextFocusOfCcEmailAddress() { FocusNode? getNextFocusOfCcEmailAddress() {
if (bccRecipientState.value == PrefixRecipientState.enabled) { if (bccRecipientState.value == PrefixRecipientState.enabled) {
return bccAddressFocusNode; return bccAddressFocusNode;
} else if (replyToRecipientState.value == PrefixRecipientState.enabled) {
return replyToAddressFocusNode;
} else {
return subjectEmailInputFocusNode;
}
}
FocusNode? getNextFocusOfBccEmailAddress() {
if (replyToRecipientState.value == PrefixRecipientState.enabled) {
return replyToAddressFocusNode;
} else { } else {
return subjectEmailInputFocusNode; return subjectEmailInputFocusNode;
} }
@@ -2115,6 +2204,10 @@ class ComposerController extends BaseController
listBccEmailAddress.remove(draggableEmailAddress.emailAddress); listBccEmailAddress.remove(draggableEmailAddress.emailAddress);
bccAddressExpandMode.value = ExpandMode.EXPAND; bccAddressExpandMode.value = ExpandMode.EXPAND;
break; break;
case PrefixEmailAddress.replyTo:
listReplyToEmailAddress.remove(draggableEmailAddress.emailAddress);
replyToAddressExpandMode.value = ExpandMode.EXPAND;
break;
default: default:
break; break;
} }
@@ -2380,6 +2473,7 @@ class ComposerController extends BaseController
toRecipients: listToEmailAddress.toSet(), toRecipients: listToEmailAddress.toSet(),
ccRecipients: listCcEmailAddress.toSet(), ccRecipients: listCcEmailAddress.toSet(),
bccRecipients: listBccEmailAddress.toSet(), bccRecipients: listBccEmailAddress.toSet(),
replyToRecipients: listReplyToEmailAddress.toSet(),
hasRequestReadReceipt: hasRequestReadReceipt.value, hasRequestReadReceipt: hasRequestReadReceipt.value,
identity: identitySelected.value, identity: identitySelected.value,
attachments: uploadController.attachmentsUploaded, attachments: uploadController.attachmentsUploaded,
@@ -2461,6 +2555,7 @@ class ComposerController extends BaseController
fromRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled; fromRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
ccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled; ccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
bccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled; bccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
replyToRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
} }
void _handleGetEmailContentFailure(GetEmailContentFailure failure) { void _handleGetEmailContentFailure(GetEmailContentFailure failure) {
@@ -132,6 +132,7 @@ class ComposerView extends GetWidget<ComposerController> {
fromState: controller.fromRecipientState.value, fromState: controller.fromRecipientState.value,
ccState: controller.ccRecipientState.value, ccState: controller.ccRecipientState.value,
bccState: controller.bccRecipientState.value, bccState: controller.bccRecipientState.value,
replyToState: controller.replyToRecipientState.value,
expandMode: controller.toAddressExpandMode.value, expandMode: controller.toAddressExpandMode.value,
controller: controller.toEmailAddressController, controller: controller.toEmailAddressController,
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
@@ -192,9 +193,9 @@ class ComposerView extends GetWidget<ComposerController> {
focusNode: controller.bccAddressFocusNode, focusNode: controller.bccAddressFocusNode,
keyTagEditor: controller.keyBccEmailTagEditor, keyTagEditor: controller.keyBccEmailTagEditor,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.subjectEmailInputFocusNode,
padding: ComposerStyle.mobileRecipientPadding, padding: ComposerStyle.mobileRecipientPadding,
margin: ComposerStyle.mobileRecipientMargin, margin: ComposerStyle.mobileRecipientMargin,
nextFocusNode: controller.getNextFocusOfBccEmailAddress(),
onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange, onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange,
onShowFullListEmailAddressAction: controller.showFullEmailAddress, onShowFullListEmailAddressAction: controller.showFullEmailAddress,
onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType, onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType,
@@ -206,6 +207,33 @@ class ComposerView extends GetWidget<ComposerController> {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}), }),
Obx(() {
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled) {
return 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,
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,
);
} else {
return const SizedBox.shrink();
}
}),
SubjectComposerWidget( SubjectComposerWidget(
focusNode: controller.subjectEmailInputFocusNode, focusNode: controller.subjectEmailInputFocusNode,
textController: controller.subjectEmailInputController, textController: controller.subjectEmailInputController,
@@ -297,6 +325,7 @@ class ComposerView extends GetWidget<ComposerController> {
fromState: controller.fromRecipientState.value, fromState: controller.fromRecipientState.value,
ccState: controller.ccRecipientState.value, ccState: controller.ccRecipientState.value,
bccState: controller.bccRecipientState.value, bccState: controller.bccRecipientState.value,
replyToState: controller.replyToRecipientState.value,
expandMode: controller.toAddressExpandMode.value, expandMode: controller.toAddressExpandMode.value,
controller: controller.toEmailAddressController, controller: controller.toEmailAddressController,
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
@@ -351,6 +380,27 @@ class ComposerView extends GetWidget<ComposerController> {
focusNode: controller.bccAddressFocusNode, focusNode: controller.bccAddressFocusNode,
keyTagEditor: controller.keyBccEmailTagEditor, keyTagEditor: controller.keyBccEmailTagEditor,
isInitial: controller.isInitialRecipient.value, 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,
),
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, nextFocusNode: controller.subjectEmailInputFocusNode,
padding: ComposerStyle.mobileRecipientPadding, padding: ComposerStyle.mobileRecipientPadding,
margin: ComposerStyle.mobileRecipientMargin, margin: ComposerStyle.mobileRecipientMargin,
@@ -94,6 +94,7 @@ class ComposerView extends GetWidget<ComposerController> {
fromState: controller.fromRecipientState.value, fromState: controller.fromRecipientState.value,
ccState: controller.ccRecipientState.value, ccState: controller.ccRecipientState.value,
bccState: controller.bccRecipientState.value, bccState: controller.bccRecipientState.value,
replyToState: controller.replyToRecipientState.value,
expandMode: controller.toAddressExpandMode.value, expandMode: controller.toAddressExpandMode.value,
controller: controller.toEmailAddressController, controller: controller.toEmailAddressController,
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
@@ -152,6 +153,29 @@ class ComposerView extends GetWidget<ComposerController> {
focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard,
keyTagEditor: controller.keyBccEmailTagEditor, keyTagEditor: controller.keyBccEmailTagEditor,
isInitial: controller.isInitialRecipient.value, 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,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
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,
focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard,
keyTagEditor: controller.keyReplyToEmailTagEditor,
isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.subjectEmailInputFocusNode, nextFocusNode: controller.subjectEmailInputFocusNode,
padding: ComposerStyle.mobileRecipientPadding, padding: ComposerStyle.mobileRecipientPadding,
margin: ComposerStyle.mobileRecipientMargin, margin: ComposerStyle.mobileRecipientMargin,
@@ -343,6 +367,7 @@ class ComposerView extends GetWidget<ComposerController> {
fromState: controller.fromRecipientState.value, fromState: controller.fromRecipientState.value,
ccState: controller.ccRecipientState.value, ccState: controller.ccRecipientState.value,
bccState: controller.bccRecipientState.value, bccState: controller.bccRecipientState.value,
replyToState: controller.replyToRecipientState.value,
expandMode: controller.toAddressExpandMode.value, expandMode: controller.toAddressExpandMode.value,
controller: controller.toEmailAddressController, controller: controller.toEmailAddressController,
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
@@ -401,6 +426,29 @@ class ComposerView extends GetWidget<ComposerController> {
focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard,
keyTagEditor: controller.keyBccEmailTagEditor, keyTagEditor: controller.keyBccEmailTagEditor,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.getNextFocusOfBccEmailAddress(),
padding: ComposerStyle.desktopRecipientPadding,
margin: ComposerStyle.desktopRecipientMargin,
onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange,
onShowFullListEmailAddressAction: controller.showFullEmailAddress,
onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType,
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
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,
focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard,
keyTagEditor: controller.keyReplyToEmailTagEditor,
isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.subjectEmailInputFocusNode, nextFocusNode: controller.subjectEmailInputFocusNode,
padding: ComposerStyle.desktopRecipientPadding, padding: ComposerStyle.desktopRecipientPadding,
margin: ComposerStyle.desktopRecipientMargin, margin: ComposerStyle.desktopRecipientMargin,
@@ -629,6 +677,7 @@ class ComposerView extends GetWidget<ComposerController> {
fromState: controller.fromRecipientState.value, fromState: controller.fromRecipientState.value,
ccState: controller.ccRecipientState.value, ccState: controller.ccRecipientState.value,
bccState: controller.bccRecipientState.value, bccState: controller.bccRecipientState.value,
replyToState: controller.replyToRecipientState.value,
expandMode: controller.toAddressExpandMode.value, expandMode: controller.toAddressExpandMode.value,
controller: controller.toEmailAddressController, controller: controller.toEmailAddressController,
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
@@ -687,6 +736,29 @@ class ComposerView extends GetWidget<ComposerController> {
focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard, focusNodeKeyboard: controller.bccAddressFocusNodeKeyboard,
keyTagEditor: controller.keyBccEmailTagEditor, keyTagEditor: controller.keyBccEmailTagEditor,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.getNextFocusOfBccEmailAddress(),
padding: ComposerStyle.tabletRecipientPadding,
margin: ComposerStyle.tabletRecipientMargin,
onFocusEmailAddressChangeAction: controller.onEmailAddressFocusChange,
onShowFullListEmailAddressAction: controller.showFullEmailAddress,
onDeleteEmailAddressTypeAction: controller.deleteEmailAddressType,
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
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,
focusNodeKeyboard: controller.replyToAddressFocusNodeKeyboard,
keyTagEditor: controller.keyReplyToEmailTagEditor,
isInitial: controller.isInitialRecipient.value,
nextFocusNode: controller.subjectEmailInputFocusNode, nextFocusNode: controller.subjectEmailInputFocusNode,
padding: ComposerStyle.tabletRecipientPadding, padding: ComposerStyle.tabletRecipientPadding,
margin: ComposerStyle.tabletRecipientMargin, margin: ComposerStyle.tabletRecipientMargin,
@@ -39,7 +39,9 @@ extension CreateEmailRequestExtension on CreateEmailRequest {
} }
Set<EmailAddress> createReplyToRecipients() { Set<EmailAddress> createReplyToRecipients() {
if (identity?.replyTo?.isNotEmpty == true) { if (replyToRecipients.isNotEmpty) {
return replyToRecipients.toSet();
} else if (identity?.replyTo?.isNotEmpty == true) {
return identity!.replyTo!.toSet(); return identity!.replyTo!.toSet();
} else { } else {
return { EmailAddress(null, session.getOwnEmailAddress()) }; return { EmailAddress(null, session.getOwnEmailAddress()) };
@@ -75,10 +75,11 @@ extension EmailActionTypeExtension on EmailActionType {
final subject = presentationEmail.subject?.escapeLtGtHtmlString() ?? ''; final subject = presentationEmail.subject?.escapeLtGtHtmlString() ?? '';
final receivedAt = presentationEmail.receivedAt; final receivedAt = presentationEmail.receivedAt;
final fromEmailAddress = presentationEmail.from.toEscapeHtmlStringUseCommaSeparator(); final fromEmailAddress = presentationEmail.from.listEmailAddressToString(isFullEmailAddress: true);
final toEmailAddress = presentationEmail.to.toEscapeHtmlStringUseCommaSeparator(); final toEmailAddress = presentationEmail.to.listEmailAddressToString(isFullEmailAddress: true);
final ccEmailAddress = presentationEmail.cc.toEscapeHtmlStringUseCommaSeparator(); final ccEmailAddress = presentationEmail.cc.listEmailAddressToString(isFullEmailAddress: true);
final bccEmailAddress = presentationEmail.bcc.toEscapeHtmlStringUseCommaSeparator(); final bccEmailAddress = presentationEmail.bcc.listEmailAddressToString(isFullEmailAddress: true);
final replyToEmailAddress = presentationEmail.replyTo.listEmailAddressToString(isFullEmailAddress: true);
if (subject.isNotEmpty) { if (subject.isNotEmpty) {
headerQuoted = headerQuoted headerQuoted = headerQuoted
@@ -116,6 +117,12 @@ extension EmailActionTypeExtension on EmailActionType {
.append(bccEmailAddress) .append(bccEmailAddress)
.addNewLineTag(); .addNewLineTag();
} }
if (replyToEmailAddress.isNotEmpty) {
headerQuoted = headerQuoted
.append('${appLocalizations.reply_to_email_address_prefix}: ')
.append(replyToEmailAddress)
.addNewLineTag();
}
return headerQuoted; return headerQuoted;
default: default:
@@ -14,6 +14,8 @@ extension PrefixEmailAddressExtension on PrefixEmailAddress {
return AppLocalizations.of(context).cc_email_address_prefix; return AppLocalizations.of(context).cc_email_address_prefix;
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
return AppLocalizations.of(context).bcc_email_address_prefix; return AppLocalizations.of(context).bcc_email_address_prefix;
case PrefixEmailAddress.replyTo:
return AppLocalizations.of(context).reply_to_email_address_prefix;
case PrefixEmailAddress.from: case PrefixEmailAddress.from:
return AppLocalizations.of(context).from_email_address_prefix; return AppLocalizations.of(context).from_email_address_prefix;
} }
@@ -27,6 +29,8 @@ extension PrefixEmailAddressExtension on PrefixEmailAddress {
return email.cc?.toList() ?? List.empty(); return email.cc?.toList() ?? List.empty();
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
return email.bcc?.toList() ?? List.empty(); return email.bcc?.toList() ?? List.empty();
case PrefixEmailAddress.replyTo:
return email.replyTo?.toList() ?? List.empty();
case PrefixEmailAddress.from: case PrefixEmailAddress.from:
return email.from?.toList() ?? List.empty(); return email.from?.toList() ?? List.empty();
} }
@@ -23,6 +23,7 @@ class CreateEmailRequest with EquatableMixin {
final Set<EmailAddress> toRecipients; final Set<EmailAddress> toRecipients;
final Set<EmailAddress> ccRecipients; final Set<EmailAddress> ccRecipients;
final Set<EmailAddress> bccRecipients; final Set<EmailAddress> bccRecipients;
final Set<EmailAddress> replyToRecipients;
final Identity? identity; final Identity? identity;
final List<Attachment>? attachments; final List<Attachment>? attachments;
final Map<String, Attachment>? inlineAttachments; final Map<String, Attachment>? inlineAttachments;
@@ -47,6 +48,7 @@ class CreateEmailRequest with EquatableMixin {
required this.toRecipients, required this.toRecipients,
required this.ccRecipients, required this.ccRecipients,
required this.bccRecipients, required this.bccRecipients,
required this.replyToRecipients,
this.hasRequestReadReceipt = true, this.hasRequestReadReceipt = true,
this.identity, this.identity,
this.attachments, this.attachments,
@@ -74,6 +76,7 @@ class CreateEmailRequest with EquatableMixin {
toRecipients, toRecipients,
ccRecipients, ccRecipients,
bccRecipients, bccRecipients,
replyToRecipients,
identity, identity,
hasRequestReadReceipt, hasRequestReadReceipt,
attachments, attachments,
@@ -9,6 +9,7 @@ class SavedEmailDraft with EquatableMixin {
final Set<EmailAddress> toRecipients; final Set<EmailAddress> toRecipients;
final Set<EmailAddress> ccRecipients; final Set<EmailAddress> ccRecipients;
final Set<EmailAddress> bccRecipients; final Set<EmailAddress> bccRecipients;
final Set<EmailAddress> replyToRecipients;
final List<Attachment> attachments; final List<Attachment> attachments;
final Identity? identity; final Identity? identity;
final bool hasReadReceipt; final bool hasReadReceipt;
@@ -19,6 +20,7 @@ class SavedEmailDraft with EquatableMixin {
required this.toRecipients, required this.toRecipients,
required this.ccRecipients, required this.ccRecipients,
required this.bccRecipients, required this.bccRecipients,
required this.replyToRecipients,
required this.attachments, required this.attachments,
required this.identity, required this.identity,
required this.hasReadReceipt, required this.hasReadReceipt,
@@ -31,6 +33,7 @@ class SavedEmailDraft with EquatableMixin {
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
attachments: [], attachments: [],
identity: null, identity: null,
hasReadReceipt: false, hasReadReceipt: false,
@@ -45,6 +48,7 @@ class SavedEmailDraft with EquatableMixin {
{0: toRecipients}, {0: toRecipients},
{1: ccRecipients}, {1: ccRecipients},
{2: bccRecipients}, {2: bccRecipients},
{3: replyToRecipients},
attachments, attachments,
identity, identity,
hasReadReceipt hasReadReceipt
@@ -156,10 +156,6 @@ class ComposerStyle {
} }
static double getMaxHeightEmailAddressWidget(BuildContext context, BoxConstraints constraints, ResponsiveUtils responsiveUtils) { static double getMaxHeightEmailAddressWidget(BuildContext context, BoxConstraints constraints, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isDesktop(context)) { return constraints.maxHeight > 0 ? constraints.maxHeight * 0.4 : 150.0;
return constraints.maxHeight > 0 ? constraints.maxHeight * 0.3 : 150.0;
} else {
return constraints.maxHeight > 0 ? constraints.maxHeight * 0.4 : 150.0;
}
} }
} }
@@ -47,6 +47,7 @@ class RecipientComposerWidget extends StatefulWidget {
final PrefixRecipientState fromState; final PrefixRecipientState fromState;
final PrefixRecipientState ccState; final PrefixRecipientState ccState;
final PrefixRecipientState bccState; final PrefixRecipientState bccState;
final PrefixRecipientState replyToState;
final bool? isInitial; final bool? isInitial;
final FocusNode? focusNode; final FocusNode? focusNode;
final FocusNode? focusNodeKeyboard; final FocusNode? focusNodeKeyboard;
@@ -77,6 +78,7 @@ class RecipientComposerWidget extends StatefulWidget {
@visibleForTesting this.isTestingForWeb = false, @visibleForTesting this.isTestingForWeb = false,
this.ccState = PrefixRecipientState.disabled, this.ccState = PrefixRecipientState.disabled,
this.bccState = PrefixRecipientState.disabled, this.bccState = PrefixRecipientState.disabled,
this.replyToState = PrefixRecipientState.disabled,
this.fromState = PrefixRecipientState.disabled, this.fromState = PrefixRecipientState.disabled,
this.isInitial, this.isInitial,
this.controller, this.controller,
@@ -368,6 +370,16 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
margin: RecipientComposerWidgetStyle.recipientMargin, margin: RecipientComposerWidgetStyle.recipientMargin,
onTapActionCallback: () => widget.onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc), 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 if (PlatformInfo.isMobile) else if (PlatformInfo.isMobile)
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
@@ -410,7 +422,8 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
bool get _isAllRecipientInputEnabled => widget.fromState == PrefixRecipientState.enabled bool get _isAllRecipientInputEnabled => widget.fromState == PrefixRecipientState.enabled
&& widget.ccState == PrefixRecipientState.enabled && widget.ccState == PrefixRecipientState.enabled
&& widget.bccState == PrefixRecipientState.enabled; && widget.bccState == PrefixRecipientState.enabled
&& widget.replyToState == PrefixRecipientState.enabled;
List<EmailAddress> get _collapsedListEmailAddress => _isCollapse List<EmailAddress> get _collapsedListEmailAddress => _isCollapse
? _currentListEmailAddress.sublist(0, 1) ? _currentListEmailAddress.sublist(0, 1)
+6
View File
@@ -206,6 +206,12 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"reply_to_email_address_prefix": "Reply to",
"@reply_to_email_address_prefix": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"cc_email_address_prefix": "Cc", "cc_email_address_prefix": "Cc",
"@cc_email_address_prefix": { "@cc_email_address_prefix": {
"type": "text", "type": "text",
@@ -204,6 +204,13 @@ class AppLocalizations {
); );
} }
String get reply_to_email_address_prefix {
return Intl.message(
'Reply to',
name: 'reply_to_email_address_prefix',
);
}
String get cc_email_address_prefix { String get cc_email_address_prefix {
return Intl.message( return Intl.message(
'Cc', 'Cc',
+2 -1
View File
@@ -3,5 +3,6 @@ enum PrefixEmailAddress {
from, from,
to, to,
cc, cc,
bcc bcc,
replyTo
} }
@@ -47,6 +47,7 @@ void main() {
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
draftsEmailId: EmailId(Id('some-id')) draftsEmailId: EmailId(Id('some-id'))
); );
when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader'))) when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader')))
@@ -85,6 +86,7 @@ void main() {
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
); );
when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader'))) when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader')))
.thenAnswer((_) async => Email()); .thenAnswer((_) async => Email());
@@ -38,6 +38,7 @@ void main() {
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
); );
when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader'))) when(composerRepository.generateEmail(any, withIdentityHeader: anyNamed('withIdentityHeader')))
.thenAnswer((_) async => Email()); .thenAnswer((_) async => Email());
@@ -306,6 +306,7 @@ void main() {
final toRecipient = EmailAddress('to', 'to@linagora.com'); final toRecipient = EmailAddress('to', 'to@linagora.com');
final ccRecipient = EmailAddress('cc', 'cc@linagora.com'); final ccRecipient = EmailAddress('cc', 'cc@linagora.com');
final bccRecipient = EmailAddress('bcc', 'bcc@linagora.com'); final bccRecipient = EmailAddress('bcc', 'bcc@linagora.com');
final replyToRecipient = EmailAddress('replyTo', 'replyTo@linagora.com');
final identity = Identity(); final identity = Identity();
final attachment = Attachment(); final attachment = Attachment();
const alwaysReadReceiptEnabled = true; const alwaysReadReceiptEnabled = true;
@@ -331,6 +332,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.identitySelected.value = identity; composerController?.identitySelected.value = identity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final state = GetAlwaysReadReceiptSettingSuccess( final state = GetAlwaysReadReceiptSettingSuccess(
@@ -342,6 +344,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: alwaysReadReceiptEnabled hasReadReceipt: alwaysReadReceiptEnabled
@@ -370,6 +373,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.identitySelected.value = identity; composerController?.identitySelected.value = identity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final state = GetAlwaysReadReceiptSettingFailure(Exception()); final state = GetAlwaysReadReceiptSettingFailure(Exception());
@@ -380,6 +384,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -407,6 +412,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
final selectedIdentity = Identity(id: IdentityId(Id('alice'))); final selectedIdentity = Identity(id: IdentityId(Id('alice')));
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -421,6 +427,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -451,6 +458,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
when(mockMailboxDashBoardController.composerArguments).thenReturn( when(mockMailboxDashBoardController.composerArguments).thenReturn(
ComposerArguments(identities: [identity])); ComposerArguments(identities: [identity]));
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -461,6 +469,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -491,6 +500,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final selectedIdentity = Identity( final selectedIdentity = Identity(
@@ -508,6 +518,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -538,6 +549,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final identity = Identity( final identity = Identity(
@@ -555,6 +567,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -594,6 +607,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final selectedIdentity = Identity(id: IdentityId(Id('alice'))); final selectedIdentity = Identity(id: IdentityId(Id('alice')));
@@ -612,6 +626,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -665,6 +680,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
final selectedIdentity = Identity(id: IdentityId(Id('alice'))); final selectedIdentity = Identity(id: IdentityId(Id('alice')));
@@ -683,6 +699,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -735,6 +752,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.identitySelected.value = identity; composerController?.identitySelected.value = identity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -748,6 +766,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: alwaysReadReceiptEnabled hasReadReceipt: alwaysReadReceiptEnabled
@@ -776,6 +795,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.identitySelected.value = identity; composerController?.identitySelected.value = identity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -787,6 +807,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -823,6 +844,7 @@ void main() {
to: {toRecipient}, to: {toRecipient},
cc: {ccRecipient}, cc: {ccRecipient},
bcc: {bccRecipient}, bcc: {bccRecipient},
replyTo: {replyToRecipient},
mailboxContain: PresentationMailbox( mailboxContain: PresentationMailbox(
MailboxId(Id('some-mailbox-id')), MailboxId(Id('some-mailbox-id')),
role: PresentationMailbox.roleJunk)), role: PresentationMailbox.roleJunk)),
@@ -837,6 +859,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -876,6 +899,7 @@ void main() {
to: {toRecipient}, to: {toRecipient},
cc: {ccRecipient}, cc: {ccRecipient},
bcc: {bccRecipient}, bcc: {bccRecipient},
replyTo: {replyToRecipient},
mailboxContain: PresentationMailbox( mailboxContain: PresentationMailbox(
MailboxId(Id('some-mailbox-id')), MailboxId(Id('some-mailbox-id')),
role: PresentationMailbox.roleJunk)), role: PresentationMailbox.roleJunk)),
@@ -889,6 +913,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -930,6 +955,7 @@ void main() {
to: {toRecipient}, to: {toRecipient},
cc: {ccRecipient}, cc: {ccRecipient},
bcc: {bccRecipient}, bcc: {bccRecipient},
replyTo: {replyToRecipient},
mailboxContain: PresentationMailbox( mailboxContain: PresentationMailbox(
MailboxId(Id('some-mailbox-id')), MailboxId(Id('some-mailbox-id')),
role: PresentationMailbox.roleJunk)), role: PresentationMailbox.roleJunk)),
@@ -946,6 +972,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -987,6 +1014,7 @@ void main() {
to: {toRecipient}, to: {toRecipient},
cc: {ccRecipient}, cc: {ccRecipient},
bcc: {bccRecipient}, bcc: {bccRecipient},
replyTo: {replyToRecipient},
mailboxContain: PresentationMailbox( mailboxContain: PresentationMailbox(
MailboxId(Id('some-mailbox-id')), MailboxId(Id('some-mailbox-id')),
role: PresentationMailbox.roleJunk)),)); role: PresentationMailbox.roleJunk)),));
@@ -1002,6 +1030,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -1041,6 +1070,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
final selectedIdentity = Identity(id: IdentityId(Id('alice'))); final selectedIdentity = Identity(id: IdentityId(Id('alice')));
composerController?.identitySelected.value = selectedIdentity; composerController?.identitySelected.value = selectedIdentity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -1060,6 +1090,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -1113,6 +1144,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
final selectedIdentity = Identity(id: IdentityId(Id('alice'))); final selectedIdentity = Identity(id: IdentityId(Id('alice')));
composerController?.identitySelected.value = selectedIdentity; composerController?.identitySelected.value = selectedIdentity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
@@ -1132,6 +1164,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: selectedIdentity, identity: selectedIdentity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: false hasReadReceipt: false
@@ -1178,6 +1211,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.hasRequestReadReceipt.value = alwaysReadReceiptEnabled; composerController?.hasRequestReadReceipt.value = alwaysReadReceiptEnabled;
const idenityId = 'some-identity-id'; const idenityId = 'some-identity-id';
@@ -1198,6 +1232,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: alwaysReadReceiptEnabled hasReadReceipt: alwaysReadReceiptEnabled
@@ -1227,6 +1262,7 @@ void main() {
composerController?.listToEmailAddress = [toRecipient]; composerController?.listToEmailAddress = [toRecipient];
composerController?.listCcEmailAddress = [ccRecipient]; composerController?.listCcEmailAddress = [ccRecipient];
composerController?.listBccEmailAddress = [bccRecipient]; composerController?.listBccEmailAddress = [bccRecipient];
composerController?.listReplyToEmailAddress = [replyToRecipient];
composerController?.identitySelected.value = identity; composerController?.identitySelected.value = identity;
when(mockUploadController.attachmentsUploaded).thenReturn([attachment]); when(mockUploadController.attachmentsUploaded).thenReturn([attachment]);
composerController?.hasRequestReadReceipt.value = alwaysReadReceiptEnabled; composerController?.hasRequestReadReceipt.value = alwaysReadReceiptEnabled;
@@ -1237,6 +1273,7 @@ void main() {
toRecipients: {toRecipient}, toRecipients: {toRecipient},
ccRecipients: {ccRecipient}, ccRecipients: {ccRecipient},
bccRecipients: {bccRecipient}, bccRecipients: {bccRecipient},
replyToRecipients: {replyToRecipient},
identity: identity, identity: identity,
attachments: [attachment], attachments: [attachment],
hasReadReceipt: alwaysReadReceiptEnabled hasReadReceipt: alwaysReadReceiptEnabled
@@ -19,6 +19,7 @@ void main() {
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
); );
group('create email request extension test:', () { group('create email request extension test:', () {
@@ -16,6 +16,7 @@ void main() {
toRecipients: {EmailAddress('to name', 'to email')}, toRecipients: {EmailAddress('to name', 'to email')},
ccRecipients: {EmailAddress('cc name', 'cc email')}, ccRecipients: {EmailAddress('cc name', 'cc email')},
bccRecipients: {EmailAddress('bcc name', 'bcc email')}, bccRecipients: {EmailAddress('bcc name', 'bcc email')},
replyToRecipients: {EmailAddress('replyTo name', 'replyTo email')},
identity: null, identity: null,
attachments: [], attachments: [],
hasReadReceipt: false hasReadReceipt: false
@@ -37,7 +38,7 @@ void main() {
// arrange // arrange
const subject = 'subject'; const subject = 'subject';
const content = 'content'; const content = 'content';
final recipent = EmailAddress('recipent name', 'recipent email'); final recipient = EmailAddress('recipient name', 'recipient email');
final identity = Identity(); final identity = Identity();
final attachments = <Attachment>[]; final attachments = <Attachment>[];
const hasReadReceipt = false; const hasReadReceipt = false;
@@ -45,9 +46,10 @@ void main() {
final toSavedEmailDraft = SavedEmailDraft( final toSavedEmailDraft = SavedEmailDraft(
subject: subject, subject: subject,
content: content, content: content,
toRecipients: {recipent}, toRecipients: {recipient},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
identity: identity, identity: identity,
attachments: attachments, attachments: attachments,
hasReadReceipt: hasReadReceipt hasReadReceipt: hasReadReceipt
@@ -57,8 +59,9 @@ void main() {
subject: subject, subject: subject,
content: content, content: content,
toRecipients: {}, toRecipients: {},
ccRecipients: {recipent}, ccRecipients: {recipient},
bccRecipients: {}, bccRecipients: {},
replyToRecipients: {},
identity: identity, identity: identity,
attachments: attachments, attachments: attachments,
hasReadReceipt: hasReadReceipt hasReadReceipt: hasReadReceipt
@@ -69,21 +72,36 @@ void main() {
content: content, content: content,
toRecipients: {}, toRecipients: {},
ccRecipients: {}, ccRecipients: {},
bccRecipients: {recipent}, bccRecipients: {recipient},
replyToRecipients: {},
identity: identity, identity: identity,
attachments: attachments, attachments: attachments,
hasReadReceipt: hasReadReceipt hasReadReceipt: hasReadReceipt
); );
final replyToSavedEmailDraft = SavedEmailDraft(
subject: subject,
content: content,
toRecipients: {},
ccRecipients: {},
bccRecipients: {},
replyToRecipients: {recipient},
identity: identity,
attachments: attachments,
hasReadReceipt: hasReadReceipt
);
// act // act
final toProps = toSavedEmailDraft.props; final toProps = toSavedEmailDraft.props;
final ccProps = ccSavedEmailDraft.props; final ccProps = ccSavedEmailDraft.props;
final bccProps = bccSavedEmailDraft.props; final bccProps = bccSavedEmailDraft.props;
final replyToProps = replyToSavedEmailDraft.props;
// assert // assert
expect(toProps.hashCode, isNot(ccProps.hashCode)); expect(toProps.hashCode, isNot(ccProps.hashCode));
expect(ccProps.hashCode, isNot(bccProps.hashCode)); expect(ccProps.hashCode, isNot(bccProps.hashCode));
expect(bccProps.hashCode, isNot(toProps.hashCode)); expect(bccProps.hashCode, isNot(replyToProps.hashCode));
expect(replyToProps.hashCode, isNot(toProps.hashCode));
}); });
test( test(
@@ -100,6 +118,7 @@ void main() {
toRecipients: listToRecipients, toRecipients: listToRecipients,
ccRecipients: {EmailAddress('cc name', 'cc email')}, ccRecipients: {EmailAddress('cc name', 'cc email')},
bccRecipients: {EmailAddress('bcc name', 'bcc email')}, bccRecipients: {EmailAddress('bcc name', 'bcc email')},
replyToRecipients: {EmailAddress('replyTo name', 'replyTo email')},
identity: null, identity: null,
attachments: [], attachments: [],
hasReadReceipt: false hasReadReceipt: false
@@ -125,6 +144,7 @@ void main() {
toRecipients: {EmailAddress('to name', 'to email')}, toRecipients: {EmailAddress('to name', 'to email')},
ccRecipients: {EmailAddress('cc name', 'cc email')}, ccRecipients: {EmailAddress('cc name', 'cc email')},
bccRecipients: {EmailAddress('bcc name', 'bcc email')}, bccRecipients: {EmailAddress('bcc name', 'bcc email')},
replyToRecipients: {EmailAddress('replyTo name', 'replyTo email')},
identity: null, identity: null,
attachments: [], attachments: [],
hasReadReceipt: false hasReadReceipt: false
@@ -136,6 +156,7 @@ void main() {
toRecipients: {EmailAddress('to name', 'to email')}, toRecipients: {EmailAddress('to name', 'to email')},
ccRecipients: {EmailAddress('cc name', 'cc email')}, ccRecipients: {EmailAddress('cc name', 'cc email')},
bccRecipients: {EmailAddress('bcc name', 'bcc email')}, bccRecipients: {EmailAddress('bcc name', 'bcc email')},
replyToRecipients: {EmailAddress('replyTo name', 'replyTo email')},
identity: null, identity: null,
attachments: [], attachments: [],
hasReadReceipt: false hasReadReceipt: false
@@ -16,8 +16,8 @@ void main() {
final replyToEmailAddress = EmailAddress('Reply To', 'replyToThis@domain.com'); final replyToEmailAddress = EmailAddress('Reply To', 'replyToThis@domain.com');
final replyToListEmailAddress = EmailAddress(null, 'replyToList@domain.com'); final replyToListEmailAddress = EmailAddress(null, 'replyToList@domain.com');
group('GIVEN user A is the sender AND send an email to user B and user E, cc to user C, bcc to user D', () { group('GIVEN user A is the sender AND sends an email to user B and user E, cc to user C, bcc to user D', () {
test('THEN user A click reply, generateRecipientsEmailAddressForComposer SHOULD return user B email + user E email to reply', () { test('THEN user A clicks reply, generateRecipientsEmailAddressForComposer SHOULD return user B email + user E email to reply', () {
final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[], <EmailAddress>[]); final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[], <EmailAddress>[]);
final emailToReply = PresentationEmail( final emailToReply = PresentationEmail(
@@ -38,7 +38,7 @@ void main() {
expect(result.value3, containsAll(expectedResult.value3)); expect(result.value3, containsAll(expectedResult.value3));
}); });
test('THEN user A click reply all, generateRecipientsEmailAddressForComposer SHOULD return user B email + user E email to reply, user C email address to cc, user D email address to bcc', () { test('THEN user A clicks reply all, generateRecipientsEmailAddressForComposer SHOULD return user B email + user E email to reply, user C email address to cc, user D email address to bcc', () {
final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]); final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]);
final emailToReply = PresentationEmail( final emailToReply = PresentationEmail(
@@ -82,7 +82,7 @@ void main() {
expect(result.value3, containsAll(expectedResult.value3)); expect(result.value3, containsAll(expectedResult.value3));
}); });
test('THEN user A click reply all, generateRecipientsEmailAddressForComposer SHOULD return replyToEmailAddress + user A email + user E email to reply, user C email address to cc, user D email address to bcc', () { test('THEN user A clicks reply all, generateRecipientsEmailAddressForComposer SHOULD return replyToEmailAddress + user A email + user E email to reply, user C email address to cc, user D email address to bcc', () {
final expectedResult = Tuple3([userAEmailAddress, userEEmailAddress, replyToEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]); final expectedResult = Tuple3([userAEmailAddress, userEEmailAddress, replyToEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]);
final emailToReply = PresentationEmail( final emailToReply = PresentationEmail(
@@ -104,8 +104,8 @@ void main() {
}); });
}); });
group('GIVEN user B is the sender, SENDER does not have the replyTo email AND send an email to user A and user E, cc to user C, bcc to user D', () { group('GIVEN user B is the sender, SENDER does not have the replyTo email AND sends an email to user A and user E, cc to user C, bcc to user D', () {
test('THEN user A click reply, generateRecipientsEmailAddressForComposer SHOULD return only user B email to reply', () { test('THEN user A clicks reply, generateRecipientsEmailAddressForComposer SHOULD return only user B email to reply', () {
final expectedResult = Tuple3([userBEmailAddress], <EmailAddress>[], <EmailAddress>[]); final expectedResult = Tuple3([userBEmailAddress], <EmailAddress>[], <EmailAddress>[]);
final emailToReply = PresentationEmail( final emailToReply = PresentationEmail(
@@ -125,7 +125,7 @@ void main() {
expect(result.value3, containsAll(expectedResult.value3)); expect(result.value3, containsAll(expectedResult.value3));
}); });
test('THEN user A click reply all, generateRecipientsEmailAddressForComposer SHOULD return user A email + user E email + user B email to reply, user C email to cc, user D email to bcc', () { test('THEN user A clicks reply all, generateRecipientsEmailAddressForComposer SHOULD return user A email + user E email + user B email to reply, user C email to cc, user D email to bcc', () {
final expectedResult = Tuple3([userAEmailAddress, userEEmailAddress, userBEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]); final expectedResult = Tuple3([userAEmailAddress, userEEmailAddress, userBEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]);
final emailToReply = PresentationEmail( final emailToReply = PresentationEmail(
@@ -171,7 +171,7 @@ void main() {
}); });
}); });
group('Given user A is the sender AND send an email to user B + user E, cc to user C, bcc to user D THEN user B click forward', () { group('Given user A is the sender AND sends an email to user B + user E, cc to user C, bcc to user D THEN user B clicks forward', () {
test('generateRecipientsEmailAddressForComposer SHOULD return user user B email + user E email to reply, user C email to cc, user D email to bcc', () { test('generateRecipientsEmailAddressForComposer SHOULD return user user B email + user E email to reply, user C email to cc, user D email to bcc', () {
final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]); final expectedResult = Tuple3([userBEmailAddress, userEEmailAddress], <EmailAddress>[userCEmailAddress], <EmailAddress>[userDEmailAddress]);