Skip to content

Commit

Permalink
TF-825 Implement download message as eml in presentation layer
Browse files Browse the repository at this point in the history
  • Loading branch information
dab246 committed May 7, 2024
1 parent 6a15276 commit 3a49bdc
Show file tree
Hide file tree
Showing 16 changed files with 132 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ extension EmailActionTypeExtension on EmailActionType {
return imagePaths.icUnsubscribe;
case EmailActionType.archiveMessage:
return imagePaths.icMailboxArchived;
case EmailActionType.downloadMessageAsEML:
return imagePaths.icDownloadAttachment;
default:
return '';
}
Expand All @@ -152,6 +154,8 @@ extension EmailActionTypeExtension on EmailActionType {
return AppLocalizations.of(context).unsubscribe;
case EmailActionType.archiveMessage:
return AppLocalizations.of(context).archiveMessage;
case EmailActionType.downloadMessageAsEML:
return AppLocalizations.of(context).downloadMessageAsEML;
default:
return '';
}
Expand Down
9 changes: 8 additions & 1 deletion lib/features/email/presentation/bindings/email_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:tmail_ui_user/features/email/data/repository/email_repository_im
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_message_as_eml_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart';
Expand Down Expand Up @@ -69,7 +70,8 @@ class EmailBindings extends BaseBindings {
Get.find<GetAllIdentitiesInteractor>(),
Get.find<StoreOpenedEmailInteractor>(),
Get.find<ViewAttachmentForWebInteractor>(),
Get.find<PrintEmailInteractor>()
Get.find<PrintEmailInteractor>(),
Get.find<DownloadMessageAsEMLInteractor>(),
));
}

Expand Down Expand Up @@ -152,6 +154,11 @@ class EmailBindings extends BaseBindings {
Get.find<DownloadAttachmentForWebInteractor>()));
Get.lazyPut(() => StoreOpenedEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => PrintEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => DownloadMessageAsEMLInteractor(
Get.find<EmailRepository>(),
Get.find<CredentialRepository>(),
Get.find<AccountRepository>(),
Get.find<AuthenticationOIDCRepository>()));
IdentityInteractorsBindings().dependencies();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/email_print.dart';
Expand All @@ -38,6 +39,7 @@ import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_reques
import 'package:tmail_ui_user/features/email/domain/model/send_receipt_to_sender_request.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_attachments_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_message_as_eml_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/export_attachment_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
Expand All @@ -50,6 +52,7 @@ import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_stat
import 'package:tmail_ui_user/features/email/domain/state/view_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_message_as_eml_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
Expand Down Expand Up @@ -115,6 +118,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
final StoreOpenedEmailInteractor _storeOpenedEmailInteractor;
final ViewAttachmentForWebInteractor _viewAttachmentForWebInteractor;
final PrintEmailInteractor _printEmailInteractor;
final DownloadMessageAsEMLInteractor _downloadMessageAsEMLInteractor;

CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
SendReceiptToSenderInteractor? _sendReceiptToSenderInteractor;
Expand Down Expand Up @@ -154,6 +158,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
this._storeOpenedEmailInteractor,
this._viewAttachmentForWebInteractor,
this._printEmailInteractor,
this._downloadMessageAsEMLInteractor,
);

@override
Expand Down Expand Up @@ -212,6 +217,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_showMessageWhenStartingEmailPrinting();
} else if (success is PrintEmailSuccess) {
_handlePrintEmailSuccess(success);
} else if (success is StartDownloadMessageAsEML) {
_showMessageWhenStartingDownloadMessageAsEML();
}
}

Expand Down Expand Up @@ -1118,6 +1125,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
case EmailActionType.printAll:
_printEmail(context, presentationEmail);
break;
case EmailActionType.downloadMessageAsEML:
_downloadMessageAsEML(presentationEmail);
break;
default:
break;
}
Expand Down Expand Up @@ -1671,4 +1681,39 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
)
);
}

void _downloadMessageAsEML(PresentationEmail presentationEmail) {
final accountId = mailboxDashBoardController.accountId.value;
final session = mailboxDashBoardController.sessionCurrent;

if (accountId == null || session == null) {
consumeState(Stream.value(Left(DownloadMessageAsEMLFailure(NotFoundSessionException()))));
return;
}

final blobId = presentationEmail.blobId;
if (blobId == null) {
consumeState(Stream.value(Left(DownloadMessageAsEMLFailure(NotFoundEmailBlobIdException()))));
return;
}

final baseDownloadUrl = session.getDownloadUrl(jmapUrl: dynamicUrlInterceptors.jmapUrl);

consumeState(_downloadMessageAsEMLInteractor.execute(
accountId,
baseDownloadUrl,
blobId,
presentationEmail.getEmailTitle()
));
}

void _showMessageWhenStartingDownloadMessageAsEML() {
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).downloadMessageAsEMLInProgress,
leadingSVGIconColor: AppColor.primaryColor,
leadingSVGIcon: imagePaths.icDownloadAttachment);
}
}
}
2 changes: 2 additions & 0 deletions lib/features/email/presentation/email_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ class EmailView extends GetWidget<SingleEmailController> {
EmailActionType.unsubscribe,
if (mailboxContain?.isArchive == false)
EmailActionType.archiveMessage,
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
EmailActionType.downloadMessageAsEML
];

if (position == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extension EmailCacheExtension on EmailCache {
Email toEmail() {
return Email(
id: EmailId(Id(id)),
blobId: blobId != null ? Id(blobId!) : null,
keywords: keywords != null
? Map.fromIterables(keywords!.keys.map((value) => KeyWordIdentifier(value)), keywords!.values)
: null,
Expand Down
1 change: 1 addition & 0 deletions lib/features/thread/data/extensions/email_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extension EmailExtension on Email {
EmailCache toEmailCache() {
return EmailCache(
id!.id.value,
blobId: blobId?.value,
keywords: keywords?.toMapString(),
size: size?.value.round(),
receivedAt: receivedAt?.value,
Expand Down
31 changes: 18 additions & 13 deletions lib/features/thread/data/model/email_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,54 @@ class EmailCache extends HiveObject with EquatableMixin {
final String id;

@HiveField(1)
final Map<String, bool>? keywords;
final String? blobId;

@HiveField(2)
final int? size;
final Map<String, bool>? keywords;

@HiveField(3)
final DateTime? receivedAt;
final int? size;

@HiveField(4)
final bool? hasAttachment;
final DateTime? receivedAt;

@HiveField(5)
final String? preview;
final bool? hasAttachment;

@HiveField(6)
final String? subject;
final String? preview;

@HiveField(7)
final DateTime? sentAt;
final String? subject;

@HiveField(8)
final List<EmailAddressHiveCache>? from;
final DateTime? sentAt;

@HiveField(9)
final List<EmailAddressHiveCache>? to;
final List<EmailAddressHiveCache>? from;

@HiveField(10)
final List<EmailAddressHiveCache>? cc;
final List<EmailAddressHiveCache>? to;

@HiveField(11)
final List<EmailAddressHiveCache>? bcc;
final List<EmailAddressHiveCache>? cc;

@HiveField(12)
final List<EmailAddressHiveCache>? replyTo;
final List<EmailAddressHiveCache>? bcc;

@HiveField(13)
Map<String, bool>? mailboxIds;
final List<EmailAddressHiveCache>? replyTo;

@HiveField(14)
Map<String, bool>? mailboxIds;

@HiveField(15)
Map<String, String?>? headerCalendarEvent;

EmailCache(
this.id,
{
this.blobId,
this.keywords,
this.size,
this.receivedAt,
Expand All @@ -77,6 +81,7 @@ class EmailCache extends HiveObject with EquatableMixin {
@override
List<Object?> get props => [
id,
blobId,
subject,
from,
to,
Expand Down
4 changes: 4 additions & 0 deletions lib/features/thread/domain/constants/thread_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class ThreadConstants {
static final defaultLimit = UnsignedInt(maxCountEmails);
static final propertiesDefault = Properties({
EmailProperty.id,
EmailProperty.blobId,
EmailProperty.subject,
EmailProperty.from,
EmailProperty.to,
Expand All @@ -29,6 +30,7 @@ class ThreadConstants {

static final propertiesQuickSearch = Properties({
EmailProperty.id,
EmailProperty.blobId,
EmailProperty.subject,
EmailProperty.from,
EmailProperty.to,
Expand All @@ -53,6 +55,7 @@ class ThreadConstants {

static final propertiesGetDetailedEmail = Properties({
EmailProperty.id,
EmailProperty.blobId,
EmailProperty.subject,
EmailProperty.from,
EmailProperty.to,
Expand All @@ -74,6 +77,7 @@ class ThreadConstants {

static final propertiesCalendarEvent = Properties({
EmailProperty.id,
EmailProperty.blobId,
EmailProperty.subject,
EmailProperty.from,
EmailProperty.to,
Expand Down
14 changes: 13 additions & 1 deletion lib/l10n/intl_messages.arb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@@last_modified": "2024-04-19T16:31:35.757887",
"@@last_modified": "2024-05-07T16:16:03.932801",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
Expand Down Expand Up @@ -3695,5 +3695,17 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"downloadMessageAsEML": "Download message as EML",
"@downloadMessageAsEML": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"downloadMessageAsEMLInProgress": "Download message as EML in progress",
"@downloadMessageAsEMLInProgress": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
14 changes: 14 additions & 0 deletions lib/main/localizations/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3851,4 +3851,18 @@ class AppLocalizations {
name: 'noSuitableBrowserForOIDC'
);
}

String get downloadMessageAsEML {
return Intl.message(
'Download message as EML',
name: 'downloadMessageAsEML',
);
}

String get downloadMessageAsEMLInProgress {
return Intl.message(
'Download message as EML in progress',
name: 'downloadMessageAsEMLInProgress'
);
}
}
3 changes: 2 additions & 1 deletion model/lib/email/email_action_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ enum EmailActionType {
unsubscribe,
composeFromUnsubscribeMailtoLink,
archiveMessage,
printAll
printAll,
downloadMessageAsEML
}
1 change: 1 addition & 0 deletions model/lib/email/email_property.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

class EmailProperty {
static const String id = 'id';
static const String blobId = 'blobId';
static const String keywords = 'keywords';
static const String size = 'size';
static const String receivedAt = 'receivedAt';
Expand Down
4 changes: 4 additions & 0 deletions model/lib/email/presentation_email.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import 'package:core/presentation/extensions/string_extension.dart';
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
Expand All @@ -21,6 +22,7 @@ import 'package:model/mailbox/select_mode.dart';
class PresentationEmail with EquatableMixin {

final EmailId? id;
final Id? blobId;
final Map<KeyWordIdentifier, bool>? keywords;
final UnsignedInt? size;
final UTCDate? receivedAt;
Expand All @@ -44,6 +46,7 @@ class PresentationEmail with EquatableMixin {

PresentationEmail({
this.id,
this.blobId,
this.keywords,
this.size,
this.receivedAt,
Expand Down Expand Up @@ -142,6 +145,7 @@ class PresentationEmail with EquatableMixin {
@override
List<Object?> get props => [
id,
blobId,
keywords,
size,
receivedAt,
Expand Down
Loading

0 comments on commit 3a49bdc

Please sign in to comment.