_getEmailBodyText({bool changedEmail = false}) async {
if (kIsWeb) {
return await htmlControllerBrowser.getText();
} else {
- if (onlyText) {
- return (await htmlEditorApi?.getText()) ?? '';
+ if (changedEmail) {
+ return await htmlEditorApi?.getText() ?? '';
} else {
- return (await htmlEditorApi?.getFullHtml()) ?? '';
+ final content = await htmlEditorApi?.getText() ?? '';
+ if (_isMobileApp && identitySelected.value?.textSignature?.value.isNotEmpty == true) {
+ final newContent = '$content
--
${identitySelected.value?.textSignature?.value}
';
+ log('ComposerController::_generateEmail()_MOBILE: $newContent');
+ return newContent;
+ } else {
+ return content;
+ }
}
}
}
@@ -328,9 +337,12 @@ class ComposerController extends BaseController {
if (arguments.presentationEmail != null && userProfile != null) {
final userEmailAddress = EmailAddress(null, userProfile.email);
- final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole);
+ final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(
+ arguments.emailActionType,
+ arguments.mailboxRole);
- if (arguments.mailboxRole == PresentationMailbox.roleSent || arguments.emailActionType == EmailActionType.edit) {
+ if (arguments.mailboxRole == PresentationMailbox.roleSent
+ || arguments.emailActionType == EmailActionType.edit) {
listToEmailAddress = recipients.value1;
listCcEmailAddress = recipients.value2;
listBccEmailAddress = recipients.value3;
@@ -362,7 +374,8 @@ class ComposerController extends BaseController {
_updateStatusEmailSendButton();
}
- void updateListEmailAddress(PrefixEmailAddress prefixEmailAddress, List newListEmailAddress) {
+ void updateListEmailAddress(PrefixEmailAddress prefixEmailAddress,
+ List newListEmailAddress) {
switch(prefixEmailAddress) {
case PrefixEmailAddress.to:
listToEmailAddress = newListEmailAddress;
@@ -395,22 +408,31 @@ class ComposerController extends BaseController {
final headerEmailQuotedAsHtml = headerEmailQuoted != null ? headerEmailQuoted.addBlockTag('cite') : '';
final trustAsHtml = arguments.emailContents?.asHtmlString ?? '';
- final emailQuotedHtml = '$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}';
+ final emailQuotedHtml = '$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}';
return emailQuotedHtml;
}
- Future _generateEmail(Map mapDefaultMailboxId, UserProfile userProfile, {bool asDrafts = false}) async {
+ Future _generateEmail(Map mapDefaultMailboxId,
+ UserProfile userProfile, {bool asDrafts = false}) async {
final generateEmailId = EmailId(Id(_uuid.v1()));
final outboxMailboxId = mapDefaultMailboxId[PresentationMailbox.roleOutbox];
final draftMailboxId = mapDefaultMailboxId[PresentationMailbox.roleDrafts];
- final listFromEmailAddress = {
- EmailAddress(null, userProfile.email)
- };
+ Set listFromEmailAddress = {EmailAddress(null, userProfile.email)};
+ if (identitySelected.value?.email?.isNotEmpty == true) {
+ listFromEmailAddress = {EmailAddress(
+ identitySelected.value?.name,
+ identitySelected.value?.email)};
+ }
+ Set listReplyToEmailAddress = {EmailAddress(null, userProfile.email)};
+ if (identitySelected.value?.replyTo?.isNotEmpty == true) {
+ listReplyToEmailAddress = identitySelected.value!.replyTo!;
+ }
final generatePartId = PartId(_uuid.v1());
final generateBlobId = Id(_uuid.v1());
- final emailBodyText = await _getEmailBodyText();
+ var emailBodyText = await _getEmailBodyText();
+ log('ComposerController::_generateEmail(): $emailBodyText');
final userAgent = await userAgentPlatform;
return Email(
@@ -420,7 +442,7 @@ class ComposerController extends BaseController {
to: listToEmailAddress.toSet(),
cc: listCcEmailAddress.toSet(),
bcc: listBccEmailAddress.toSet(),
- replyTo: listFromEmailAddress,
+ replyTo: listReplyToEmailAddress,
keywords: asDrafts ? {KeyWordIdentifier.emailDraft : true} : null,
subject: subjectEmail.value,
htmlBody: {
@@ -504,7 +526,8 @@ class ComposerController extends BaseController {
if (!_validateAttachmentsSize()) {
showConfirmDialogAction(
context,
- AppLocalizations.of(context).message_dialog_send_email_exceeds_maximum_size(filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
+ AppLocalizations.of(context).message_dialog_send_email_exceeds_maximum_size(
+ filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
AppLocalizations.of(context).got_it,
() => {},
title: AppLocalizations.of(context).sending_failed,
@@ -521,7 +544,8 @@ class ComposerController extends BaseController {
final session = mailboxDashBoardController.sessionCurrent;
final mapDefaultMailboxId = mailboxDashBoardController.mapDefaultMailboxId;
final userProfile = mailboxDashBoardController.userProfile.value;
- if (arguments != null && session != null && mapDefaultMailboxId.isNotEmpty && userProfile != null) {
+ if (arguments != null && session != null && mapDefaultMailboxId.isNotEmpty
+ && userProfile != null) {
_saveEmailAddress();
final email = await _generateEmail(mapDefaultMailboxId, userProfile);
@@ -530,11 +554,11 @@ class ComposerController extends BaseController {
final submissionCreateId = Id(_uuid.v1());
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
- accountId,
- EmailRequest(email, submissionCreateId, mailboxIdSaved: sentMailboxId,
- emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
- ? arguments.presentationEmail?.id
- : null)));
+ accountId,
+ EmailRequest(email, submissionCreateId, mailboxIdSaved: sentMailboxId,
+ emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
+ ? arguments.presentationEmail?.id
+ : null)));
}
if (kIsWeb) {
@@ -564,7 +588,8 @@ class ComposerController extends BaseController {
Future> getAutoCompleteSuggestion({String? word, bool? isAll}) async {
if (_contactSuggestionSource == ContactSuggestionSource.all) {
- return await _getAutoCompleteWithDeviceContactInteractor.execute(AutoCompletePattern(word: word, isAll: isAll))
+ return await _getAutoCompleteWithDeviceContactInteractor
+ .execute(AutoCompletePattern(word: word, isAll: isAll))
.then((value) => value.fold(
(failure) => [],
(success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : []));
@@ -610,7 +635,8 @@ class ComposerController extends BaseController {
if (currentContext != null) {
showConfirmDialogAction(
currentContext!,
- AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
+ AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(
+ filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
AppLocalizations.of(currentContext!).got_it,
() => {},
title: AppLocalizations.of(currentContext!).maximum_files_size,
@@ -686,7 +712,8 @@ class ComposerController extends BaseController {
}
Future _isEmailChanged(BuildContext context, ComposerArguments arguments) async {
- final newEmailBody = await _getEmailBodyText(onlyText: true);
+ final newEmailBody = (await _getEmailBodyText(changedEmail: true))
+ .replaceAll('
', '');
log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody');
var oldEmailBody = '';
final contentEmail = getContentEmail(context);
@@ -747,9 +774,11 @@ class ComposerController extends BaseController {
final oldEmail = arguments.presentationEmail;
if (arguments.emailActionType == EmailActionType.edit && oldEmail != null) {
- mailboxDashBoardController.consumeState(_updateEmailDraftsInteractor.execute(accountId, newEmail, oldEmail.id));
+ mailboxDashBoardController.consumeState(
+ _updateEmailDraftsInteractor.execute(accountId, newEmail, oldEmail.id));
} else {
- mailboxDashBoardController.consumeState(_saveEmailAsDraftsInteractor.execute(accountId, newEmail));
+ mailboxDashBoardController.consumeState(
+ _saveEmailAsDraftsInteractor.execute(accountId, newEmail));
}
}
}
@@ -821,7 +850,8 @@ class ComposerController extends BaseController {
}
void toggleDisplayAttachments() {
- final newExpandMode = expandModeAttachments.value == ExpandMode.COLLAPSE ? ExpandMode.EXPAND : ExpandMode.COLLAPSE;
+ final newExpandMode = expandModeAttachments.value == ExpandMode.COLLAPSE
+ ? ExpandMode.EXPAND : ExpandMode.COLLAPSE;
expandModeAttachments.value = newExpandMode;
}
@@ -912,7 +942,87 @@ class ComposerController extends BaseController {
}
void selectIdentity(Identity? newIdentity) {
+ final formerIdentity = identitySelected.value;
identitySelected.value = newIdentity;
+ if (newIdentity != null) {
+ _applyIdentityForAllFieldComposer(formerIdentity, newIdentity);
+ FocusManager.instance.primaryFocus?.unfocus();
+ }
+ }
+
+ bool get _isMobileApp {
+ return !BuildUtils.isWeb
+ && currentContext != null
+ && _responsiveUtils.isMobile(currentContext!);
+ }
+
+ void _applyIdentityForAllFieldComposer(Identity? formerIdentity, Identity newIdentity) {
+ if (formerIdentity != null) {
+ // Remove former identity
+ if (formerIdentity.bcc?.isNotEmpty == true) {
+ _removeBccEmailAddressFromFormerIdentity(formerIdentity.bcc!);
+ }
+
+ if (!_isMobileApp) {
+ _removeSignature();
+ }
+ }
+
+ // Add new identity
+ if (newIdentity.bcc?.isNotEmpty == true) {
+ _applyBccEmailAddressFromIdentity(newIdentity.bcc!);
+ }
+
+ if (!_isMobileApp) {
+ if (newIdentity.htmlSignature?.value.isNotEmpty == true) {
+ _applySignature(newIdentity.htmlSignature!);
+ } else if (newIdentity.textSignature?.value.isNotEmpty == true) {
+ _applySignature(newIdentity.textSignature!);
+ }
+ }
+ }
+
+ void _applyBccEmailAddressFromIdentity(Set listEmailAddress) {
+ if (!listEmailAddressType.contains(PrefixEmailAddress.bcc)) {
+ listEmailAddressType.add(PrefixEmailAddress.bcc);
+ }
+ listBccEmailAddress = listEmailAddress.toList();
+ toAddressExpandMode.value = ExpandMode.COLLAPSE;
+ ccAddressExpandMode.value = ExpandMode.COLLAPSE;
+ bccAddressExpandMode.value = ExpandMode.COLLAPSE;
+ _updateStatusEmailSendButton();
+ }
+
+ void _removeBccEmailAddressFromFormerIdentity(Set listEmailAddress) {
+ listBccEmailAddress = listBccEmailAddress
+ .where((address) => !listEmailAddress.contains(address))
+ .toList();
+ if (listBccEmailAddress.isEmpty) {
+ listEmailAddressType.remove(PrefixEmailAddress.bcc);
+ }
+ toAddressExpandMode.value = ExpandMode.COLLAPSE;
+ ccAddressExpandMode.value = ExpandMode.COLLAPSE;
+ bccAddressExpandMode.value = ExpandMode.COLLAPSE;
+ _updateStatusEmailSendButton();
+ }
+
+ void _applySignature(Signature signature) {
+ final signatureAsHtml = '--
${signature.value}';
+ log('ComposerController::_applySignature(): $signatureAsHtml');
+ if (BuildUtils.isWeb) {
+ htmlControllerBrowser.insertSignature(signatureAsHtml);
+ } else {
+ htmlEditorApi?.insertSignature(signatureAsHtml);
+ }
+ }
+
+ void _removeSignature() {
+ log('ComposerController::_removeSignature():');
+ if (BuildUtils.isWeb) {
+ htmlControllerBrowser.removeSignature();
+ } else {
+ htmlEditorApi?.removeSignature();
+ }
}
void closeComposer() {
diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart
index ea2f27bf7..420a88f4c 100644
--- a/lib/features/composer/presentation/composer_view.dart
+++ b/lib/features/composer/presentation/composer_view.dart
@@ -89,7 +89,9 @@ class ComposerView extends GetWidget {
borderRadius: const BorderRadius.all(Radius.circular(24)),
child: SafeArea(
child: Column(children: [
- Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildAppBar(context, controller.isEnableEmailSendButton.value)),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: _buildAppBar(context, controller.isEnableEmailSendButton.value)),
const Padding(padding: EdgeInsets.only(top: 8), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
Expanded(child: _buildBodyTablet(context)),
const Divider(color: AppColor.colorDividerComposer, height: 1),
@@ -119,12 +121,13 @@ class ComposerView extends GetWidget {
controller.closeComposer();
}),
Expanded(child: _buildTitleComposer(context)),
- buildIconWeb(
- icon: SvgPicture.asset(
- isEnableSendButton ? imagePaths.icSendMobile : imagePaths.icSendDisable,
- fit: BoxFit.fill),
- tooltip: AppLocalizations.of(context).send,
- onTap: () => controller.sendEmailAction(context)),
+ if (responsiveUtils.isMobile(context))
+ buildIconWeb(
+ icon: SvgPicture.asset(
+ isEnableSendButton ? imagePaths.icSendMobile : imagePaths.icSendDisable,
+ fit: BoxFit.fill),
+ tooltip: AppLocalizations.of(context).send,
+ onTap: () => controller.sendEmailAction(context)),
]
),
);
@@ -481,6 +484,7 @@ class ComposerView extends GetWidget {
return HtmlEditor(
key: const Key('composer_editor'),
minHeight: 550,
+ initialContent: '
',
onCreated: (editorApi) => controller.htmlEditorApi = editorApi);
} else {
final message = controller.getContentEmail(context);
diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart
index ef1443fb4..d4002264c 100644
--- a/lib/features/composer/presentation/composer_view_web.dart
+++ b/lib/features/composer/presentation/composer_view_web.dart
@@ -331,29 +331,31 @@ class ComposerView extends GetWidget {
customButton: SvgPicture.asset(imagePaths.icEditIdentity),
items: controller.listIdentities.map((item) => DropdownMenuItem(
value: item,
- child: Container(
- alignment: Alignment.centerLeft,
- padding: const EdgeInsets.symmetric(horizontal: 8),
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(12),
- color: item == controller.identitySelected.value ? AppColor.colorBgMenuItemDropDownSelected : Colors.transparent),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- item.name ?? '',
- style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, color: Colors.black),
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- ),
- Text(
- item.email ?? '',
- style: const TextStyle(fontSize: 13, fontWeight: FontWeight.normal, color: AppColor.colorHintSearchBar),
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- )
- ]
+ child: PointerInterceptor(
+ child: Container(
+ alignment: Alignment.centerLeft,
+ padding: const EdgeInsets.symmetric(horizontal: 8),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(12),
+ color: item == controller.identitySelected.value ? AppColor.colorBgMenuItemDropDownSelected : Colors.transparent),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(
+ item.name ?? '',
+ style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, color: Colors.black),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ Text(
+ item.email ?? '',
+ style: const TextStyle(fontSize: 13, fontWeight: FontWeight.normal, color: AppColor.colorHintSearchBar),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ )
+ ]
+ ),
),
),
)).toList(),
@@ -516,7 +518,7 @@ class ComposerView extends GetWidget {
Obx(() {
if (controller.composerArguments.value != null) {
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
- final initContent = controller.textEditorWeb ?? '';
+ final initContent = controller.textEditorWeb ?? '
';
return Expanded(child: Padding(
padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10),
child: _buildEditor(context, initContent)));
@@ -554,8 +556,8 @@ class ComposerView extends GetWidget {
return html_editor_browser.HtmlEditor(
key: const Key('composer_editor_web'),
controller: controller.htmlControllerBrowser,
- htmlEditorOptions: html_editor_browser.HtmlEditorOptions(
- hint: AppLocalizations.of(context).hint_compose_email,
+ htmlEditorOptions: const html_editor_browser.HtmlEditorOptions(
+ hint: '',
darkMode: false,
),
blockQuotedContent: initContent,
diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart
index ba5ba924f..e366e48f0 100644
--- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart
+++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart
@@ -150,14 +150,9 @@ class MailboxDashBoardController extends ReloadableController {
message: AppLocalizations.of(currentContext!).message_has_been_sent_successfully,
icon: _imagePaths.icSendToast);
}
- clearState();
} else if (success is SaveEmailAsDraftsSuccess) {
log('MailboxDashBoardController::onDone(): SaveEmailAsDraftsSuccess');
_saveEmailAsDraftsSuccess(success);
- clearState();
- } else if (success is RemoveEmailDraftsSuccess
- || success is UpdateEmailDraftsSuccess) {
- clearState();
} else if (success is MoveToMailboxSuccess) {
_moveToMailboxSuccess(success);
} else if (success is DeleteEmailPermanentlySuccess) {
diff --git a/pubspec.yaml b/pubspec.yaml
index fabfbbf0a..c1521ff06 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -122,13 +122,14 @@ dependencies:
# enough_html_editor: Compose email for Mobile & Tablet
enough_html_editor:
git:
- url: https://github.com/Enough-Software/enough_html_editor.git
+ url: https://github.com/dab246/enough_html_editor.git
+ ref: improvements_for_use_tmail
# html_editor_enhanced: Compose email for Web Browser
html_editor_enhanced:
git:
url: https://github.com/dab246/html-editor-enhanced.git
- ref: fix_display_content
+ ref: improvements_for_use_tmail
# fk_user_agent
fk_user_agent: 2.1.0