TF-3035 Restore identity from draft

This commit is contained in:
DatDang
2024-09-05 16:46:28 +07:00
committed by Dat H. Pham
parent fd78f327b7
commit 82a49c5923
21 changed files with 199 additions and 49 deletions
@@ -0,0 +1,26 @@
import 'package:core/data/network/dio_client.dart';
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
import 'package:html/dom.dart';
class HideDraftSignatureTransformer extends DomTransformer {
const HideDraftSignatureTransformer();
@override
Future<void> process({
required Document document,
required DioClient dioClient,
Map<String, String>? mapUrlDownloadCID
}) async {
final signature = document.querySelector('div.tmail-signature');
if (signature == null) return;
final currentStyle = signature.attributes['style']?.trim();
if (currentStyle == null) {
signature.attributes['style'] = 'display: none;';
} else if (currentStyle.endsWith(';')) {
signature.attributes['style'] = '$currentStyle display: none;';
} else {
signature.attributes['style'] = '$currentStyle; display: none;';
}
}
}
@@ -6,6 +6,7 @@ import 'package:core/presentation/utils/html_transformer/dom/add_target_blank_in
import 'package:core/presentation/utils/html_transformer/dom/add_tooltip_link_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/add_tooltip_link_transformers.dart';
import 'package:core/presentation/utils/html_transformer/dom/blockcode_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/blockcode_transformers.dart';
import 'package:core/presentation/utils/html_transformer/dom/blockquoted_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/blockquoted_transformers.dart';
import 'package:core/presentation/utils/html_transformer/dom/hide_draft_signature_transformer.dart';
import 'package:core/presentation/utils/html_transformer/dom/image_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/image_transformers.dart';
import 'package:core/presentation/utils/html_transformer/dom/remove_collapsed_signature_button_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_collapsed_signature_button_transformers.dart';
import 'package:core/presentation/utils/html_transformer/dom/remove_lazy_loading_for_background_image_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_lazy_loading_for_background_image_transformers.dart';
@@ -47,6 +48,9 @@ class TransformConfiguration {
]); ]);
factory TransformConfiguration.forDraftsEmail() => TransformConfiguration.fromDomTransformers([const ImageTransformer()]); factory TransformConfiguration.forDraftsEmail() => TransformConfiguration.fromDomTransformers([const ImageTransformer()]);
factory TransformConfiguration.forEditDraftsEmail() => TransformConfiguration.fromDomTransformers([
...TransformConfiguration.forDraftsEmail().domTransformers,
const HideDraftSignatureTransformer()]);
factory TransformConfiguration.forPreviewEmailOnWeb() => TransformConfiguration.create( factory TransformConfiguration.forPreviewEmailOnWeb() => TransformConfiguration.create(
customDomTransformers: [ customDomTransformers: [
@@ -44,7 +44,10 @@ class ComposerRepositoryImpl extends ComposerRepository {
} }
@override @override
Future<Email> generateEmail(CreateEmailRequest createEmailRequest) async { Future<Email> generateEmail(
CreateEmailRequest createEmailRequest,
{bool withIdentityHeader = false}
) async {
String emailContent = createEmailRequest.emailContent; String emailContent = createEmailRequest.emailContent;
Set<EmailBodyPart> emailAttachments = Set.from(createEmailRequest.createAttachments()); Set<EmailBodyPart> emailAttachments = Set.from(createEmailRequest.createAttachments());
@@ -69,7 +72,8 @@ class ComposerRepositoryImpl extends ComposerRepository {
newEmailContent: emailContent, newEmailContent: emailContent,
newEmailAttachments: emailAttachments, newEmailAttachments: emailAttachments,
userAgent: userAgent, userAgent: userAgent,
partId: emailBodyPartId partId: emailBodyPartId,
withIdentityHeader: withIdentityHeader,
); );
return emailObject; return emailObject;
@@ -5,7 +5,9 @@ import 'package:tmail_ui_user/features/composer/presentation/model/create_email_
import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart'; import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart';
abstract class ComposerRepository { abstract class ComposerRepository {
Future<Email> generateEmail(CreateEmailRequest createEmailRequest); Future<Email> generateEmail(
CreateEmailRequest createEmailRequest,
{bool withIdentityHeader = false});
Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken}); Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken});
@@ -103,7 +103,9 @@ class CreateNewAndSaveEmailToDraftsInteractor {
Future<Email?> _createEmailObject(CreateEmailRequest createEmailRequest) async { Future<Email?> _createEmailObject(CreateEmailRequest createEmailRequest) async {
try { try {
final emailCreated = await _composerRepository.generateEmail(createEmailRequest); final emailCreated = await _composerRepository.generateEmail(
createEmailRequest,
withIdentityHeader: true);
return emailCreated; return emailCreated;
} catch (e) { } catch (e) {
logError('CreateNewAndSaveEmailToDraftsInteractor::_createEmailObject: Exception: $e'); logError('CreateNewAndSaveEmailToDraftsInteractor::_createEmailObject: Exception: $e');
@@ -24,13 +24,14 @@ class SaveComposerCacheOnWebInteractor {
UserName userName, UserName userName,
) async { ) async {
try { try {
final emailCreated = await _composerRepository.generateEmail(createEmailRequest); final emailCreated = await _composerRepository.generateEmail(
createEmailRequest,
withIdentityHeader: true);
await _composerCacheRepository.saveComposerCacheOnWeb( await _composerCacheRepository.saveComposerCacheOnWeb(
accountId: accountId, accountId: accountId,
userName: userName, userName: userName,
composerCache: ComposerCache( composerCache: ComposerCache(
email: emailCreated, email: emailCreated,
identity: createEmailRequest.identity,
hasRequestReadReceipt: createEmailRequest.hasRequestReadReceipt, hasRequestReadReceipt: createEmailRequest.hasRequestReadReceipt,
displayMode: createEmailRequest.displayMode displayMode: createEmailRequest.displayMode
)); ));
@@ -17,9 +17,11 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart'; import 'package:html_editor_enhanced/html_editor.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
@@ -58,6 +60,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/list_sha
import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/signature_status.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
@@ -191,6 +194,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
ButtonState _closeComposerButtonState = ButtonState.enabled; ButtonState _closeComposerButtonState = ButtonState.enabled;
ButtonState _saveToDraftButtonState = ButtonState.enabled; ButtonState _saveToDraftButtonState = ButtonState.enabled;
ButtonState _sendButtonState = ButtonState.enabled; ButtonState _sendButtonState = ButtonState.enabled;
SignatureStatus _identityContentOnOpenPolicy = SignatureStatus.editedAvailable;
late Worker uploadInlineImageWorker; late Worker uploadInlineImageWorker;
late Worker dashboardViewStateWorker; late Worker dashboardViewStateWorker;
@@ -258,6 +262,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
} else { } else {
richTextMobileTabletController = null; richTextMobileTabletController = null;
} }
_identityContentOnOpenPolicy = SignatureStatus.editedAvailable;
super.onClose(); super.onClose();
} }
@@ -716,14 +721,21 @@ class ComposerController extends BaseController with DragDropFileMixin implement
} }
} }
Identity? _selectIdentityFromId(IdentityId? identityId) {
if (identityId == null) return null;
return listFromIdentities.firstWhereOrNull(
(identity) => identity.id == identityId);
}
void _initIdentities(ComposerArguments composerArguments) { void _initIdentities(ComposerArguments composerArguments) {
listFromIdentities.value = composerArguments.identities ?? []; listFromIdentities.value = composerArguments.identities ?? [];
final selectedIdentityFromId = _selectIdentityFromId(
composerArguments.selectedIdentityId);
if (listFromIdentities.isEmpty) { if (listFromIdentities.isEmpty) {
_getAllIdentities(); _getAllIdentities();
} else if (composerArguments.selectedIdentity != null } else if (selectedIdentityFromId != null) {
&& listFromIdentities.contains(composerArguments.selectedIdentity!) _selectIdentity(selectedIdentityFromId);
) {
_selectIdentity(composerArguments.selectedIdentity!);
} else if (composerArguments.identities?.isNotEmpty == true) { } else if (composerArguments.identities?.isNotEmpty == true) {
_selectIdentity(composerArguments.identities!.first); _selectIdentity(composerArguments.identities!.first);
} }
@@ -744,11 +756,10 @@ class ComposerController extends BaseController with DragDropFileMixin implement
listFromIdentities.value = listIdentitiesMayDeleted; listFromIdentities.value = listIdentitiesMayDeleted;
if (identitySelected.value == null) { if (identitySelected.value == null) {
final selectedIdentityFromArguments = composerArguments.value?.selectedIdentity; final selectedIdentityFromId = _selectIdentityFromId(
if (selectedIdentityFromArguments != null composerArguments.value?.selectedIdentityId);
&& listFromIdentities.contains(selectedIdentityFromArguments) if (selectedIdentityFromId != null) {
) { await _selectIdentity(selectedIdentityFromId);
await _selectIdentity(selectedIdentityFromArguments);
} else { } else {
await _selectIdentity(listIdentitiesMayDeleted.firstOrNull); await _selectIdentity(listIdentitiesMayDeleted.firstOrNull);
} }
@@ -1389,7 +1400,9 @@ class ComposerController extends BaseController with DragDropFileMixin implement
accountId, accountId,
emailId, emailId,
mailboxDashBoardController.baseDownloadUrl, mailboxDashBoardController.baseDownloadUrl,
TransformConfiguration.forDraftsEmail() TransformConfiguration.forEditDraftsEmail(),
additionalProperties: Properties({
IndividualHeaderIdentifier.identityHeader.value}),
)); ));
} }
@@ -1412,9 +1425,18 @@ class ComposerController extends BaseController with DragDropFileMixin implement
if (composerArguments.value?.emailActionType == EmailActionType.editDraft) { if (composerArguments.value?.emailActionType == EmailActionType.editDraft) {
_setUpRequestReadReceiptForDraftEmail(success.emailCurrent); _setUpRequestReadReceiptForDraftEmail(success.emailCurrent);
_restoreIdentityFromHeader(success.emailCurrent);
} }
} }
void _restoreIdentityFromHeader(Email? email) {
final identityIdFromHeader = email?.identityIdFromHeader;
if (identityIdFromHeader == null) return;
final selectedIdentityFromHeader = _selectIdentityFromId(identityIdFromHeader);
if (selectedIdentityFromHeader == null) return;
identitySelected.value = selectedIdentityFromHeader;
}
void _transformHtmlEmailContent(String? emailContent) { void _transformHtmlEmailContent(String? emailContent) {
emailContentsViewState(Right(TransformHtmlEmailContentLoading())); emailContentsViewState(Right(TransformHtmlEmailContentLoading()));
if (emailContent?.isEmpty == true) { if (emailContent?.isEmpty == true) {
@@ -1662,11 +1684,18 @@ class ComposerController extends BaseController with DragDropFileMixin implement
identitySelected.value = newIdentity; identitySelected.value = newIdentity;
if (newIdentity == null) return; if (newIdentity == null) return;
if (composerArguments.value?.emailActionType == EmailActionType.reopenComposerBrowser) { final emailActionType = composerArguments.value?.emailActionType;
composerArguments.value = composerArguments.value?.copyWith( switch (emailActionType) {
emailActionType: EmailActionType.editDraft); case EmailActionType.reopenComposerBrowser:
} else { case EmailActionType.editDraft:
await _applyIdentityForAllFieldComposer(formerIdentity, newIdentity); if (_identityContentOnOpenPolicy == SignatureStatus.editedAvailable) {
_identityContentOnOpenPolicy = SignatureStatus.editedApplied;
} else {
await _applyIdentityForAllFieldComposer(formerIdentity, newIdentity);
}
break;
default:
await _applyIdentityForAllFieldComposer(formerIdentity, newIdentity);
} }
} }
@@ -1891,7 +1920,9 @@ class ComposerController extends BaseController with DragDropFileMixin implement
if (identitySelected.value == null) { if (identitySelected.value == null) {
_getAllIdentities(); _getAllIdentities();
} else { } else {
await _selectIdentity(identitySelected.value); if (composerArguments.value?.emailActionType != EmailActionType.editDraft) {
await _selectIdentity(identitySelected.value);
}
_autoFocusFieldWhenLauncher(); _autoFocusFieldWhenLauncher();
} }
} }
@@ -105,6 +105,7 @@ extension CreateEmailRequestExtension on CreateEmailRequest {
required Set<EmailBodyPart> newEmailAttachments, required Set<EmailBodyPart> newEmailAttachments,
required String userAgent, required String userAgent,
required PartId partId, required PartId partId,
bool withIdentityHeader = false,
}) { }) {
return Email( return Email(
mailboxIds: createMailboxIds(), mailboxIds: createMailboxIds(),
@@ -145,6 +146,9 @@ extension CreateEmailRequestExtension on CreateEmailRequest {
headerMdn: hasRequestReadReceipt headerMdn: hasRequestReadReceipt
? { IndividualHeaderIdentifier.headerMdn: createMdnEmailAddress() } ? { IndividualHeaderIdentifier.headerMdn: createMdnEmailAddress() }
: null, : null,
identityHeader: withIdentityHeader
? {IndividualHeaderIdentifier.identityHeader: identity?.id?.id.value}
: null
); );
} }
@@ -0,0 +1,4 @@
enum SignatureStatus {
editedAvailable,
editedApplied,
}
@@ -9,6 +9,7 @@ import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart'; import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.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/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -26,7 +27,11 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_r
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
abstract class EmailDataSource { abstract class EmailDataSource {
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId); Future<Email> getEmailContent(
Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties});
Future<void> sendEmail( Future<void> sendEmail(
Session session, Session session,
@@ -10,6 +10,7 @@ import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.dart'; import 'package:email_recovery/email_recovery/email_recovery_action_id.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -35,9 +36,18 @@ class EmailDataSourceImpl extends EmailDataSource {
EmailDataSourceImpl(this.emailAPI, this._exceptionThrower); EmailDataSourceImpl(this.emailAPI, this._exceptionThrower);
@override @override
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId) { Future<Email> getEmailContent(
Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties}
) {
return Future.sync(() async { return Future.sync(() async {
return await emailAPI.getEmailContent(session, accountId, emailId); return await emailAPI.getEmailContent(
session,
accountId,
emailId,
additionalProperties: additionalProperties);
}).catchError(_exceptionThrower.throwException); }).catchError(_exceptionThrower.throwException);
} }
@@ -12,6 +12,7 @@ import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart'; import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.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/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -109,7 +110,12 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource {
} }
@override @override
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId) { Future<Email> getEmailContent(
Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties}
) {
throw UnimplementedError(); throw UnimplementedError();
} }
@@ -81,7 +81,12 @@ class EmailAPI with HandleSetErrorMixin {
EmailAPI(this._httpClient, this._downloadManager, this._dioClient, this._uuid); EmailAPI(this._httpClient, this._downloadManager, this._dioClient, this._uuid);
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId) async { Future<Email> getEmailContent(
Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties}
) async {
final processingInvocation = ProcessingInvocation(); final processingInvocation = ProcessingInvocation();
final jmapRequestBuilder = JmapRequestBuilder(_httpClient, processingInvocation); final jmapRequestBuilder = JmapRequestBuilder(_httpClient, processingInvocation);
@@ -90,6 +95,9 @@ class EmailAPI with HandleSetErrorMixin {
..addIds({emailId.id}) ..addIds({emailId.id})
..addProperties(ThreadConstants.propertiesGetEmailContent) ..addProperties(ThreadConstants.propertiesGetEmailContent)
..addFetchHTMLBodyValues(true); ..addFetchHTMLBodyValues(true);
if (additionalProperties != null) {
getEmailMethod.addProperties(additionalProperties);
}
final getEmailInvocation = jmapRequestBuilder.invocation(getEmailMethod); final getEmailInvocation = jmapRequestBuilder.invocation(getEmailMethod);
@@ -11,6 +11,7 @@ import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart'; import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.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/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -49,8 +50,17 @@ class EmailRepositoryImpl extends EmailRepository {
); );
@override @override
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId) { Future<Email> getEmailContent(
return emailDataSource[DataSourceType.network]!.getEmailContent(session ,accountId, emailId); Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties}
) {
return emailDataSource[DataSourceType.network]!.getEmailContent(
session,
accountId,
emailId,
additionalProperties: additionalProperties);
} }
@override @override
@@ -10,6 +10,7 @@ import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart'; import 'package:email_recovery/email_recovery/email_recovery_action.dart';
import 'package:email_recovery/email_recovery/email_recovery_action_id.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/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -28,7 +29,11 @@ import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_messag
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
abstract class EmailRepository { abstract class EmailRepository {
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId); Future<Email> getEmailContent(
Session session,
AccountId accountId,
EmailId emailId,
{Properties? additionalProperties});
Future<void> sendEmail( Future<void> sendEmail(
Session session, Session session,
@@ -6,6 +6,7 @@ import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_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/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
@@ -23,14 +24,27 @@ class GetEmailContentInteractor {
EmailId emailId, EmailId emailId,
String baseDownloadUrl, String baseDownloadUrl,
TransformConfiguration transformConfiguration, TransformConfiguration transformConfiguration,
{Properties? additionalProperties}
) async* { ) async* {
try { try {
yield Right<Failure, Success>(GetEmailContentLoading()); yield Right<Failure, Success>(GetEmailContentLoading());
if (PlatformInfo.isMobile) { if (PlatformInfo.isMobile) {
yield* _getStoredOpenedEmail(session, accountId, emailId, baseDownloadUrl, transformConfiguration); yield* _getStoredOpenedEmail(
session,
accountId,
emailId,
baseDownloadUrl,
transformConfiguration,
additionalProperties: additionalProperties);
} else { } else {
yield* _getContentEmailFromServer(session, accountId, emailId, baseDownloadUrl, transformConfiguration); yield* _getContentEmailFromServer(
session,
accountId,
emailId,
baseDownloadUrl,
transformConfiguration,
additionalProperties: additionalProperties);
} }
} catch (e) { } catch (e) {
log('GetEmailContentInteractor::execute(): exception = $e'); log('GetEmailContentInteractor::execute(): exception = $e');
@@ -44,9 +58,14 @@ class GetEmailContentInteractor {
EmailId emailId, EmailId emailId,
String baseDownloadUrl, String baseDownloadUrl,
TransformConfiguration transformConfiguration, TransformConfiguration transformConfiguration,
{Properties? additionalProperties}
) async* { ) async* {
try { try {
final email = await emailRepository.getEmailContent(session, accountId, emailId); final email = await emailRepository.getEmailContent(
session,
accountId,
emailId,
additionalProperties: additionalProperties);
final listAttachments = email.allAttachments.getListAttachmentsDisplayedOutside(email.htmlBodyAttachments); final listAttachments = email.allAttachments.getListAttachmentsDisplayedOutside(email.htmlBodyAttachments);
final listInlineImages = email.allAttachments.listAttachmentsDisplayedInContent; final listInlineImages = email.allAttachments.listAttachmentsDisplayedInContent;
@@ -87,6 +106,7 @@ class GetEmailContentInteractor {
EmailId emailId, EmailId emailId,
String baseDownloadUrl, String baseDownloadUrl,
TransformConfiguration transformConfiguration, TransformConfiguration transformConfiguration,
{Properties? additionalProperties}
) async* { ) async* {
try { try {
log('GetEmailContentInteractor::_getStoredOpenedEmail(): CALLED'); log('GetEmailContentInteractor::_getStoredOpenedEmail(): CALLED');
@@ -109,7 +129,8 @@ class GetEmailContentInteractor {
accountId, accountId,
emailId, emailId,
baseDownloadUrl, baseDownloadUrl,
transformConfiguration transformConfiguration,
additionalProperties: additionalProperties
); );
} }
} }
@@ -120,6 +141,7 @@ class GetEmailContentInteractor {
EmailId emailId, EmailId emailId,
String baseDownloadUrl, String baseDownloadUrl,
TransformConfiguration transformConfiguration, TransformConfiguration transformConfiguration,
{Properties? additionalProperties}
) async* { ) async* {
try { try {
log('GetEmailContentInteractor::_getStoredNewEmail():CALLED'); log('GetEmailContentInteractor::_getStoredNewEmail():CALLED');
@@ -142,7 +164,8 @@ class GetEmailContentInteractor {
accountId, accountId,
emailId, emailId,
baseDownloadUrl, baseDownloadUrl,
transformConfiguration transformConfiguration,
additionalProperties: additionalProperties
); );
} }
} }
@@ -3,10 +3,10 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
extension ComposerArgumentsExtension on ComposerArguments { extension ComposerArgumentsExtension on ComposerArguments {
ComposerArguments withIdentity({List<Identity>? identities, Identity? selectedIdentity}) { ComposerArguments withIdentity({List<Identity>? identities, IdentityId? selectedIdentityId}) {
return copyWith( return copyWith(
identities: identities, identities: identities,
selectedIdentity: selectedIdentity, selectedIdentityId: selectedIdentityId,
); );
} }
} }
@@ -26,7 +26,7 @@ class ComposerArguments extends RouterArguments {
final MessageIdsHeaderValue? references; final MessageIdsHeaderValue? references;
final EmailId? previousEmailId; final EmailId? previousEmailId;
final List<Identity>? identities; final List<Identity>? identities;
final Identity? selectedIdentity; final IdentityId? selectedIdentityId;
final List<Attachment>? inlineImages; final List<Attachment>? inlineImages;
final bool? hasRequestReadReceipt; final bool? hasRequestReadReceipt;
final ScreenDisplayMode displayMode; final ScreenDisplayMode displayMode;
@@ -46,7 +46,7 @@ class ComposerArguments extends RouterArguments {
this.references, this.references,
this.previousEmailId, this.previousEmailId,
this.identities, this.identities,
this.selectedIdentity, this.selectedIdentityId,
this.inlineImages, this.inlineImages,
this.hasRequestReadReceipt, this.hasRequestReadReceipt,
this.displayMode = ScreenDisplayMode.normal this.displayMode = ScreenDisplayMode.normal
@@ -87,7 +87,7 @@ class ComposerArguments extends RouterArguments {
factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) => factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) =>
ComposerArguments( ComposerArguments(
emailActionType: EmailActionType.editDraft, emailActionType: EmailActionType.editDraft,
presentationEmail: presentationEmail presentationEmail: presentationEmail,
); );
factory ComposerArguments.fromSessionStorageBrowser(ComposerCache composerCache) => factory ComposerArguments.fromSessionStorageBrowser(ComposerCache composerCache) =>
@@ -96,7 +96,7 @@ class ComposerArguments extends RouterArguments {
presentationEmail: composerCache.email?.toPresentationEmail(), presentationEmail: composerCache.email?.toPresentationEmail(),
emailContents: composerCache.email?.emailContentList.asHtmlString, emailContents: composerCache.email?.emailContentList.asHtmlString,
attachments: composerCache.email?.allAttachments.getListAttachmentsDisplayedOutside(composerCache.email?.htmlBodyAttachments ?? []), attachments: composerCache.email?.allAttachments.getListAttachmentsDisplayedOutside(composerCache.email?.htmlBodyAttachments ?? []),
selectedIdentity: composerCache.identity, selectedIdentityId: composerCache.email?.identityIdFromHeader,
inlineImages: composerCache.email?.allAttachments.listAttachmentsDisplayedInContent, inlineImages: composerCache.email?.allAttachments.listAttachmentsDisplayedInContent,
hasRequestReadReceipt: composerCache.hasRequestReadReceipt, hasRequestReadReceipt: composerCache.hasRequestReadReceipt,
displayMode: composerCache.displayMode, displayMode: composerCache.displayMode,
@@ -189,7 +189,7 @@ class ComposerArguments extends RouterArguments {
references, references,
previousEmailId, previousEmailId,
identities, identities,
selectedIdentity, selectedIdentityId,
inlineImages, inlineImages,
hasRequestReadReceipt, hasRequestReadReceipt,
displayMode, displayMode,
@@ -210,7 +210,7 @@ class ComposerArguments extends RouterArguments {
MessageIdsHeaderValue? references, MessageIdsHeaderValue? references,
EmailId? previousEmailId, EmailId? previousEmailId,
List<Identity>? identities, List<Identity>? identities,
Identity? selectedIdentity, IdentityId? selectedIdentityId,
List<Attachment>? inlineImages, List<Attachment>? inlineImages,
bool? hasRequestReadReceipt, bool? hasRequestReadReceipt,
ScreenDisplayMode? displayMode, ScreenDisplayMode? displayMode,
@@ -230,7 +230,7 @@ class ComposerArguments extends RouterArguments {
references: references ?? this.references, references: references ?? this.references,
previousEmailId: previousEmailId ?? this.previousEmailId, previousEmailId: previousEmailId ?? this.previousEmailId,
identities: identities ?? this.identities, identities: identities ?? this.identities,
selectedIdentity: selectedIdentity ?? this.selectedIdentity, selectedIdentityId: selectedIdentityId ?? this.selectedIdentityId,
inlineImages: inlineImages ?? this.inlineImages, inlineImages: inlineImages ?? this.inlineImages,
hasRequestReadReceipt: hasRequestReadReceipt ?? this.hasRequestReadReceipt, hasRequestReadReceipt: hasRequestReadReceipt ?? this.hasRequestReadReceipt,
displayMode: displayMode ?? this.displayMode, displayMode: displayMode ?? this.displayMode,
@@ -1,5 +1,4 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
@@ -10,13 +9,11 @@ part 'composer_cache.g.dart';
class ComposerCache with EquatableMixin { class ComposerCache with EquatableMixin {
final Email? email; final Email? email;
final Identity? identity;
final bool? hasRequestReadReceipt; final bool? hasRequestReadReceipt;
final ScreenDisplayMode displayMode; final ScreenDisplayMode displayMode;
ComposerCache({ ComposerCache({
this.email, this.email,
this.identity,
this.hasRequestReadReceipt, this.hasRequestReadReceipt,
this.displayMode = ScreenDisplayMode.normal this.displayMode = ScreenDisplayMode.normal
}); });
@@ -28,7 +25,6 @@ class ComposerCache with EquatableMixin {
@override @override
List<Object?> get props => [ List<Object?> get props => [
email, email,
identity,
hasRequestReadReceipt, hasRequestReadReceipt,
displayMode displayMode
]; ];
@@ -1485,7 +1485,7 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
void goToComposer(ComposerArguments arguments) async { void goToComposer(ComposerArguments arguments) async {
final argumentsWithIdentity = arguments.withIdentity( final argumentsWithIdentity = arguments.withIdentity(
identities: List.from(_identities ?? []), identities: List.from(_identities ?? []),
selectedIdentity: arguments.selectedIdentity); selectedIdentityId: arguments.selectedIdentityId);
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
if (composerOverlayState.value == ComposerOverlayState.inActive) { if (composerOverlayState.value == ComposerOverlayState.inActive) {
@@ -2,7 +2,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:core/domain/extensions/datetime_extension.dart'; import 'package:core/domain/extensions/datetime_extension.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/properties/properties.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart'; import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
@@ -34,6 +36,13 @@ extension EmailExtension on Email {
String get sMimeStatusHeaderParsed => sMimeStatusHeader?[IndividualHeaderIdentifier.sMimeStatusHeader]?.trim() ?? ''; String get sMimeStatusHeaderParsed => sMimeStatusHeader?[IndividualHeaderIdentifier.sMimeStatusHeader]?.trim() ?? '';
IdentityId? get identityIdFromHeader {
final rawIdentityId = identityHeader?[IndividualHeaderIdentifier.identityHeader];
if (rawIdentityId == null) return null;
return IdentityId(Id(rawIdentityId));
}
bool hasReadReceipt(Map<MailboxId, PresentationMailbox> mapMailbox) { bool hasReadReceipt(Map<MailboxId, PresentationMailbox> mapMailbox) {
final mailboxCurrent = findMailboxContain(mapMailbox); final mailboxCurrent = findMailboxContain(mapMailbox);
return !hasMdnSent && return !hasMdnSent &&