TF-1961 Transform html email content in composer
(cherry picked from commit f5470c130744242195b265a0ea4aad044ad8e740)
This commit is contained in:
@@ -5,6 +5,7 @@ import 'package:core/presentation/utils/app_toast.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/style_utils.dart';
|
||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.dart';
|
||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||
import 'package:core/presentation/views/text/text_overflow_builder.dart';
|
||||
@@ -321,22 +322,17 @@ abstract class BaseComposerView extends GetWidget<ComposerController>
|
||||
)
|
||||
),
|
||||
const Spacer(),
|
||||
Material(
|
||||
type: MaterialType.circle,
|
||||
color: Colors.transparent,
|
||||
child: TextButton(
|
||||
onPressed: controller.toggleDisplayAttachments,
|
||||
child: Text(
|
||||
expandModeAttachment == ExpandMode.EXPAND
|
||||
? AppLocalizations.of(context).hide
|
||||
: '${AppLocalizations.of(context).showAll} (${uploadFilesState.length})',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
color: AppColor.colorTextButton
|
||||
)
|
||||
)
|
||||
)
|
||||
TMailButtonWidget.fromText(
|
||||
text: expandModeAttachment == ExpandMode.EXPAND
|
||||
? AppLocalizations.of(context).hide
|
||||
: '${AppLocalizations.of(context).showAll} (${uploadFilesState.length})',
|
||||
onTapActionCallback: controller.toggleDisplayAttachments,
|
||||
textStyle: const TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
color: AppColor.colorTextButton
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
@@ -29,6 +29,7 @@ import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart';
|
||||
@@ -163,6 +164,7 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.lazyPut(() => RemoveComposerCacheOnWebInteractor(Get.find<ComposerCacheRepository>()));
|
||||
Get.lazyPut(() => SaveComposerCacheOnWebInteractor(Get.find<ComposerCacheRepository>()));
|
||||
Get.lazyPut(() => DownloadImageAsBase64Interactor(Get.find<ComposerRepository>()));
|
||||
Get.lazyPut(() => TransformHtmlEmailContentInteractor(Get.find<EmailRepository>()));
|
||||
|
||||
IdentityInteractorsBindings().dependencies();
|
||||
}
|
||||
@@ -184,6 +186,7 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.find<SaveComposerCacheOnWebInteractor>(),
|
||||
Get.find<RichTextWebController>(),
|
||||
Get.find<DownloadImageAsBase64Interactor>(),
|
||||
Get.find<TransformHtmlEmailContentInteractor>(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,11 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/email_ac
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_on_web_interactor.dart';
|
||||
@@ -60,6 +63,7 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_id
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/identity_extension.dart';
|
||||
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
||||
@@ -95,7 +99,7 @@ class ComposerController extends BaseController {
|
||||
final bccAddressExpandMode = ExpandMode.EXPAND.obs;
|
||||
final identitySelected = Rxn<Identity>();
|
||||
final listIdentities = <Identity>[].obs;
|
||||
final emailContentsViewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
|
||||
final emailContentsViewState = Rxn<Either<Failure, Success>>();
|
||||
final hasRequestReadReceipt = false.obs;
|
||||
|
||||
final LocalFilePickerInteractor _localFilePickerInteractor;
|
||||
@@ -109,6 +113,7 @@ class ComposerController extends BaseController {
|
||||
final SaveComposerCacheOnWebInteractor _saveComposerCacheOnWebInteractor;
|
||||
final RichTextWebController richTextWebController;
|
||||
final DownloadImageAsBase64Interactor _downloadImageAsBase64Interactor;
|
||||
final TransformHtmlEmailContentInteractor _transformHtmlEmailContentInteractor;
|
||||
|
||||
GetAutoCompleteWithDeviceContactInteractor? _getAutoCompleteWithDeviceContactInteractor;
|
||||
GetAutoCompleteInteractor? _getAutoCompleteInteractor;
|
||||
@@ -145,7 +150,6 @@ class ComposerController extends BaseController {
|
||||
List<Attachment> initialAttachments = <Attachment>[];
|
||||
String? _textEditorWeb;
|
||||
String? _initTextEditor;
|
||||
String? _emailContents;
|
||||
double? maxWithEditor;
|
||||
late Worker uploadInlineImageWorker;
|
||||
|
||||
@@ -201,6 +205,7 @@ class ComposerController extends BaseController {
|
||||
this._saveComposerCacheOnWebInteractor,
|
||||
this.richTextWebController,
|
||||
this._downloadImageAsBase64Interactor,
|
||||
this._transformHtmlEmailContentInteractor,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -264,7 +269,9 @@ class ComposerController extends BaseController {
|
||||
@override
|
||||
void handleSuccessViewState(Success success) {
|
||||
super.handleSuccessViewState(success);
|
||||
if (success is GetEmailContentLoading) {
|
||||
if (success is GetEmailContentLoading ||
|
||||
success is TransformHtmlEmailContentLoading ||
|
||||
success is TransformHtmlEmailContentSuccess) {
|
||||
emailContentsViewState.value = Right(success);
|
||||
} else if (success is LocalFilePickerSuccess) {
|
||||
_pickFileSuccess(success);
|
||||
@@ -299,7 +306,8 @@ class ComposerController extends BaseController {
|
||||
super.handleFailureViewState(failure);
|
||||
if (failure is LocalFilePickerFailure || failure is LocalFilePickerCancel) {
|
||||
_pickFileFailure(failure);
|
||||
} else if (failure is GetEmailContentFailure) {
|
||||
} else if (failure is GetEmailContentFailure ||
|
||||
failure is TransformHtmlEmailContentFailure) {
|
||||
emailContentsViewState.value = Left(failure);
|
||||
}
|
||||
}
|
||||
@@ -387,39 +395,105 @@ class ComposerController extends BaseController {
|
||||
: Get.arguments;
|
||||
if (arguments is ComposerArguments) {
|
||||
composerArguments.value = arguments;
|
||||
|
||||
injectAutoCompleteBindings(
|
||||
mailboxDashBoardController.sessionCurrent,
|
||||
mailboxDashBoardController.accountId.value);
|
||||
mailboxDashBoardController.sessionCurrent,
|
||||
mailboxDashBoardController.accountId.value
|
||||
);
|
||||
|
||||
if (arguments.emailActionType == EmailActionType.edit) {
|
||||
_getEmailContentAction(arguments);
|
||||
switch(arguments.emailActionType) {
|
||||
case EmailActionType.editDraft:
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.editDraft
|
||||
);
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.editDraft
|
||||
);
|
||||
_getEmailContentFromEmailId(
|
||||
emailId: arguments.presentationEmail!.id!,
|
||||
isDraftEmail: arguments.presentationEmail!.isDraft
|
||||
);
|
||||
break;
|
||||
case EmailActionType.editSendingEmail:
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.sendingEmail!.presentationEmail,
|
||||
actionType: EmailActionType.editSendingEmail
|
||||
);
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.sendingEmail!.presentationEmail,
|
||||
actionType: EmailActionType.editSendingEmail
|
||||
);
|
||||
_getEmailContentFromSendingEmail(arguments.sendingEmail!);
|
||||
break;
|
||||
case EmailActionType.composeFromContentShared:
|
||||
_getEmailContentFromContentShared(arguments.emailContents!);
|
||||
break;
|
||||
case EmailActionType.composeFromFileShared:
|
||||
_addAttachmentFromFileShare(arguments.listSharedMediaFile!);
|
||||
break;
|
||||
case EmailActionType.composeFromEmailAddress:
|
||||
listToEmailAddress.add(arguments.emailAddress!);
|
||||
isInitialRecipient.value = true;
|
||||
toAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
_updateStatusEmailSendButton();
|
||||
break;
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: arguments.emailActionType,
|
||||
mailboxRole: arguments.presentationEmail!.mailboxContain?.role ?? mailboxDashBoardController.selectedMailbox.value?.role
|
||||
);
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: arguments.emailActionType
|
||||
);
|
||||
_transformHtmlEmailContent(arguments.emailContents);
|
||||
break;
|
||||
case EmailActionType.forward:
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: arguments.emailActionType
|
||||
);
|
||||
_initAttachments(arguments.attachments ?? []);
|
||||
_transformHtmlEmailContent(arguments.emailContents);
|
||||
break;
|
||||
case EmailActionType.reopenComposerBrowser:
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.reopenComposerBrowser
|
||||
);
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.reopenComposerBrowser
|
||||
);
|
||||
_initAttachments(arguments.attachments ?? []);
|
||||
_getEmailContentFromSessionStorageBrowser(arguments.emailContents!);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_initEmailAddress(arguments);
|
||||
_initSubjectEmail(arguments);
|
||||
_initAttachments(arguments);
|
||||
}
|
||||
|
||||
_autoFocusFieldWhenLauncher();
|
||||
}
|
||||
|
||||
void _initSubjectEmail(ComposerArguments arguments) {
|
||||
if (currentContext != null) {
|
||||
final subjectEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? '';
|
||||
final newSubject = arguments.emailActionType.getSubjectComposer(currentContext!, subjectEmail);
|
||||
setSubjectEmail(newSubject);
|
||||
subjectEmailInputController.text = newSubject;
|
||||
}
|
||||
void _initSubjectEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required EmailActionType actionType
|
||||
}) {
|
||||
final subjectEmail = presentationEmail.getEmailTitle().trim();
|
||||
final newSubject = actionType.getSubjectComposer(currentContext, subjectEmail);
|
||||
setSubjectEmail(newSubject);
|
||||
subjectEmailInputController.text = newSubject;
|
||||
}
|
||||
|
||||
void _initAttachments(ComposerArguments arguments) {
|
||||
if (arguments.attachments?.isNotEmpty == true) {
|
||||
initialAttachments = arguments.attachments!;
|
||||
uploadController.initializeUploadAttachments(
|
||||
arguments.attachments!.listAttachmentsDisplayedOutSide);
|
||||
}
|
||||
if (PlatformInfo.isWeb) {
|
||||
expandModeAttachments.value = ExpandMode.EXPAND;
|
||||
void _initAttachments(List<Attachment> attachments) {
|
||||
if (attachments.isNotEmpty) {
|
||||
initialAttachments = attachments;
|
||||
uploadController.initializeUploadAttachments(attachments.listAttachmentsDisplayedOutSide);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +512,6 @@ class ComposerController extends BaseController {
|
||||
.toList();
|
||||
|
||||
if (listIdentities.isNotEmpty) {
|
||||
_initTextEditor = null;
|
||||
await selectIdentity(listIdentities.first);
|
||||
}
|
||||
}
|
||||
@@ -446,113 +519,49 @@ class ComposerController extends BaseController {
|
||||
_autoFocusFieldWhenLauncher();
|
||||
}
|
||||
|
||||
String? _getHeaderEmailQuoted(BuildContext context, ComposerArguments arguments) {
|
||||
final presentationEmail = arguments.presentationEmail;
|
||||
if (presentationEmail != null) {
|
||||
final locale = Localizations.localeOf(context).toLanguageTag();
|
||||
log('ComposerController::_getHeaderEmailQuoted(): emailActionType: ${arguments.emailActionType}');
|
||||
switch(arguments.emailActionType) {
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
final receivedAt = presentationEmail.receivedAt;
|
||||
final emailAddress = presentationEmail.from.listEmailAddressToString(isFullEmailAddress: true);
|
||||
return AppLocalizations.of(context).header_email_quoted(
|
||||
receivedAt.formatDateToLocal(pattern: 'MMM d, y h:mm a', locale: locale),
|
||||
emailAddress);
|
||||
case EmailActionType.forward:
|
||||
var headerQuoted = '------- ${AppLocalizations.of(context).forwarded_message} -------'.addNewLineTag();
|
||||
|
||||
final subject = presentationEmail.subject ?? '';
|
||||
final receivedAt = presentationEmail.receivedAt;
|
||||
final fromEmailAddress = presentationEmail.from.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final toEmailAddress = presentationEmail.to.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final ccEmailAddress = presentationEmail.cc.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final bccEmailAddress = presentationEmail.bcc.listEmailAddressToString(isFullEmailAddress: true);
|
||||
|
||||
if (subject.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).subject_email}: ')
|
||||
.append(subject)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (receivedAt != null) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).date}: ')
|
||||
.append(receivedAt.formatDateToLocal(pattern: 'MMM d, y h:mm a', locale: locale))
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (fromEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).from_email_address_prefix}: ')
|
||||
.append(fromEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (toEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).to_email_address_prefix}: ')
|
||||
.append(toEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (ccEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).cc_email_address_prefix}: ')
|
||||
.append(ccEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (bccEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).bcc_email_address_prefix}: ')
|
||||
.append(bccEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
|
||||
return headerQuoted;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _initEmailAddress(ComposerArguments arguments) {
|
||||
void _initEmailAddress({
|
||||
required PresentationEmail presentationEmail,
|
||||
required EmailActionType actionType,
|
||||
Role? mailboxRole,
|
||||
}) {
|
||||
final recipients = presentationEmail.generateRecipientsEmailAddressForComposer(
|
||||
emailActionType: actionType,
|
||||
mailboxRole: mailboxRole
|
||||
);
|
||||
log('ComposerController::_initEmailAddress:recipients: $recipients');
|
||||
final userProfile = mailboxDashBoardController.userProfile.value;
|
||||
if (arguments.presentationEmail != null && userProfile != null) {
|
||||
final userEmailAddress = EmailAddress(null, userProfile.email);
|
||||
final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(
|
||||
arguments.emailActionType,
|
||||
arguments.mailboxRole);
|
||||
|
||||
final isSender = arguments.presentationEmail!.from.asList().every((element) => element.email == userEmailAddress.email);
|
||||
|
||||
if (userProfile != null) {
|
||||
final isSender = presentationEmail.from.asList().every((element) => element.email == userProfile.email);
|
||||
if (isSender) {
|
||||
listToEmailAddress = List.from(recipients.value1);
|
||||
listCcEmailAddress = List.from(recipients.value2);
|
||||
listBccEmailAddress = List.from(recipients.value3);
|
||||
listToEmailAddress = List.from(recipients.value1.toSet());
|
||||
listCcEmailAddress = List.from(recipients.value2.toSet());
|
||||
listBccEmailAddress = List.from(recipients.value3.toSet());
|
||||
} else {
|
||||
listToEmailAddress = List.from(recipients.value1.toSet().filterEmailAddress(userEmailAddress));
|
||||
listCcEmailAddress = List.from(recipients.value2.toSet().filterEmailAddress(userEmailAddress));
|
||||
listBccEmailAddress = List.from(recipients.value3.toSet().filterEmailAddress(userEmailAddress));
|
||||
listToEmailAddress = List.from(recipients.value1.toSet().filterEmailAddress(userProfile.email));
|
||||
listCcEmailAddress = List.from(recipients.value2.toSet().filterEmailAddress(userProfile.email));
|
||||
listBccEmailAddress = List.from(recipients.value3.toSet().filterEmailAddress(userProfile.email));
|
||||
}
|
||||
} else {
|
||||
listToEmailAddress = List.from(recipients.value1.toSet());
|
||||
listCcEmailAddress = List.from(recipients.value2.toSet());
|
||||
listBccEmailAddress = List.from(recipients.value3.toSet());
|
||||
}
|
||||
|
||||
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
|
||||
isInitialRecipient.value = true;
|
||||
toAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
|
||||
if (listCcEmailAddress.isNotEmpty) {
|
||||
listEmailAddressType.add(PrefixEmailAddress.cc);
|
||||
ccAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
|
||||
if (listBccEmailAddress.isNotEmpty) {
|
||||
listEmailAddressType.add(PrefixEmailAddress.bcc);
|
||||
bccAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
} else if (arguments.emailAddress != null) {
|
||||
listToEmailAddress.add(arguments.emailAddress!);
|
||||
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
|
||||
isInitialRecipient.value = true;
|
||||
toAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
|
||||
if (listCcEmailAddress.isNotEmpty) {
|
||||
listEmailAddressType.add(PrefixEmailAddress.cc);
|
||||
ccAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
|
||||
if (listBccEmailAddress.isNotEmpty) {
|
||||
listEmailAddressType.add(PrefixEmailAddress.bcc);
|
||||
bccAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||
}
|
||||
|
||||
_updateStatusEmailSendButton();
|
||||
}
|
||||
|
||||
@@ -586,13 +595,21 @@ class ComposerController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
String getEmailContentQuotedAsHtml(BuildContext context, ComposerArguments arguments) {
|
||||
final headerEmailQuoted = _getHeaderEmailQuoted(context, arguments);
|
||||
String getEmailContentQuotedAsHtml({
|
||||
required BuildContext context,
|
||||
required String emailContent,
|
||||
required EmailActionType emailActionType,
|
||||
required PresentationEmail presentationEmail,
|
||||
}) {
|
||||
final headerEmailQuoted = emailActionType.getHeaderEmailQuoted(
|
||||
context: context,
|
||||
presentationEmail: presentationEmail
|
||||
);
|
||||
log('ComposerController::getEmailContentQuotedAsHtml(): headerEmailQuoted: $headerEmailQuoted');
|
||||
final headerEmailQuotedAsHtml = headerEmailQuoted != null ? headerEmailQuoted.addBlockTag('cite') : '';
|
||||
|
||||
final trustAsHtml = arguments.emailContents ?? '';
|
||||
final emailQuotedHtml = '${HtmlExtension.editorStartTags}$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}';
|
||||
final headerEmailQuotedAsHtml = headerEmailQuoted != null
|
||||
? headerEmailQuoted.addCiteTag()
|
||||
: '';
|
||||
final emailQuotedHtml = '${HtmlExtension.editorStartTags}$headerEmailQuotedAsHtml${emailContent.addBlockQuoteTag()}';
|
||||
|
||||
return emailQuotedHtml;
|
||||
}
|
||||
@@ -789,13 +806,13 @@ class ComposerController extends BaseController {
|
||||
|
||||
if (arguments != null && accountId != null && userProfile != null && session != null) {
|
||||
final createdEmail = await _generateEmail(context, userProfile, outboxMailboxId: outboxMailboxId);
|
||||
final emailRequest = arguments.sendingEmail != null
|
||||
final emailRequest = arguments.emailActionType == EmailActionType.editSendingEmail
|
||||
? arguments.sendingEmail!.toEmailRequest(newEmail: createdEmail)
|
||||
: EmailRequest(
|
||||
email: createdEmail,
|
||||
sentMailboxId: sentMailboxId,
|
||||
identityId: identitySelected.value?.id,
|
||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
|
||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.editDraft
|
||||
? arguments.presentationEmail?.id
|
||||
: null,
|
||||
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
|
||||
@@ -952,36 +969,40 @@ class ComposerController extends BaseController {
|
||||
uploadController.deleteFileUploaded(uploadId);
|
||||
}
|
||||
|
||||
Future<bool> _isEmailChanged(
|
||||
BuildContext context,
|
||||
ComposerArguments arguments,
|
||||
) async {
|
||||
Future<bool> _isEmailChanged({
|
||||
required BuildContext context,
|
||||
required EmailActionType emailActionType,
|
||||
PresentationEmail? presentationEmail,
|
||||
Role? mailboxRole,
|
||||
}) async {
|
||||
final newEmailBody = await _getEmailBodyText(context, changedEmail: true);
|
||||
log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody');
|
||||
var oldEmailBody = _initTextEditor ?? '';
|
||||
final oldEmailBody = _initTextEditor ?? '';
|
||||
log('ComposerController::_isEmailChanged(): oldEmailBody: $oldEmailBody');
|
||||
final isEmailBodyChanged = !oldEmailBody.trim().isSame(newEmailBody.trim());
|
||||
log('ComposerController::_isEmailChanged(): isEmailBodyChanged: $isEmailBodyChanged');
|
||||
|
||||
final newEmailSubject = subjectEmail.value ?? '';
|
||||
final titleEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? '';
|
||||
final oldEmailSubject = arguments.emailActionType == EmailActionType.edit ? titleEmail : '';
|
||||
final oldEmailSubject = emailActionType == EmailActionType.editDraft
|
||||
? presentationEmail?.getEmailTitle().trim() ?? ''
|
||||
: '';
|
||||
final isEmailSubjectChanged = !oldEmailSubject.trim().isSame(newEmailSubject.trim());
|
||||
|
||||
final recipients = arguments.presentationEmail
|
||||
?.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole)
|
||||
?? const Tuple3(<EmailAddress>[], <EmailAddress>[], <EmailAddress>[]);
|
||||
final recipients = presentationEmail
|
||||
?.generateRecipientsEmailAddressForComposer(
|
||||
emailActionType: emailActionType,
|
||||
mailboxRole: mailboxRole
|
||||
) ?? const Tuple3(<EmailAddress>[], <EmailAddress>[], <EmailAddress>[]);
|
||||
|
||||
final newToEmailAddress = listToEmailAddress;
|
||||
final oldToEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value1 : [];
|
||||
final oldToEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value1 : [];
|
||||
final isToEmailAddressChanged = !oldToEmailAddress.isSame(newToEmailAddress);
|
||||
|
||||
final newCcEmailAddress = listCcEmailAddress;
|
||||
final oldCcEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value2 : [];
|
||||
final oldCcEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value2 : [];
|
||||
final isCcEmailAddressChanged = !oldCcEmailAddress.isSame(newCcEmailAddress);
|
||||
|
||||
final newBccEmailAddress = listBccEmailAddress;
|
||||
final oldBccEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value3 : [];
|
||||
final oldBccEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value3 : [];
|
||||
final isBccEmailAddressChanged = !oldBccEmailAddress.isSame(newBccEmailAddress);
|
||||
|
||||
final isAttachmentsChanged = !initialAttachments.isSame(uploadController.attachmentsUploaded.toList());
|
||||
@@ -999,36 +1020,60 @@ class ComposerController extends BaseController {
|
||||
clearFocusEditor(context);
|
||||
|
||||
final arguments = composerArguments.value;
|
||||
final draftMailboxId = mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts];
|
||||
final userProfile = mailboxDashBoardController.userProfile.value;
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
|
||||
if (arguments != null && userProfile != null && accountId != null && session != null) {
|
||||
final isChanged = await _isEmailChanged(context, arguments);
|
||||
if (isChanged && context.mounted) {
|
||||
final newEmail = await _generateEmail(
|
||||
context,
|
||||
userProfile,
|
||||
asDrafts: true,
|
||||
draftMailboxId: draftMailboxId);
|
||||
final oldEmail = arguments.presentationEmail;
|
||||
|
||||
if (arguments.emailActionType == EmailActionType.edit && oldEmail != null && oldEmail.id != null) {
|
||||
mailboxDashBoardController.consumeState(
|
||||
_updateEmailDraftsInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
newEmail,
|
||||
oldEmail.id!
|
||||
)
|
||||
);
|
||||
} else {
|
||||
mailboxDashBoardController.consumeState(_saveEmailAsDraftsInteractor.execute(session, accountId, newEmail));
|
||||
}
|
||||
|
||||
uploadController.clearInlineFileUploaded();
|
||||
if (arguments == null ||
|
||||
userProfile == null ||
|
||||
session == null ||
|
||||
accountId == null
|
||||
) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
mailboxDashBoardController.closeComposerOverlay();
|
||||
} else {
|
||||
if (canPop) popBack();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final isChanged = await _isEmailChanged(
|
||||
context: context,
|
||||
emailActionType: arguments.emailActionType,
|
||||
presentationEmail: arguments.presentationEmail,
|
||||
mailboxRole: arguments.mailboxRole
|
||||
);
|
||||
|
||||
if (isChanged && context.mounted) {
|
||||
final draftMailboxId = mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts];
|
||||
|
||||
final newEmail = await _generateEmail(
|
||||
context,
|
||||
userProfile,
|
||||
asDrafts: true,
|
||||
draftMailboxId: draftMailboxId
|
||||
);
|
||||
|
||||
if (arguments.emailActionType == EmailActionType.editDraft) {
|
||||
mailboxDashBoardController.consumeState(
|
||||
_updateEmailDraftsInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
newEmail,
|
||||
arguments.presentationEmail!.id!
|
||||
)
|
||||
);
|
||||
} else {
|
||||
mailboxDashBoardController.consumeState(
|
||||
_saveEmailAsDraftsInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
newEmail
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
uploadController.clearInlineFileUploaded();
|
||||
}
|
||||
|
||||
if (PlatformInfo.isWeb) {
|
||||
@@ -1087,90 +1132,109 @@ class ComposerController extends BaseController {
|
||||
return listFileInfo;
|
||||
}
|
||||
|
||||
void _getEmailContentAction(ComposerArguments arguments) async {
|
||||
|
||||
final listSharedMediaFile = arguments.listSharedMediaFile;
|
||||
if (listSharedMediaFile != null && listSharedMediaFile.isNotEmpty) {
|
||||
final listImageSharedMediaFile = listSharedMediaFile.where((element) => element.type == SharedMediaType.IMAGE);
|
||||
final listFileAttachmentSharedMediaFile = listSharedMediaFile.where((element) => element.type != SharedMediaType.IMAGE);
|
||||
if (listImageSharedMediaFile.isNotEmpty) {
|
||||
final listInlineImage = covertListSharedMediaFileToInlineImage(arguments.listSharedMediaFile!);
|
||||
for (var e in listInlineImage) {
|
||||
_uploadInlineAttachmentsAction(e.fileInfo!);
|
||||
}
|
||||
void _addAttachmentFromFileShare(List<SharedMediaFile> listSharedMediaFile) {
|
||||
final listImageSharedMediaFile = listSharedMediaFile.where((element) => element.type == SharedMediaType.IMAGE);
|
||||
final listFileAttachmentSharedMediaFile = listSharedMediaFile.where((element) => element.type != SharedMediaType.IMAGE);
|
||||
if (listImageSharedMediaFile.isNotEmpty) {
|
||||
final listInlineImage = covertListSharedMediaFileToInlineImage(listSharedMediaFile);
|
||||
for (var e in listInlineImage) {
|
||||
_uploadInlineAttachmentsAction(e.fileInfo!);
|
||||
}
|
||||
if (listFileAttachmentSharedMediaFile.isNotEmpty) {
|
||||
final listFile = covertListSharedMediaFileToFileInfo(arguments.listSharedMediaFile!);
|
||||
if (uploadController.hasEnoughMaxAttachmentSize(listFiles: listFile)) {
|
||||
_uploadAttachmentsAction(listFile);
|
||||
} else {
|
||||
if (currentContext != null) {
|
||||
showConfirmDialogAction(
|
||||
currentContext!,
|
||||
AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(
|
||||
filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
|
||||
AppLocalizations.of(currentContext!).got_it,
|
||||
onConfirmAction: () => {},
|
||||
title: AppLocalizations.of(currentContext!).maximum_files_size,
|
||||
hasCancelButton: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (listFileAttachmentSharedMediaFile.isNotEmpty) {
|
||||
final listFile = covertListSharedMediaFileToFileInfo(listSharedMediaFile);
|
||||
if (uploadController.hasEnoughMaxAttachmentSize(listFiles: listFile)) {
|
||||
_uploadAttachmentsAction(listFile);
|
||||
} else {
|
||||
if (currentContext != null) {
|
||||
showConfirmDialogAction(
|
||||
currentContext!,
|
||||
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,
|
||||
hasCancelButton: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.emailContents != null && arguments.emailContents!.isNotEmpty && arguments.sendingEmail != null) {
|
||||
_emailContents = arguments.emailContents;
|
||||
emailContentsViewState.value = Right(
|
||||
GetEmailContentSuccess(
|
||||
emailContent: _emailContents!,
|
||||
emailContentDisplayed: '',
|
||||
attachments: [],
|
||||
emailCurrent: arguments.presentationEmail?.toEmail()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: _dynamicUrlInterceptors.jmapUrl);
|
||||
final accountId = mailboxDashBoardController.sessionCurrent?.accounts.keys.first;
|
||||
final emailId = arguments.presentationEmail?.id;
|
||||
if (session != null && emailId != null && baseDownloadUrl != null && accountId != null) {
|
||||
consumeState(_getEmailContentInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadUrl,
|
||||
composeEmail: true,
|
||||
draftsEmail: arguments.presentationEmail?.isDraft ?? false
|
||||
));
|
||||
void _getEmailContentFromSendingEmail(SendingEmail sendingEmail) {
|
||||
consumeState(Stream.value(
|
||||
Right(GetEmailContentSuccess(
|
||||
htmlEmailContent: sendingEmail.presentationEmail.emailContentList.asHtmlString,
|
||||
attachments: sendingEmail.email.allAttachments,
|
||||
emailCurrent: sendingEmail.email
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
void _getEmailContentFromSessionStorageBrowser(String content) {
|
||||
consumeState(Stream.value(
|
||||
Right(GetEmailContentSuccess(
|
||||
htmlEmailContent: content,
|
||||
attachments: [],
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
void _getEmailContentFromContentShared(String content) {
|
||||
consumeState(Stream.value(
|
||||
Right(GetEmailContentSuccess(
|
||||
htmlEmailContent: content,
|
||||
attachments: [],
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
void _getEmailContentFromEmailId({required EmailId emailId, bool isDraftEmail = false}) {
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
if (session != null && accountId != null) {
|
||||
TransformConfiguration transformConfiguration = TransformConfiguration.standardConfiguration;
|
||||
if (isDraftEmail) {
|
||||
transformConfiguration = TransformConfiguration.forDraftsEmail();
|
||||
} else if (PlatformInfo.isWeb) {
|
||||
transformConfiguration = TransformConfiguration.forComposeEmailPlatformWeb();
|
||||
}
|
||||
|
||||
consumeState(_getEmailContentInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
emailId,
|
||||
mailboxDashBoardController.baseDownloadUrl,
|
||||
transformConfiguration
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _getEmailContentOffLineSuccess(GetEmailContentFromCacheSuccess success) {
|
||||
if (success.attachments.isNotEmpty) {
|
||||
initialAttachments = success.attachments;
|
||||
uploadController.initializeUploadAttachments(
|
||||
success.attachments.listAttachmentsDisplayedOutSide);
|
||||
}
|
||||
_initAttachments(success.attachments);
|
||||
emailContentsViewState.value = Right(success);
|
||||
_emailContents = success.emailContent;
|
||||
}
|
||||
|
||||
void _getEmailContentSuccess(GetEmailContentSuccess success) {
|
||||
if (success.attachments.isNotEmpty) {
|
||||
initialAttachments = success.attachments;
|
||||
uploadController.initializeUploadAttachments(
|
||||
success.attachments.listAttachmentsDisplayedOutSide);
|
||||
}
|
||||
_initAttachments(success.attachments);
|
||||
emailContentsViewState.value = Right(success);
|
||||
_emailContents = success.emailContent;
|
||||
}
|
||||
|
||||
void _transformHtmlEmailContent(String? emailContent) {
|
||||
emailContentsViewState(Right(TransformHtmlEmailContentLoading()));
|
||||
if (emailContent?.isEmpty == true) {
|
||||
consumeState(Stream.value(Left(TransformHtmlEmailContentFailure(EmptyEmailContentException()))));
|
||||
} else {
|
||||
consumeState(_transformHtmlEmailContentInteractor.execute(
|
||||
emailContent!,
|
||||
TransformConfiguration.forReplyForwardEmail()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
String getEmailAddressSender() {
|
||||
final arguments = composerArguments.value;
|
||||
if (arguments != null) {
|
||||
if (arguments.emailActionType == EmailActionType.edit) {
|
||||
if (arguments.emailActionType == EmailActionType.editDraft) {
|
||||
return arguments.presentationEmail?.from?.first.emailAddress ?? '';
|
||||
} else {
|
||||
return mailboxDashBoardController.userProfile.value?.email ?? '';
|
||||
|
||||
@@ -15,9 +15,11 @@ import 'package:get/get.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:rich_text_composer/rich_text_composer.dart';
|
||||
import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/cupertino_loading_widget.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/base_composer_view.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
|
||||
@@ -276,38 +278,96 @@ class ComposerView extends BaseComposerView {
|
||||
switch(argsComposer.emailActionType) {
|
||||
case EmailActionType.compose:
|
||||
case EmailActionType.composeFromEmailAddress:
|
||||
return _buildHtmlEditor(context, initialContent: HtmlExtension.editorStartTags);
|
||||
case EmailActionType.edit:
|
||||
return controller.emailContentsViewState.value.fold(
|
||||
(failure) => _buildHtmlEditor(context, initialContent: HtmlExtension.editorStartTags),
|
||||
case EmailActionType.composeFromFileShared:
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: HtmlExtension.editorStartTags
|
||||
);
|
||||
case EmailActionType.editDraft:
|
||||
case EmailActionType.editSendingEmail:
|
||||
case EmailActionType.composeFromContentShared:
|
||||
case EmailActionType.reopenComposerBrowser:
|
||||
final emailContentsViewState = controller.emailContentsViewState.value;
|
||||
if (emailContentsViewState == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return emailContentsViewState.fold(
|
||||
(failure) => _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: HtmlExtension.editorStartTags
|
||||
),
|
||||
(success) {
|
||||
if (success is GetEmailContentLoading) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: loadingWidget,
|
||||
);
|
||||
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
|
||||
} else if (success is GetEmailContentSuccess) {
|
||||
var contentHtml = success.emailContent;
|
||||
var contentHtml = success.htmlEmailContent;
|
||||
if (contentHtml.isEmpty == true) {
|
||||
contentHtml = HtmlExtension.editorStartTags;
|
||||
}
|
||||
return _buildHtmlEditor(context, initialContent: contentHtml);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: contentHtml
|
||||
);
|
||||
} else {
|
||||
return _buildHtmlEditor(context, initialContent: HtmlExtension.editorStartTags);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: HtmlExtension.editorStartTags
|
||||
);
|
||||
}
|
||||
});
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
case EmailActionType.forward:
|
||||
var contentHtml = controller.getEmailContentQuotedAsHtml(
|
||||
context,
|
||||
argsComposer);
|
||||
if (contentHtml.isEmpty == true) {
|
||||
contentHtml = HtmlExtension.editorStartTags;
|
||||
final emailContentsViewState = controller.emailContentsViewState.value;
|
||||
if (emailContentsViewState == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return _buildHtmlEditor(context, initialContent: contentHtml);
|
||||
return emailContentsViewState.fold(
|
||||
(failure) {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: '',
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: emailContentQuoted
|
||||
);
|
||||
},
|
||||
(success) {
|
||||
if (success is TransformHtmlEmailContentLoading) {
|
||||
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
|
||||
} else if (success is TransformHtmlEmailContentSuccess) {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: success.htmlContent,
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: emailContentQuoted
|
||||
);
|
||||
} else {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: '',
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: emailContentQuoted
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
default:
|
||||
return _buildHtmlEditor(context, initialContent: HtmlExtension.editorStartTags);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
initialContent: HtmlExtension.editorStartTags
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,12 +10,14 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/cupertino_loading_widget.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/base_composer_view.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_editor_widget.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/toolbar_rich_text_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
|
||||
@@ -385,46 +387,96 @@ class ComposerView extends BaseComposerView {
|
||||
switch(argsComposer.emailActionType) {
|
||||
case EmailActionType.compose:
|
||||
case EmailActionType.composeFromEmailAddress:
|
||||
case EmailActionType.composeFromFileShared:
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags);
|
||||
case EmailActionType.edit:
|
||||
return controller.emailContentsViewState.value.fold(
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags
|
||||
);
|
||||
case EmailActionType.editDraft:
|
||||
case EmailActionType.editSendingEmail:
|
||||
case EmailActionType.composeFromContentShared:
|
||||
case EmailActionType.reopenComposerBrowser:
|
||||
final emailContentsViewState = controller.emailContentsViewState.value;
|
||||
if (emailContentsViewState == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return emailContentsViewState.fold(
|
||||
(failure) => _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags),
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags
|
||||
),
|
||||
(success) {
|
||||
if (success is GetEmailContentLoading) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: loadingWidget,
|
||||
);
|
||||
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
|
||||
} else if (success is GetEmailContentSuccess) {
|
||||
var contentHtml = success.emailContent;
|
||||
var contentHtml = success.htmlEmailContent;
|
||||
if (contentHtml.isEmpty == true) {
|
||||
contentHtml = HtmlExtension.editorStartTags;
|
||||
}
|
||||
return _buildHtmlEditor(context, currentTextEditor ?? contentHtml);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? contentHtml
|
||||
);
|
||||
} else {
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags);
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags
|
||||
);
|
||||
}
|
||||
});
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
case EmailActionType.forward:
|
||||
var contentHtml = controller.getEmailContentQuotedAsHtml(
|
||||
context,
|
||||
argsComposer);
|
||||
if (contentHtml.isEmpty == true) {
|
||||
contentHtml = HtmlExtension.editorStartTags;
|
||||
final emailContentsViewState = controller.emailContentsViewState.value;
|
||||
if (emailContentsViewState == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return _buildHtmlEditor(context, currentTextEditor ?? contentHtml);
|
||||
return emailContentsViewState.fold(
|
||||
(failure) {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: '',
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? emailContentQuoted
|
||||
);
|
||||
},
|
||||
(success) {
|
||||
if (success is TransformHtmlEmailContentLoading) {
|
||||
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
|
||||
} else if (success is TransformHtmlEmailContentSuccess) {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: success.htmlContent,
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? emailContentQuoted
|
||||
);
|
||||
} else {
|
||||
final emailContentQuoted = controller.getEmailContentQuotedAsHtml(
|
||||
context: context,
|
||||
emailContent: '',
|
||||
emailActionType: argsComposer.emailActionType,
|
||||
presentationEmail: argsComposer.presentationEmail!
|
||||
);
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? emailContentQuoted
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
default:
|
||||
return _buildHtmlEditor(
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags);
|
||||
context,
|
||||
currentTextEditor ?? HtmlExtension.editorStartTags
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
|
||||
import 'package:core/presentation/extensions/html_extension.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:model/extensions/utc_date_extension.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
extension EmailActionTypeExtension on EmailActionType {
|
||||
String getSubjectComposer(BuildContext context, String subject) {
|
||||
String getSubjectComposer(BuildContext? context, String subject) {
|
||||
switch(this) {
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
if (subject.toLowerCase().startsWith('re:')) {
|
||||
return subject;
|
||||
} else {
|
||||
return '${AppLocalizations.of(context).prefix_reply_email} $subject';
|
||||
return context != null
|
||||
? '${AppLocalizations.of(context).prefix_reply_email} $subject'
|
||||
: subject;
|
||||
}
|
||||
case EmailActionType.forward:
|
||||
if (subject.toLowerCase().startsWith('fwd:')) {
|
||||
return subject;
|
||||
} else {
|
||||
return '${AppLocalizations.of(context).prefix_forward_email} $subject';
|
||||
return context != null
|
||||
? '${AppLocalizations.of(context).prefix_forward_email} $subject'
|
||||
: subject;
|
||||
}
|
||||
case EmailActionType.edit:
|
||||
case EmailActionType.editDraft:
|
||||
case EmailActionType.editSendingEmail:
|
||||
case EmailActionType.reopenComposerBrowser:
|
||||
return subject;
|
||||
default:
|
||||
return '';
|
||||
@@ -40,4 +50,71 @@ extension EmailActionTypeExtension on EmailActionType {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String? getHeaderEmailQuoted({
|
||||
required BuildContext context,
|
||||
required PresentationEmail presentationEmail
|
||||
}) {
|
||||
final locale = Localizations.localeOf(context).toLanguageTag();
|
||||
switch(this) {
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyAll:
|
||||
final receivedAt = presentationEmail.receivedAt;
|
||||
final emailAddress = presentationEmail.from.listEmailAddressToString(isFullEmailAddress: true);
|
||||
return AppLocalizations.of(context).header_email_quoted(
|
||||
receivedAt.formatDateToLocal(pattern: 'MMM d, y h:mm a', locale: locale),
|
||||
emailAddress
|
||||
);
|
||||
case EmailActionType.forward:
|
||||
var headerQuoted = '------- ${AppLocalizations.of(context).forwarded_message} -------'.addNewLineTag();
|
||||
|
||||
final subject = presentationEmail.subject ?? '';
|
||||
final receivedAt = presentationEmail.receivedAt;
|
||||
final fromEmailAddress = presentationEmail.from.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final toEmailAddress = presentationEmail.to.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final ccEmailAddress = presentationEmail.cc.listEmailAddressToString(isFullEmailAddress: true);
|
||||
final bccEmailAddress = presentationEmail.bcc.listEmailAddressToString(isFullEmailAddress: true);
|
||||
|
||||
if (subject.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).subject_email}: ')
|
||||
.append(subject)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (receivedAt != null) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).date}: ')
|
||||
.append(receivedAt.formatDateToLocal(pattern: 'MMM d, y h:mm a', locale: locale))
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (fromEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).from_email_address_prefix}: ')
|
||||
.append(fromEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (toEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).to_email_address_prefix}: ')
|
||||
.append(toEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (ccEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).cc_email_address_prefix}: ')
|
||||
.append(ccEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
if (bccEmailAddress.isNotEmpty) {
|
||||
headerQuoted = headerQuoted
|
||||
.append('${AppLocalizations.of(context).bcc_email_address_prefix}: ')
|
||||
.append(bccEmailAddress)
|
||||
.addNewLineTag();
|
||||
}
|
||||
|
||||
return headerQuoted;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class ComposerStyle {
|
||||
if (responsiveUtils.isPortraitMobile(context) || responsiveUtils.isLandscapeMobile(context)) {
|
||||
return const EdgeInsetsDirectional.symmetric(horizontal: 16);
|
||||
} else {
|
||||
return const EdgeInsetsDirectional.only(start: 88, end: 48);
|
||||
return const EdgeInsetsDirectional.only(start: 88, end: 48, top: 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user