TF-825 Download email as EML file (#2854)
This commit is contained in:
@@ -351,12 +351,12 @@ class EmailAPI with HandleSetErrorMixin {
|
||||
headers: headerParam,
|
||||
responseType: ResponseType.bytes),
|
||||
onReceiveProgress: (downloaded, total) {
|
||||
log('DownloadClient::downloadFileForWeb(): downloaded = $downloaded | total: $total');
|
||||
log('EmailAPI::downloadFileForWeb(): downloaded = $downloaded | total: $total');
|
||||
double progress = 0;
|
||||
if (downloaded > 0 && total > downloaded) {
|
||||
if (downloaded > 0 && total >= downloaded) {
|
||||
progress = (downloaded / total) * 100;
|
||||
}
|
||||
log('DownloadClient::downloadFileForWeb(): progress = ${progress.round()}%');
|
||||
log('EmailAPI::downloadFileForWeb(): progress = ${progress.round()}%');
|
||||
onReceiveController.add(Right(DownloadingAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
|
||||
@@ -4,4 +4,6 @@ class NotFoundEmailContentException implements Exception {}
|
||||
|
||||
class EmptyEmailContentException implements Exception {}
|
||||
|
||||
class NotFoundEmailRecoveryActionException implements Exception {}
|
||||
class NotFoundEmailRecoveryActionException implements Exception {}
|
||||
|
||||
class NotFoundEmailBlobIdException implements Exception {}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
|
||||
@@ -59,14 +58,14 @@ class DownloadAttachmentForWebSuccess extends UIState {
|
||||
class DownloadAttachmentForWebFailure extends FeatureFailure {
|
||||
|
||||
final DownloadTaskId? taskId;
|
||||
final Id? attachmentBlobId;
|
||||
final Attachment? attachment;
|
||||
|
||||
DownloadAttachmentForWebFailure({
|
||||
required this.attachmentBlobId,
|
||||
this.attachment,
|
||||
this.taskId,
|
||||
dynamic exception
|
||||
}) : super(exception: exception);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [taskId, ...super.props];
|
||||
List<Object?> get props => [attachment, taskId, ...super.props];
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class ViewAttachmentForWebSuccess extends DownloadAttachmentForWebSuccess {
|
||||
|
||||
class ViewAttachmentForWebFailure extends DownloadAttachmentForWebFailure {
|
||||
ViewAttachmentForWebFailure({
|
||||
required super.attachmentBlobId,
|
||||
required super.attachment,
|
||||
super.taskId,
|
||||
super.exception,
|
||||
});
|
||||
|
||||
@@ -72,7 +72,7 @@ class DownloadAttachmentForWebInteractor {
|
||||
} catch (exception) {
|
||||
yield Left<Failure, Success>(
|
||||
DownloadAttachmentForWebFailure(
|
||||
attachmentBlobId: attachment.blobId,
|
||||
attachment: attachment,
|
||||
taskId: taskId,
|
||||
exception: exception
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ class ViewAttachmentForWebInteractor {
|
||||
(failure) {
|
||||
if (failure is DownloadAttachmentForWebFailure) {
|
||||
return Left(ViewAttachmentForWebFailure(
|
||||
attachmentBlobId: attachment.blobId,
|
||||
attachment: attachment,
|
||||
taskId: failure.taskId,
|
||||
exception: failure.exception,
|
||||
));
|
||||
|
||||
@@ -20,6 +20,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mdn/disposition.dart';
|
||||
import 'package:jmap_dart_client/jmap/mdn/mdn.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:model/email/eml_attachment.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
@@ -28,6 +29,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';
|
||||
@@ -810,7 +812,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
} else {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAttachmentForWebFailure(
|
||||
attachmentBlobId: attachment.blobId,
|
||||
attachment: attachment,
|
||||
exception: NotFoundSessionException()))
|
||||
));
|
||||
}
|
||||
@@ -831,7 +833,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
} else {
|
||||
consumeState(Stream.value(
|
||||
Left(ViewAttachmentForWebFailure(
|
||||
attachmentBlobId: attachment.blobId,
|
||||
attachment: attachment,
|
||||
exception: NotFoundSessionException()))
|
||||
));
|
||||
}
|
||||
@@ -876,12 +878,16 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
mailboxDashBoardController.deleteDownloadTask(failure.taskId!);
|
||||
}
|
||||
|
||||
_updateAttachmentsViewState(failure.attachmentBlobId, Left(failure));
|
||||
if (failure.attachment != null) {
|
||||
_updateAttachmentsViewState(failure.attachment?.blobId, Left(failure));
|
||||
}
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).attachment_download_failed);
|
||||
failure.attachment is EMLAttachment
|
||||
? AppLocalizations.of(currentContext!).downloadMessageAsEMLFailed
|
||||
: AppLocalizations.of(currentContext!).attachment_download_failed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,6 +1147,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
case EmailActionType.printAll:
|
||||
_printEmail(context, presentationEmail);
|
||||
break;
|
||||
case EmailActionType.downloadMessageAsEML:
|
||||
_downloadMessageAsEML(presentationEmail);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1772,4 +1781,14 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
AppLocalizations.of(currentContext!).eventReplyWasSentUnsuccessfully);
|
||||
}
|
||||
}
|
||||
|
||||
void _downloadMessageAsEML(PresentationEmail presentationEmail) {
|
||||
final emlAttachment = presentationEmail.createEMLAttachment();
|
||||
if (emlAttachment.blobId == null) {
|
||||
consumeState(Stream.value(Left(DownloadAttachmentForWebFailure(exception: NotFoundEmailBlobIdException()))));
|
||||
return;
|
||||
}
|
||||
|
||||
downloadAttachmentForWeb(emlAttachment);
|
||||
}
|
||||
}
|
||||
@@ -473,6 +473,8 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
EmailActionType.unsubscribe,
|
||||
if (mailboxContain?.isArchive == false)
|
||||
EmailActionType.archiveMessage,
|
||||
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
|
||||
EmailActionType.downloadMessageAsEML
|
||||
];
|
||||
|
||||
if (position == null) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:get/get_utils/src/get_utils/get_utils.dart';
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
Reference in New Issue
Block a user