+
+
$subjectPrefix: $subject
+
+
+
+
+
+
+
+ ${listAttachment?.isNotEmpty == true ? _createAttachmentsElement(listAttachment: listAttachment ?? [], titleAttachment: titleAttachment) : ''}
+ ''');
+ } catch (e) {
+ logError('PreviewEmlFileUtils::_createEmailElement: Exception = $e');
+ return null;
+ }
+ }
+
+ String _createRecipientHtmlTag(String prefix, String emailAddress) {
+ try {
+ return '''
+
+ $prefix: $emailAddress
+
+ ''';
+ } catch (e) {
+ logError('PreviewEmlFileUtils::_createRecipientHtmlTag: Exception = $e');
+ return '';
+ }
+ }
+
+ String _createAttachmentHtmlTag(PrintAttachment printAttachment) {
+ return '''
+
+
+
})
+
+
+
${printAttachment.name}
+
${printAttachment.size}
+
+
+ ''';
+ }
+
+ String _createAttachmentsElement({
+ required String titleAttachment,
+ required List
listAttachment
+ }) {
+ try {
+ return '''
+
+
+
${listAttachment.length} $titleAttachment
+
+
+ ${listAttachment.map((attachment) => _createAttachmentHtmlTag(attachment)).toList().join('\n')}
+
+ ''';
+ } catch (e) {
+ logError('PreviewEmlFileUtils::_createAttachmentsElement: Exception = $e');
+ return '';
+ }
+ }
+
+ String generatePreviewEml({
+ required String appName,
+ required String userName,
+ required String subjectPrefix,
+ required String subject,
+ required String emailContent,
+ required String senderName,
+ required String senderEmailAddress,
+ required String dateTime,
+ required String fromPrefix,
+ required String toPrefix,
+ required String ccPrefix,
+ required String bccPrefix,
+ required String replyToPrefix,
+ required String titleAttachment,
+ required String attachmentIcon,
+ String? toAddress,
+ String? ccAddress,
+ String? bccAddress,
+ String? replyToAddress,
+ List? listAttachment,
+ }) {
+ Document document = parse(HtmlUtils.createTemplateHtmlDocument(title: '$subject - $userName'));
+
+ Element? emailElement = _createEmailElement(
+ subjectPrefix: subjectPrefix,
+ fromPrefix: fromPrefix,
+ toPrefix: toPrefix,
+ ccPrefix: ccPrefix,
+ bccPrefix: bccPrefix,
+ replyToPrefix: replyToPrefix,
+ subject: subject,
+ toAddress: toAddress,
+ ccAddress: ccAddress,
+ bccAddress: bccAddress,
+ replyToAddress: replyToAddress,
+ senderName: senderName,
+ senderEmailAddress: senderEmailAddress,
+ dateTime: dateTime,
+ emailContent: emailContent,
+ attachmentIcon: attachmentIcon,
+ titleAttachment: titleAttachment,
+ listAttachment: listAttachment,
+ );
+
+ Element linkFontElement = Element.html(HtmlTemplate.fontLink);
+ document.head?.append(linkFontElement);
+
+ Element styleElement = Element.html(HtmlTemplate.previewEMLFileCssStyle);
+ document.head?.append(styleElement);
+
+ if (emailElement != null) {
+ document.body?.append(emailElement);
+ }
+
+ final htmlDocument = document.outerHtml;
+
+ return htmlDocument;
+ }
+}
diff --git a/lib/features/caching/exceptions/local_storage_exception.dart b/lib/features/caching/exceptions/local_storage_exception.dart
new file mode 100644
index 000000000..0c8c81cb9
--- /dev/null
+++ b/lib/features/caching/exceptions/local_storage_exception.dart
@@ -0,0 +1 @@
+class NotFoundDataWithThisKeyException implements Exception {}
\ No newline at end of file
diff --git a/lib/features/caching/utils/local_storage_manager.dart b/lib/features/caching/utils/local_storage_manager.dart
new file mode 100644
index 000000000..0ff67c6d6
--- /dev/null
+++ b/lib/features/caching/utils/local_storage_manager.dart
@@ -0,0 +1,27 @@
+
+import 'package:collection/collection.dart';
+import 'package:tmail_ui_user/features/caching/exceptions/local_storage_exception.dart';
+import 'package:universal_html/html.dart' as html;
+
+class LocalStorageManager {
+
+ void save(String key, String value) {
+ html.window.localStorage.addAll({key: value});
+ }
+
+ String get(String key) {
+ final entry = html.window.localStorage
+ .entries
+ .firstWhereOrNull((entry) => entry.key == key);
+
+ if (entry != null) {
+ return entry.value;
+ } else {
+ throw NotFoundDataWithThisKeyException();
+ }
+ }
+
+ void remove(String key) {
+ html.window.localStorage.remove(key);
+ }
+}
\ No newline at end of file
diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart
index 903399479..e2ad10338 100644
--- a/lib/features/composer/presentation/composer_bindings.dart
+++ b/lib/features/composer/presentation/composer_bindings.dart
@@ -2,6 +2,7 @@ import 'package:core/core.dart';
import 'package:core/utils/application_manager.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
+import 'package:tmail_ui_user/features/caching/utils/local_storage_manager.dart';
import 'package:tmail_ui_user/features/composer/data/datasource/composer_datasource.dart';
import 'package:tmail_ui_user/features/composer/data/datasource/contact_datasource.dart';
import 'package:tmail_ui_user/features/composer/data/datasource_impl/composer_datasource_impl.dart';
@@ -24,6 +25,7 @@ import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dar
import 'package:tmail_ui_user/features/email/data/datasource/print_file_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart';
+import 'package:tmail_ui_user/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/print_file_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
@@ -131,6 +133,9 @@ class ComposerBindings extends BaseBindings {
Get.find(),
Get.find(),
Get.find()));
+ Get.lazyPut(() => EmailLocalStorageDataSourceImpl(
+ Get.find(),
+ Get.find()));
Get.lazyPut(() => RemoteServerSettingsDataSourceImpl(
Get.find(),
Get.find()));
@@ -170,7 +175,8 @@ class ComposerBindings extends BaseBindings {
Get.lazyPut(() => EmailRepositoryImpl(
{
DataSourceType.network: Get.find(),
- DataSourceType.hiveCache: Get.find()
+ DataSourceType.hiveCache: Get.find(),
+ DataSourceType.local: Get.find(),
},
Get.find(),
Get.find(),
diff --git a/lib/features/email/data/datasource/email_datasource.dart b/lib/features/email/data/datasource/email_datasource.dart
index 791626a6d..a989e2b1e 100644
--- a/lib/features/email/data/datasource/email_datasource.dart
+++ b/lib/features/email/data/datasource/email_datasource.dart
@@ -24,6 +24,7 @@ import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
@@ -187,4 +188,10 @@ abstract class EmailDataSource {
List emailIds);
Future> parseEmailByBlobIds(AccountId accountId, Set blobIds);
+
+ Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest);
+
+ Future sharePreviewEmailEMLContent(String keyStored, String previewEMLContent);
+
+ Future getPreviewEmailEMLContentShared(String keyStored);
}
\ No newline at end of file
diff --git a/lib/features/email/data/datasource_impl/email_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_datasource_impl.dart
index 15365ac8e..6c89cd042 100644
--- a/lib/features/email/data/datasource_impl/email_datasource_impl.dart
+++ b/lib/features/email/data/datasource_impl/email_datasource_impl.dart
@@ -1,13 +1,23 @@
import 'dart:async';
import 'dart:typed_data';
+import 'package:core/data/model/print_attachment.dart';
import 'package:core/data/network/download/downloaded_response.dart';
+import 'package:core/domain/extensions/datetime_extension.dart';
+import 'package:core/presentation/extensions/html_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
+import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
+import 'package:core/utils/app_logger.dart';
+import 'package:core/utils/file_utils.dart';
+import 'package:core/utils/platform_info.dart';
+import 'package:core/utils/preview_eml_file_utils.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.dart';
+import 'package:filesize/filesize.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
@@ -19,11 +29,14 @@ import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
+import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
+import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
@@ -34,6 +47,10 @@ class EmailDataSourceImpl extends EmailDataSource {
final EmailAPI emailAPI;
final ExceptionThrower _exceptionThrower;
final ExceptionThrower _sendEmailExceptionThrower = Get.find();
+ final PreviewEmlFileUtils _previewEmailUtils = Get.find();
+ final HtmlAnalyzer _htmlAnalyzer = Get.find();
+ final FileUtils _fileUtils = Get.find();
+ final ImagePaths _imagePaths = Get.find();
EmailDataSourceImpl(this.emailAPI, this._exceptionThrower);
@@ -385,4 +402,125 @@ class EmailDataSourceImpl extends EmailDataSource {
return await emailAPI.parseEmailByBlobIds(accountId, blobIds);
}).catchError(_exceptionThrower.throwException);
}
+
+ @override
+ Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest) {
+ return Future.sync(() async {
+ final email = previewEmailEMLRequest.email;
+ final appLocalizations = previewEmailEMLRequest.appLocalizations;
+ final locale = previewEmailEMLRequest.locale.toLanguageTag();
+
+ final listAttachments = email
+ .allAttachments
+ .getListAttachmentsDisplayedOutside(email.htmlBodyAttachments);
+
+ final listInlineImages = email
+ .allAttachments
+ .listAttachmentsDisplayedInContent;
+
+ final mapCidImageDownloadUrl = listInlineImages.toMapCidImageDownloadUrl(
+ accountId: previewEmailEMLRequest.accountId,
+ downloadUrl: previewEmailEMLRequest.baseDownloadUrl,
+ );
+
+ final emailContentEscaped = await _transformEmailContent(
+ email.emailContentList,
+ mapCidImageDownloadUrl,
+ );
+
+ final sender = email.from?.isNotEmpty == true
+ ? email.from!.first
+ : null;
+
+ final receiveTime = email.getReceivedAt(
+ newLocale: locale,
+ pattern: email.receivedAt?.value.toLocal().toPatternForPrinting(locale)
+ );
+
+ final sentTime = email.getSentAt(
+ newLocale: locale,
+ pattern: email.sentAt?.value.toLocal().toPatternForPrinting(locale)
+ );
+
+ final List listPrintAttachment = [];
+
+ if (listAttachments.isNotEmpty) {
+ await Future.forEach(listAttachments, (attachment) async {
+ final iconBase64Data = await _fileUtils.convertImageAssetToBase64(
+ attachment.getIcon(_imagePaths));
+
+ final printAttachment = PrintAttachment(
+ iconBase64Data: iconBase64Data,
+ name: attachment.name.escapeLtGtHtmlString(),
+ size: filesize(attachment.size?.value),
+ );
+
+ listPrintAttachment.add(printAttachment);
+ });
+ }
+
+ final attachmentIconBase64Data = email.hasAttachment == true
+ ? await _fileUtils.convertImageAssetToBase64(_imagePaths.icAttachment)
+ : '';
+
+ final previewEmlHtmlDocument = _previewEmailUtils.generatePreviewEml(
+ appName: appLocalizations.app_name,
+ userName: previewEmailEMLRequest.userName.value,
+ subjectPrefix: appLocalizations.subject,
+ subject: previewEmailEMLRequest.email.subject?.escapeLtGtHtmlString() ?? '',
+ emailContent: emailContentEscaped,
+ senderName: sender?.name.escapeLtGtHtmlString() ?? '',
+ senderEmailAddress: sender?.email ?? '',
+ dateTime: receiveTime.isNotEmpty ? receiveTime : sentTime,
+ fromPrefix: appLocalizations.from_email_address_prefix,
+ toPrefix: appLocalizations.to_email_address_prefix,
+ ccPrefix: appLocalizations.cc_email_address_prefix,
+ bccPrefix: appLocalizations.bcc_email_address_prefix,
+ replyToPrefix: appLocalizations.replyToEmailAddressPrefix,
+ titleAttachment: appLocalizations.attachments.toLowerCase(),
+ attachmentIcon: attachmentIconBase64Data,
+ toAddress: email.to?.listEmailAddressToString(isFullEmailAddress: true),
+ ccAddress: email.cc?.listEmailAddressToString(isFullEmailAddress: true),
+ bccAddress: email.bcc?.listEmailAddressToString(isFullEmailAddress: true),
+ replyToAddress: email.replyTo?.listEmailAddressToString(isFullEmailAddress: true),
+ listAttachment: listPrintAttachment,
+ );
+
+ return previewEmlHtmlDocument;
+ }).catchError(_exceptionThrower.throwException);
+ }
+
+ Future _transformEmailContent(
+ List emailContents,
+ Map mapCidImageDownloadUrl,
+ ) async {
+ try {
+ final transformConfiguration = PlatformInfo.isWeb
+ ? TransformConfiguration.forPreviewEmailOnWeb()
+ : TransformConfiguration.forPreviewEmail();
+
+ final listEmailContent = await Future.wait(emailContents
+ .map((emailContent) async => await _htmlAnalyzer.transformEmailContent(
+ emailContent,
+ mapCidImageDownloadUrl,
+ transformConfiguration,
+ ))
+ .toList());
+
+ return listEmailContent.asHtmlString;
+ } catch (e) {
+ logError('EmailDataSourceImpl::_transformEmailContent:Exception = $e');
+ return '';
+ }
+ }
+
+ @override
+ Future sharePreviewEmailEMLContent(String keyStored, String previewEMLContent) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getPreviewEmailEMLContentShared(String keyStored) {
+ throw UnimplementedError();
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart
index f142c9af6..fe38c8ed6 100644
--- a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart
+++ b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart
@@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/email/domain/extensions/detailed_email_hi
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/offline_mode/extensions/list_sending_email_hive_cache_extension.dart';
@@ -531,4 +532,19 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource {
Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) {
throw UnimplementedError();
}
+
+ @override
+ Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future sharePreviewEmailEMLContent(String keyStored, String previewEMLContent) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getPreviewEmailEMLContentShared(String keyStored) {
+ throw UnimplementedError();
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart
new file mode 100644
index 000000000..bdea0f469
--- /dev/null
+++ b/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart
@@ -0,0 +1,224 @@
+
+import 'dart:async';
+import 'dart:typed_data';
+
+import 'package:core/data/network/download/downloaded_response.dart';
+import 'package:core/presentation/state/failure.dart';
+import 'package:core/presentation/state/success.dart';
+import 'package:dartz/dartz.dart';
+import 'package:dio/dio.dart';
+import 'package:email_recovery/email_recovery/email_recovery_action.dart';
+import 'package:email_recovery/email_recovery/email_recovery_action_id.dart';
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
+import 'package:jmap_dart_client/jmap/core/id.dart';
+import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
+import 'package:jmap_dart_client/jmap/core/session/session.dart';
+import 'package:jmap_dart_client/jmap/core/user_name.dart';
+import 'package:jmap_dart_client/jmap/mail/email/email.dart';
+import 'package:model/account/account_request.dart';
+import 'package:model/download/download_task_id.dart';
+import 'package:model/email/attachment.dart';
+import 'package:model/email/mark_star_action.dart';
+import 'package:model/email/read_actions.dart';
+import 'package:tmail_ui_user/features/caching/utils/local_storage_manager.dart';
+import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
+import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
+import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
+import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
+import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
+import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
+import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
+
+class EmailLocalStorageDataSourceImpl extends EmailDataSource {
+
+ final LocalStorageManager _localStorageManager;
+ final ExceptionThrower _exceptionThrower;
+
+ EmailLocalStorageDataSourceImpl(
+ this._localStorageManager,
+ this._exceptionThrower,
+ );
+
+ @override
+ Future deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId, {CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future<({List emailIdsSuccess, Map mapErrors})> deleteMultipleEmailsPermanently(Session session, AccountId accountId, List emailIds) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future deleteMultipleSendingEmail(AccountId accountId, UserName userName, List sendingIds) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future deleteSendingEmail(AccountId accountId, UserName userName, String sendingId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future downloadAttachmentForWeb(DownloadTaskId taskId, Attachment attachment, AccountId accountId, String baseDownloadUrl, AccountRequest accountRequest, StreamController> onReceiveController, {CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future> downloadAttachments(List attachments, AccountId accountId, String baseDownloadUrl, AccountRequest accountRequest) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future exportAttachment(Attachment attachment, AccountId accountId, String baseDownloadUrl, AccountRequest accountRequest, CancelToken cancelToken) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future> getAllSendingEmails(AccountId accountId, UserName userName) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getDetailedEmailById(Session session, AccountId accountId, EmailId emailId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getEmailContent(Session session, AccountId accountId, EmailId emailId, {Properties? additionalProperties}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getRestoredDeletedMessage(EmailRecoveryActionId emailRecoveryActionId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getStoredEmail(Session session, AccountId accountId, EmailId emailId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getStoredNewEmail(Session session, AccountId accountId, EmailId emailId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getStoredOpenedEmail(Session session, AccountId accountId, EmailId emailId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getStoredSendingEmail(AccountId accountId, UserName userName, String sendingId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future<({List emailIdsSuccess, Map mapErrors})> markAsRead(Session session, AccountId accountId, List emailIds, ReadActions readActions) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future<({List emailIdsSuccess, Map mapErrors})> markAsStar(Session session, AccountId accountId, List emailIds, MarkStarAction markStarAction) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future<({List emailIdsSuccess, Map mapErrors})> moveToMailbox(Session session, AccountId accountId, MoveToMailboxRequest moveRequest) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future removeEmailDrafts(Session session, AccountId accountId, EmailId emailId, {CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future restoreDeletedMessage(RestoredDeletedMessageRequest restoredDeletedMessageRequest) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future saveEmailAsDrafts(Session session, AccountId accountId, Email email, {CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future sendEmail(Session session, AccountId accountId, EmailRequest emailRequest, {CreateNewMailboxRequest? mailboxRequest, CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future sharePreviewEmailEMLContent(String keyStored, String previewEMLContent) {
+ return Future.sync(() async {
+ return _localStorageManager.save(keyStored, previewEMLContent);
+ }).catchError(_exceptionThrower.throwException);
+ }
+
+ @override
+ Future storeDetailedNewEmail(Session session, AccountId accountId, DetailedEmail detailedEmail) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future storeEmail(Session session, AccountId accountId, Email email) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future storeEventAttendanceStatus(Session session, AccountId accountId, EmailId emailId, EventActionType eventActionType) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future storeOpenedEmail(Session session, AccountId accountId, DetailedEmail detailedEmail) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future storeSendingEmail(AccountId accountId, UserName userName, SendingEmail sendingEmail) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future unsubscribeMail(Session session, AccountId accountId, EmailId emailId) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future updateEmailDrafts(Session session, AccountId accountId, Email newEmail, EmailId oldEmailId, {CancelToken? cancelToken}) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future> updateMultipleSendingEmail(AccountId accountId, UserName userName, List newSendingEmails) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future updateSendingEmail(AccountId accountId, UserName userName, SendingEmail newSendingEmail) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Future getPreviewEmailEMLContentShared(String keyStored) {
+ return Future.sync(() async {
+ return _localStorageManager.get(keyStored);
+ }).catchError(_exceptionThrower.throwException);
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart
index 9b0d2172c..d851fd5b2 100644
--- a/lib/features/email/data/network/email_api.dart
+++ b/lib/features/email/data/network/email_api.dart
@@ -902,7 +902,9 @@ class EmailAPI with HandleSetErrorMixin {
Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) async {
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
- final parseEmailMethod = ParseEmailMethod(accountId, blobIds);
+ final parseEmailMethod = ParseEmailMethod(accountId, blobIds)
+ ..addProperties(ThreadConstants.propertiesParseEmailByBlobId)
+ ..addFetchHTMLBodyValues(true);
final parseEmailInvocation = requestBuilder.invocation(parseEmailMethod);
final response = await (requestBuilder
diff --git a/lib/features/email/data/repository/email_repository_impl.dart b/lib/features/email/data/repository/email_repository_impl.dart
index 263814227..1cbc92f9a 100644
--- a/lib/features/email/data/repository/email_repository_impl.dart
+++ b/lib/features/email/data/repository/email_repository_impl.dart
@@ -32,6 +32,7 @@ import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/email_print.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
+import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
@@ -486,6 +487,21 @@ class EmailRepositoryImpl extends EmailRepository {
@override
Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) {
- throw UnimplementedError();
+ return emailDataSource[DataSourceType.network]!.parseEmailByBlobIds(accountId, blobIds);
+ }
+
+ @override
+ Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest) {
+ return emailDataSource[DataSourceType.network]!.generatePreviewEmailEMLContent(previewEmailEMLRequest);
+ }
+
+ @override
+ Future sharePreviewEmailEMLContent(String keyStored, String previewEMLContent) {
+ return emailDataSource[DataSourceType.local]!.sharePreviewEmailEMLContent(keyStored, previewEMLContent);
+ }
+
+ @override
+ Future getPreviewEmailEMLContentShared(String keyStored) {
+ return emailDataSource[DataSourceType.local]!.getPreviewEmailEMLContentShared(keyStored);
}
}
\ No newline at end of file
diff --git a/lib/features/email/domain/model/preview_email_eml_request.dart b/lib/features/email/domain/model/preview_email_eml_request.dart
new file mode 100644
index 000000000..e790b3211
--- /dev/null
+++ b/lib/features/email/domain/model/preview_email_eml_request.dart
@@ -0,0 +1,40 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:jmap_dart_client/jmap/core/id.dart';
+import 'package:jmap_dart_client/jmap/core/user_name.dart';
+import 'package:jmap_dart_client/jmap/mail/email/email.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class PreviewEmailEMLRequest with EquatableMixin {
+ final AccountId accountId;
+ final UserName userName;
+ final Id blobId;
+ final Email email;
+ final Locale locale;
+ final AppLocalizations appLocalizations;
+ final String baseDownloadUrl;
+
+ PreviewEmailEMLRequest({
+ required this.accountId,
+ required this.userName,
+ required this.blobId,
+ required this.email,
+ required this.locale,
+ required this.appLocalizations,
+ required this.baseDownloadUrl,
+ });
+
+ String get keyStored => blobId.value;
+
+ @override
+ List