TF-4050 Preview and download uploaded file in composer on web

This commit is contained in:
dab246
2025-11-07 01:12:20 +07:00
committed by Dat H. Pham
parent ecd3ac0295
commit 972b20ec16
72 changed files with 2438 additions and 1751 deletions
+15 -8
View File
@@ -57,11 +57,12 @@ import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/mail_api_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_all_attachments_for_web_state.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
@@ -343,12 +344,18 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin {
progress = (downloaded / total) * 100;
}
log('EmailAPI::downloadFileForWeb(): progress = ${progress.round()}%');
onReceiveController?.add(Right(DownloadingAttachmentForWeb(
taskId,
attachment,
progress,
downloaded,
total)));
onReceiveController?.add(
Right(
DownloadingAttachmentForWeb(
taskId,
attachment,
progress,
downloaded,
total,
DownloadSourceView.emailView,
),
),
);
}
);
@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:core/data/model/source_type/data_source_type.dart';
import 'package:core/data/network/download/downloaded_response.dart';
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dio/dio.dart';
@@ -14,8 +13,6 @@ 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/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/account/account_request.dart';
import 'package:model/email/attachment.dart';
import 'package:model/email/email_content.dart';
import 'package:model/email/mark_star_action.dart';
import 'package:model/email/read_actions.dart';
@@ -135,22 +132,6 @@ class EmailRepositoryImpl extends EmailRepository {
return result;
}
@override
Future<DownloadedResponse> exportAttachment(
Attachment attachment,
AccountId accountId,
String baseDownloadUrl,
AccountRequest accountRequest,
CancelToken cancelToken
) {
return emailDataSource[DataSourceType.network]!.exportAttachment(
attachment,
accountId,
baseDownloadUrl,
accountRequest,
cancelToken);
}
@override
Future<({
List<EmailId> emailIdsSuccess,
@@ -494,22 +475,6 @@ class EmailRepositoryImpl extends EmailRepository {
return _printFileDataSource.printEmail(emailPrint);
}
@override
Future<DownloadedResponse> exportAllAttachments(
AccountId accountId,
EmailId emailId,
String baseDownloadAllUrl,
String outputFileName,
AccountRequest accountRequest, {
CancelToken? cancelToken,
}) => emailDataSource[DataSourceType.network]!.exportAllAttachments(
accountId,
emailId,
baseDownloadAllUrl,
outputFileName,
accountRequest,
);
@override
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
return emailDataSource[DataSourceType.local]!.generateEntireMessageAsDocument(entireMessageRequest);
@@ -1 +0,0 @@
class DownloadAttachmentInteractorIsNull implements Exception {}
@@ -1,6 +1,5 @@
import 'dart:async';
import 'package:core/data/network/download/downloaded_response.dart';
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
import 'package:dio/dio.dart';
import 'package:email_recovery/email_recovery/email_recovery_action.dart';
@@ -12,8 +11,6 @@ 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/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/account/account_request.dart';
import 'package:model/email/attachment.dart';
import 'package:model/email/email_content.dart';
import 'package:model/email/mark_star_action.dart';
import 'package:model/email/read_actions.dart';
@@ -52,14 +49,6 @@ abstract class EmailRepository {
ReadActions readActions,
);
Future<DownloadedResponse> exportAttachment(
Attachment attachment,
AccountId accountId,
String baseDownloadUrl,
AccountRequest accountRequest,
CancelToken cancelToken
);
Future<({
List<EmailId> emailIdsSuccess,
Map<Id, SetError> mapErrors,
@@ -170,14 +159,5 @@ abstract class EmailRepository {
Future<void> printEmail(EmailPrint emailPrint);
Future<DownloadedResponse> exportAllAttachments(
AccountId accountId,
EmailId emailId,
String baseDownloadAllUrl,
String outputFileName,
AccountRequest accountRequest,
{CancelToken? cancelToken}
);
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest);
}
@@ -1,54 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dio/dio.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
class StartDownloadAllAttachmentsForWeb extends UIState {
StartDownloadAllAttachmentsForWeb(this.taskId, this.attachment, {this.cancelToken});
final DownloadTaskId taskId;
final Attachment attachment;
final CancelToken? cancelToken;
@override
List<Object?> get props => [taskId, attachment, cancelToken];
}
class DownloadingAllAttachmentsForWeb extends LoadingState {
DownloadingAllAttachmentsForWeb(
this.taskId,
this.fileName,
this.progress,
this.downloaded,
this.total,
);
final DownloadTaskId taskId;
final String fileName;
final double progress;
final int downloaded;
final int total;
@override
List<Object?> get props => [taskId, fileName, progress, downloaded, total];
}
class DownloadAllAttachmentsForWebSuccess extends UIState {
DownloadAllAttachmentsForWebSuccess({required this.taskId});
final DownloadTaskId taskId;
@override
List<Object> get props => [taskId];
}
class DownloadAllAttachmentsForWebFailure extends FeatureFailure {
DownloadAllAttachmentsForWebFailure({super.exception, required this.taskId, this.cancelToken});
final DownloadTaskId taskId;
final CancelToken? cancelToken;
@override
List<Object?> get props => [exception, taskId, cancelToken];
}
@@ -1,77 +0,0 @@
import 'dart:typed_data';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dio/dio.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
class IdleDownloadAttachmentForWeb extends UIState {}
class StartDownloadAttachmentForWeb extends UIState {
final DownloadTaskId taskId;
final Attachment attachment;
final CancelToken? cancelToken;
final bool previewerSupported;
StartDownloadAttachmentForWeb(this.taskId, this.attachment, [this.cancelToken, this.previewerSupported = false]);
@override
List<Object?> get props => [taskId, attachment, cancelToken, previewerSupported];
}
class DownloadingAttachmentForWeb extends UIState {
final DownloadTaskId taskId;
final Attachment attachment;
final double progress;
final int downloaded;
final int total;
DownloadingAttachmentForWeb(
this.taskId,
this.attachment,
this.progress,
this.downloaded,
this.total
);
@override
List<Object> get props => [
taskId,
attachment,
progress,
downloaded,
total
];
}
class DownloadAttachmentForWebSuccess extends UIState {
final DownloadTaskId taskId;
final Attachment attachment;
final Uint8List bytes;
final bool previewerSupported;
DownloadAttachmentForWebSuccess(this.taskId, this.attachment, this.bytes, this.previewerSupported);
@override
List<Object> get props => [taskId, attachment, bytes, previewerSupported];
}
class DownloadAttachmentForWebFailure extends FeatureFailure {
final DownloadTaskId? taskId;
final Attachment? attachment;
final CancelToken? cancelToken;
DownloadAttachmentForWebFailure({
this.attachment,
this.taskId,
this.cancelToken,
super.exception
});
@override
List<Object?> get props => [attachment, taskId, cancelToken, ...super.props];
}
@@ -1,18 +0,0 @@
import 'package:core/data/network/download/downloaded_response.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class ExportingAllAttachments extends LoadingState {}
class ExportAllAttachmentsSuccess extends UIState {
ExportAllAttachmentsSuccess(this.downloadedResponse);
final DownloadedResponse downloadedResponse;
@override
List<Object> get props => [downloadedResponse];
}
class ExportAllAttachmentsFailure extends FeatureFailure {
ExportAllAttachmentsFailure({super.exception});
}
@@ -1,17 +0,0 @@
import 'package:core/data/network/download/downloaded_response.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class ExportAttachmentSuccess extends UIState {
final DownloadedResponse downloadedResponse;
ExportAttachmentSuccess(this.downloadedResponse);
@override
List<Object> get props => [downloadedResponse];
}
class ExportAttachmentFailure extends FeatureFailure {
ExportAttachmentFailure(dynamic exception) : super(exception: exception);
}
@@ -1,40 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:model/email/attachment.dart';
class GettingHtmlContentFromAttachment extends LoadingState {
GettingHtmlContentFromAttachment({required this.attachment});
final Attachment attachment;
@override
List<Object?> get props => [attachment];
}
class GetHtmlContentFromAttachmentSuccess extends UIState {
GetHtmlContentFromAttachmentSuccess({
required this.sanitizedHtmlContent,
required this.htmlAttachmentTitle,
required this.attachment,
});
final String sanitizedHtmlContent;
final String htmlAttachmentTitle;
final Attachment attachment;
@override
List<Object?> get props => [
sanitizedHtmlContent,
htmlAttachmentTitle,
attachment,
];
}
class GetHtmlContentFromAttachmentFailure extends FeatureFailure {
GetHtmlContentFromAttachmentFailure({super.exception, required this.attachment});
final Attachment attachment;
@override
List<Object?> get props => [attachment];
}
@@ -1,27 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
class GettingPreviewEmailEMLContentShared extends LoadingState {}
class GetPreviewEmailEMLContentSharedSuccess extends UIState {
final EMLPreviewer emlPreviewer;
GetPreviewEmailEMLContentSharedSuccess(this.emlPreviewer);
@override
List<Object?> get props => [emlPreviewer];
}
class GetPreviewEmailEMLContentSharedFailure extends FeatureFailure {
final String? keyStored;
GetPreviewEmailEMLContentSharedFailure({
this.keyStored,
dynamic exception,
}) : super(exception: exception);
@override
List<Object?> get props => [keyStored, exception];
}
@@ -1,26 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
class GettingPreviewEMLContentInMemory extends LoadingState {}
class GetPreviewEMLContentInMemorySuccess extends UIState {
final EMLPreviewer emlPreviewer;
GetPreviewEMLContentInMemorySuccess(this.emlPreviewer);
@override
List<Object?> get props => [emlPreviewer];
}
class GetPreviewEMLContentInMemoryFailure extends FeatureFailure {
final String? keyStored;
GetPreviewEMLContentInMemoryFailure({
this.keyStored,
dynamic exception,
}) : super(exception: exception);
@override
List<Object?> get props => [keyStored, exception];
}
@@ -1,11 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class MovingPreviewEmailEMLContentFromPersistentToMemory extends LoadingState {}
class MovePreviewEmailEMLContentFromPersistentToMemorySuccess extends UIState {}
class MovePreviewEmailEMLContentFromPersistentToMemoryFailure extends FeatureFailure {
MovePreviewEmailEMLContentFromPersistentToMemoryFailure(dynamic exception) : super(exception: exception);
}
@@ -1,37 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.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/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
class ParsingEmailByBlobId extends LoadingState {}
class ParseEmailByBlobIdSuccess extends UIState {
final AccountId? accountId;
final Session? session;
final String ownEmailAddress;
final Email email;
final Id blobId;
ParseEmailByBlobIdSuccess({
required this.email,
required this.blobId,
required this.accountId,
required this.session,
required this.ownEmailAddress,
});
@override
List<Object?> get props => [
email,
blobId,
accountId,
session,
ownEmailAddress,
];
}
class ParseEmailByBlobIdFailure extends FeatureFailure {
ParseEmailByBlobIdFailure(dynamic exception) : super(exception: exception);
}
@@ -1,34 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
class PreviewingEmailFromEmlFile extends LoadingState {}
class PreviewEmailFromEmlFileSuccess extends UIState {
final EMLPreviewer emlPreviewer;
final AccountId? accountId;
final Session? session;
final String ownEmailAddress;
PreviewEmailFromEmlFileSuccess(
this.emlPreviewer,
this.accountId,
this.session,
this.ownEmailAddress,
);
@override
List<Object?> get props => [
emlPreviewer,
accountId,
session,
ownEmailAddress,
];
}
class PreviewEmailFromEmlFileFailure extends FeatureFailure {
PreviewEmailFromEmlFileFailure(dynamic exception)
: super(exception: exception);
}
@@ -1,11 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class RemovingPreviewEmailEMLContentShared extends LoadingState {}
class RemovePreviewEmailEMLContentSharedSuccess extends UIState {}
class RemovePreviewEmailEMLContentSharedFailure extends FeatureFailure {
RemovePreviewEmailEMLContentSharedFailure(dynamic exception) : super(exception: exception);
}
@@ -1,88 +0,0 @@
import 'dart:async';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:jmap_dart_client/jmap/account_id.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/account/authentication_type.dart';
import 'package:model/account/password.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart';
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class DownloadAllAttachmentsForWebInteractor {
const DownloadAllAttachmentsForWebInteractor(
this._downloadRepository,
this._accountRepository,
this._authenticationOIDCRepository,
this.credentialRepository,
);
final DownloadRepository _downloadRepository;
final AccountRepository _accountRepository;
final AuthenticationOIDCRepository _authenticationOIDCRepository;
final CredentialRepository credentialRepository;
Stream<Either<Failure, Success>> execute(
AccountId accountId,
EmailId emailId,
String baseDownloadAllUrl,
Attachment attachment,
DownloadTaskId taskId, {
StreamController<Either<Failure, Success>>? onReceiveController,
CancelToken? cancelToken,
}) async* {
try {
yield Right(StartDownloadAllAttachmentsForWeb(
taskId,
attachment,
));
onReceiveController?.add(Right(StartDownloadAllAttachmentsForWeb(
taskId,
attachment,
cancelToken: cancelToken,
)));
final currentAccount = await _accountRepository.getCurrentAccount();
AccountRequest accountRequest;
if (currentAccount.authenticationType == AuthenticationType.oidc) {
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
accountRequest = AccountRequest.withOidc(token: tokenOidc);
} else {
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
accountRequest = AccountRequest.withBasic(
userName: UserName(authenticationInfoCache.username),
password: Password(authenticationInfoCache.password),
);
}
await _downloadRepository.downloadAllAttachmentsForWeb(
accountId,
emailId,
baseDownloadAllUrl,
attachment.name!,
accountRequest,
taskId,
onReceiveController: onReceiveController,
cancelToken: cancelToken
);
yield Right(DownloadAllAttachmentsForWebSuccess(taskId: taskId));
} catch (e) {
logError('DownloadAllAttachmentsForWebInteractor::execute():EXCEPTION: $e');
yield Left(DownloadAllAttachmentsForWebFailure(
exception: e,
taskId: taskId,
cancelToken: cancelToken,
));
}
}
}
@@ -1,88 +0,0 @@
import 'dart:async';
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:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:model/account/account_request.dart';
import 'package:model/account/authentication_type.dart';
import 'package:model/account/password.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class DownloadAttachmentForWebInteractor {
final DownloadRepository downloadRepository;
final CredentialRepository credentialRepository;
final AccountRepository _accountRepository;
final AuthenticationOIDCRepository _authenticationOIDCRepository;
DownloadAttachmentForWebInteractor(
this.downloadRepository,
this.credentialRepository,
this._accountRepository,
this._authenticationOIDCRepository);
Stream<Either<Failure, Success>> execute(
DownloadTaskId taskId,
Attachment attachment,
AccountId accountId,
String baseDownloadUrl, {
StreamController<Either<Failure, Success>>? onReceiveController,
CancelToken? cancelToken,
bool previewerSupported = false,
}) async* {
try {
yield Right<Failure, Success>(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported));
onReceiveController?.add(Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported)));
final currentAccount = await _accountRepository.getCurrentAccount();
AccountRequest? accountRequest;
if (currentAccount.authenticationType == AuthenticationType.oidc) {
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
accountRequest = AccountRequest.withOidc(token: tokenOidc);
} else {
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
accountRequest = AccountRequest.withBasic(
userName: UserName(authenticationInfoCache.username),
password: Password(authenticationInfoCache.password),
);
}
final bytesDownloaded = await downloadRepository.downloadAttachmentForWeb(
taskId,
attachment,
accountId,
baseDownloadUrl,
accountRequest,
onReceiveController: onReceiveController,
cancelToken: cancelToken
);
yield Right<Failure, Success>(
DownloadAttachmentForWebSuccess(
taskId,
attachment,
bytesDownloaded,
previewerSupported,
)
);
} catch (exception) {
yield Left<Failure, Success>(
DownloadAttachmentForWebFailure(
attachment: attachment,
taskId: taskId,
exception: exception,
cancelToken: cancelToken,
)
);
}
}
}
@@ -1,68 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:jmap_dart_client/jmap/account_id.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/account/authentication_type.dart';
import 'package:model/account/password.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/state/export_all_attachments_state.dart';
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
class ExportAllAttachmentsInteractor {
const ExportAllAttachmentsInteractor(
this._emailRepository,
this._accountRepository,
this._authenticationOIDCRepository,
this.credentialRepository,
);
final EmailRepository _emailRepository;
final AccountRepository _accountRepository;
final AuthenticationOIDCRepository _authenticationOIDCRepository;
final CredentialRepository credentialRepository;
Stream<Either<Failure, Success>> execute(
AccountId accountId,
EmailId emailId,
String baseDownloadAllUrl,
String outputFileName,
{CancelToken? cancelToken}
) async* {
try {
yield Right(ExportingAllAttachments());
final currentAccount = await _accountRepository.getCurrentAccount();
AccountRequest accountRequest;
if (currentAccount.authenticationType == AuthenticationType.oidc) {
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
accountRequest = AccountRequest.withOidc(token: tokenOidc);
} else {
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
accountRequest = AccountRequest.withBasic(
userName: UserName(authenticationInfoCache.username),
password: Password(authenticationInfoCache.password),
);
}
final result = await _emailRepository.exportAllAttachments(
accountId,
emailId,
baseDownloadAllUrl,
outputFileName,
accountRequest,
cancelToken: cancelToken,
);
yield Right(ExportAllAttachmentsSuccess(result));
} catch (e) {
logError('ExportAllAttachmentsInteractor::execute():EXCEPTION: $e');
yield Left(ExportAllAttachmentsFailure(exception: e));
}
}
}
@@ -1,64 +0,0 @@
import 'dart:async';
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/state/export_attachment_state.dart';
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
class ExportAttachmentInteractor {
final EmailRepository emailRepository;
final CredentialRepository credentialRepository;
final AccountRepository _accountRepository;
final AuthenticationOIDCRepository _authenticationOIDCRepository;
ExportAttachmentInteractor(
this.emailRepository,
this.credentialRepository,
this._accountRepository,
this._authenticationOIDCRepository,
);
Stream<Either<Failure, Success>> execute(
Attachment attachment,
AccountId accountId,
String baseDownloadUrl,
CancelToken cancelToken
) async* {
try {
final currentAccount = await _accountRepository.getCurrentAccount();
AccountRequest? accountRequest;
if (currentAccount.authenticationType == AuthenticationType.oidc) {
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
accountRequest = AccountRequest.withOidc(token: tokenOidc);
} else {
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
accountRequest = AccountRequest.withBasic(
userName: UserName(authenticationInfoCache.username),
password: Password(authenticationInfoCache.password),
);
}
final downloadedResponse = await emailRepository.exportAttachment(
attachment,
accountId,
baseDownloadUrl,
accountRequest,
cancelToken
);
yield Right<Failure, Success>(ExportAttachmentSuccess(downloadedResponse));
} catch (exception) {
log('ExportAttachmentInteractor::execute(): exception: $exception');
yield Left<Failure, Success>(ExportAttachmentFailure(exception));
}
}
}
@@ -1,105 +0,0 @@
import 'dart:async';
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/string_convert.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.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/get_html_content_from_attachment_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
class GetHtmlContentFromAttachmentInteractor {
GetHtmlContentFromAttachmentInteractor(
this._downloadAttachmentForWebInteractor,
);
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
Stream<Either<Failure, Success>> execute(
AccountId accountId,
Attachment attachment,
DownloadTaskId taskId,
String baseDownloadUrl,
TransformConfiguration transformConfiguration,
) async* {
try {
yield Right(GettingHtmlContentFromAttachment(attachment: attachment));
final downloadState = await _downloadAttachmentForWebInteractor.execute(
taskId,
attachment,
accountId,
baseDownloadUrl,
).last;
Either<Failure, Success>? sanitizeState;
await downloadState.fold(
(failure) {
sanitizeState = Left(GetHtmlContentFromAttachmentFailure(
exception: failure is FeatureFailure ? failure.exception : null,
attachment: attachment,
));
},
(success) async {
if (success is! DownloadAttachmentForWebSuccess) {
sanitizeState = Right(GettingHtmlContentFromAttachment(attachment: attachment));
} else {
final htmlContent = StringConvert.decodeFromBytes(
success.bytes,
charset: success.attachment.charset,
isHtml: true,
);
sanitizeState = await _sanitizeHtmlContent(
htmlContent,
transformConfiguration,
attachment,
);
}
},
);
if (sanitizeState != null) {
yield sanitizeState!;
} else {
yield Left(GetHtmlContentFromAttachmentFailure(
exception: null,
attachment: attachment,
));
}
} catch (e) {
logError('GetHtmlContentFromAttachmentInteractor:exception: $e');
yield Left(GetHtmlContentFromAttachmentFailure(
exception: e,
attachment: attachment,
));
}
}
Future<Either<Failure, Success>?> _sanitizeHtmlContent(
String htmlContent,
TransformConfiguration transformConfiguration,
Attachment attachment,
) async {
try {
final sanitizedHtmlContent = await _downloadAttachmentForWebInteractor
.downloadRepository
.sanitizeHtmlContent(htmlContent, transformConfiguration);
return Right(GetHtmlContentFromAttachmentSuccess(
sanitizedHtmlContent: sanitizedHtmlContent,
htmlAttachmentTitle: attachment.generateFileName(),
attachment: attachment,
));
} catch (e) {
return Left(GetHtmlContentFromAttachmentFailure(
exception: e,
attachment: attachment,
));
}
}
}
@@ -1,27 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_preview_email_eml_content_shared_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class GetPreviewEmailEMLContentSharedInteractor {
final DownloadRepository _downloadRepository;
const GetPreviewEmailEMLContentSharedInteractor(this._downloadRepository);
Stream<Either<Failure, Success>> execute(String keyStored) async* {
try {
yield Right<Failure, Success>(GettingPreviewEmailEMLContentShared());
final previewEMLContent = await _downloadRepository
.getPreviewEmailEMLContentShared(keyStored);
yield Right<Failure, Success>(GetPreviewEmailEMLContentSharedSuccess(previewEMLContent));
} catch (e) {
yield Left<Failure, Success>(GetPreviewEmailEMLContentSharedFailure(
keyStored: keyStored,
exception: e,
));
}
}
}
@@ -1,24 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_preview_eml_content_in_memory_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class GetPreviewEmlContentInMemoryInteractor {
final DownloadRepository _downloadRepository;
const GetPreviewEmlContentInMemoryInteractor(this._downloadRepository);
Stream<Either<Failure, Success>> execute(String keyStored) async* {
try {
yield Right<Failure, Success>(GettingPreviewEMLContentInMemory());
final emlPreviewer = await _downloadRepository.getPreviewEMLContentInMemory(keyStored);
yield Right<Failure, Success>(GetPreviewEMLContentInMemorySuccess(emlPreviewer));
} catch (e) {
yield Left<Failure, Success>(GetPreviewEMLContentInMemoryFailure(
keyStored: keyStored,
exception: e,
));
}
}
}
@@ -1,27 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_preview_eml_content_from_persistent_to_memory_state.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class MovePreviewEmlContentFromPersistentToMemoryInteractor {
final DownloadRepository _downloadRepository;
const MovePreviewEmlContentFromPersistentToMemoryInteractor(
this._downloadRepository,
);
Stream<Either<Failure, Success>> execute(EMLPreviewer emlPreviewer) async* {
try {
yield Right<Failure, Success>(MovingPreviewEmailEMLContentFromPersistentToMemory());
await Future.wait([
_downloadRepository.removePreviewEmailEMLContentShared(emlPreviewer.id),
_downloadRepository.storePreviewEMLContentToSessionStorage(emlPreviewer),
]);
yield Right<Failure, Success>(MovePreviewEmailEMLContentFromPersistentToMemorySuccess());
} catch (e) {
yield Left<Failure, Success>(MovePreviewEmailEMLContentFromPersistentToMemoryFailure(e));
}
}
}
@@ -1,40 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.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/session/session.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class ParseEmailByBlobIdInteractor {
final DownloadRepository _downloadRepository;
const ParseEmailByBlobIdInteractor(this._downloadRepository);
Stream<Either<Failure, Success>> execute(
AccountId accountId,
Session session,
String ownEmailAddress,
Id blobId,
) async* {
try {
yield Right<Failure, Success>(ParsingEmailByBlobId());
final emailParsed = await _downloadRepository.parseEmailByBlobIds(
accountId,
{blobId},
);
yield Right<Failure, Success>(ParseEmailByBlobIdSuccess(
email: emailParsed.first,
blobId: blobId,
session: session,
accountId: accountId,
ownEmailAddress: ownEmailAddress,
));
} catch (e) {
yield Left<Failure, Success>(ParseEmailByBlobIdFailure(e));
}
}
}
@@ -1,52 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/platform_info.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class PreviewEmailFromEmlFileInteractor {
final DownloadRepository _downloadRepository;
const PreviewEmailFromEmlFileInteractor(this._downloadRepository);
Stream<Either<Failure, Success>> execute(
PreviewEmailEMLRequest previewEmailEMLRequest,
) async* {
try {
yield Right<Failure, Success>(PreviewingEmailFromEmlFile());
final previewEMLContent = await _downloadRepository
.generatePreviewEmailEMLContent(previewEmailEMLRequest);
final emlPreviewer = EMLPreviewer(
id: previewEmailEMLRequest.keyStored,
title: previewEmailEMLRequest.title,
content: previewEMLContent,
);
if (PlatformInfo.isWeb) {
if (previewEmailEMLRequest.isShared) {
await _downloadRepository.sharePreviewEmailEMLContent(emlPreviewer);
} else {
await _downloadRepository.storePreviewEMLContentToSessionStorage(
emlPreviewer,
);
}
}
yield Right<Failure, Success>(
PreviewEmailFromEmlFileSuccess(
emlPreviewer,
previewEmailEMLRequest.accountId,
previewEmailEMLRequest.session,
previewEmailEMLRequest.ownEmailAddress,
),
);
} catch (e) {
yield Left<Failure, Success>(PreviewEmailFromEmlFileFailure(e));
}
}
}
@@ -1,21 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/email/domain/state/remove_preview_email_eml_content_shared_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
class RemovePreviewEmailEmlContentSharedInteractor {
final DownloadRepository _downloadRepository;
const RemovePreviewEmailEmlContentSharedInteractor(this._downloadRepository);
Stream<Either<Failure, Success>> execute(String keyStored) async* {
try {
yield Right<Failure, Success>(RemovingPreviewEmailEMLContentShared());
await _downloadRepository.removePreviewEmailEMLContentShared(keyStored);
yield Right<Failure, Success>(RemovePreviewEmailEMLContentSharedSuccess());
} catch (e) {
yield Left<Failure, Success>(RemovePreviewEmailEMLContentSharedFailure(e));
}
}
}
@@ -1,7 +1,5 @@
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_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';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
@@ -22,12 +20,10 @@ class EmailBindings extends Bindings {
Get.put(SingleEmailController(
Get.find<GetEmailContentInteractor>(),
Get.find<MarkAsEmailReadInteractor>(),
Get.find<ExportAttachmentInteractor>(),
Get.find<MarkAsStarEmailInteractor>(),
Get.find<GetAllIdentitiesInteractor>(),
Get.find<StoreOpenedEmailInteractor>(),
Get.find<PrintEmailInteractor>(),
Get.find<ExportAllAttachmentsInteractor>(),
currentEmailId: currentEmailId,
), tag: tag);
}
@@ -16,8 +16,6 @@ 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/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/export_all_attachments_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_entire_message_as_document_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart';
@@ -26,9 +24,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.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';
@@ -111,23 +106,12 @@ class EmailInteractorBindings extends InteractorsBindings {
void bindingsInteractor() {
Get.lazyPut(() => GetEmailContentInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsEmailReadInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => ExportAttachmentInteractor(
Get.find<EmailRepository>(),
Get.find<CredentialRepository>(),
Get.find<AccountRepository>(),
Get.find<AuthenticationOIDCRepository>(),
));
Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => GetStoredEmailStateInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => StoreOpenedEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => PrintEmailInteractor(Get.find<EmailRepository>()));
IdentityInteractorsBindings().dependencies();
Get.lazyPut(() => ExportAllAttachmentsInteractor(
Get.find<EmailRepository>(),
Get.find<AccountRepository>(),
Get.find<AuthenticationOIDCRepository>(),
Get.find<CredentialRepository>()));
if (PlatformInfo.isIOS) {
Get.lazyPut(() => GetEntireMessageAsDocumentInteractor(
Get.find<EmailRepository>(),
@@ -1,13 +1,10 @@
import 'dart:async';
import 'dart:io';
import 'package:core/core.dart';
import 'package:core/presentation/utils/html_transformer/text/new_line_transformer.dart';
import 'package:core/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
@@ -26,12 +23,12 @@ import 'package:jmap_dart_client/jmap/mdn/disposition.dart';
import 'package:jmap_dart_client/jmap/mdn/mdn.dart';
import 'package:model/error_type_handler/unknown_uri_exception.dart';
import 'package:model/model.dart';
import 'package:open_file/open_file.dart' as open_file;
import 'package:pointer_interceptor/pointer_interceptor.dart';
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/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/base/state/button_state.dart';
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.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/event_action.dart';
@@ -43,9 +40,6 @@ import 'package:tmail_ui_user/features/email/domain/state/calendar_event_counter
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_maybe_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reject_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.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/export_all_attachments_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/get_entire_message_as_document_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
@@ -57,8 +51,6 @@ import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_stat
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_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_entire_message_as_document_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
@@ -71,7 +63,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
import 'package:tmail_ui_user/features/email/presentation/bindings/calendar_event_interactor_bindings.dart';
import 'package:tmail_ui_user/features/email/presentation/bindings/mdn_interactor_bindings.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_attendee_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_organizer_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/handle_mail_action_by_shortcut_action_extension.dart';
@@ -84,12 +75,11 @@ import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscrib
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_attachment_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preview_attachment_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
@@ -121,12 +111,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
final GetEmailContentInteractor _getEmailContentInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final ExportAttachmentInteractor _exportAttachmentInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
final StoreOpenedEmailInteractor _storeOpenedEmailInteractor;
final PrintEmailInteractor _printEmailInteractor;
final ExportAllAttachmentsInteractor _exportAllAttachmentsInteractor;
final EmailId? _currentEmailId;
CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
@@ -193,12 +181,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
SingleEmailController(
this._getEmailContentInteractor,
this._markAsEmailReadInteractor,
this._exportAttachmentInteractor,
this._markAsStarEmailInteractor,
this._getAllIdentitiesInteractor,
this._storeOpenedEmailInteractor,
this._printEmailInteractor,
this._exportAllAttachmentsInteractor, {
this._printEmailInteractor, {
EmailId? currentEmailId,
}) : _currentEmailId = currentEmailId;
@@ -236,10 +222,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_getEmailContentOfflineSuccess(success);
} else if (success is MarkAsEmailReadSuccess) {
_handleMarkAsEmailReadCompleted(success);
} else if (success is ExportAttachmentSuccess) {
_exportAttachmentSuccessAction(success);
} else if (success is ExportAllAttachmentsSuccess) {
_exportAllAttachmentsSuccessAction(success);
} else if (success is MarkAsStarEmailSuccess) {
_markAsEmailStarSuccess(success);
} else if (success is GetAllIdentitiesSuccess) {
@@ -267,10 +249,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
void handleFailureViewState(Failure failure) {
if (failure is MarkAsEmailReadFailure) {
_handleMarkAsEmailReadFailure(failure);
} else if (failure is ExportAttachmentFailure) {
_exportAttachmentFailureAction(failure);
} else if (failure is ExportAllAttachmentsFailure) {
_exportAllAttachmentsFailureAction(failure);
} else if (failure is ParseCalendarEventFailure) {
_handleParseCalendarEventFailure(failure);
} else if (failure is GetEmailContentFailure) {
@@ -697,173 +675,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_threadDetailController?.markCollapsedEmailReadSuccess(success);
}
void exportAttachment(Attachment attachment) {
final cancelToken = CancelToken();
_showDownloadingFileDialog(attachment.name ?? '', cancelToken: cancelToken);
_exportAttachmentAction(attachment, cancelToken);
}
void _showDownloadingFileDialog(String attachmentName, {CancelToken? cancelToken}) {
if (cancelToken != null) {
Get.dialog(
PointerInterceptor(
child: Builder(
builder: (context) {
final appLocalizations = AppLocalizations.of(context);
return (DownloadingFileDialogBuilder()
..key(const Key('downloading_file_dialog'))
..title(appLocalizations.preparing_to_export)
..content(appLocalizations.downloading_file(attachmentName))
..actionText(appLocalizations.cancel)
..addCancelDownloadActionClick(() {
cancelToken.cancel([
appLocalizations.user_cancel_download_file,
]);
popBack();
}))
.build();
},
),
),
barrierDismissible: false,
);
} else {
Get.dialog(
PointerInterceptor(
child: Builder(
builder: (context) {
final appLocalizations = AppLocalizations.of(context);
return (DownloadingFileDialogBuilder()
..key(const Key('downloading_file_for_web_dialog'))
..title(appLocalizations.preparing_to_save)
..content(
appLocalizations.downloading_file(attachmentName),
))
.build();
},
),
),
);
}
}
void _exportAttachmentAction(Attachment attachment, CancelToken cancelToken) {
if (accountId != null && session != null) {
try {
final baseDownloadUrl = session!.getDownloadUrl(
jmapUrl: dynamicUrlInterceptors.jmapUrl,
);
consumeState(_exportAttachmentInteractor.execute(
attachment,
accountId!,
baseDownloadUrl,
cancelToken,
));
} catch (e) {
logError('SingleEmailController::_exportAttachmentAction(): $e');
consumeState(Stream.value(Left(ExportAttachmentFailure(e))));
}
} else {
consumeState(Stream.value(Left(ExportAttachmentFailure(NotFoundAccountIdException()))));
}
}
void exportAllAttachments(String outputFileName) {
final cancelToken = CancelToken();
_showDownloadingFileDialog(outputFileName, cancelToken: cancelToken);
_exportAllAttachmentsAction(outputFileName, cancelToken);
}
void _exportAllAttachmentsAction(String outputFileName, CancelToken cancelToken) {
if (accountId == null || session == null) {
consumeState(Stream.value(Left(ExportAllAttachmentsFailure(
exception: NotFoundSessionException(),
))));
return;
}
final downloadAllSupported = session!.isDownloadAllSupported(accountId);
if (!downloadAllSupported) {
consumeState(Stream.value(Left(ExportAllAttachmentsFailure())));
return;
}
final baseDownloadAllUrl = session!.getDownloadAllCapability(accountId)!.endpoint!;
consumeState(_exportAllAttachmentsInteractor.execute(
accountId!,
currentEmail!.id!,
baseDownloadAllUrl,
outputFileName,
cancelToken: cancelToken,
));
}
void _exportAttachmentFailureAction(ExportAttachmentFailure failure) {
if (failure.exception is! CancelDownloadFileException) {
if (Get.isDialogOpen == true) {
popBack();
}
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastErrorMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).attachment_download_failed);
}
}
}
void _exportAttachmentSuccessAction(ExportAttachmentSuccess success) async {
popBack();
_openDownloadedPreviewWorkGroupDocument(success.downloadedResponse);
}
void _exportAllAttachmentsFailureAction(ExportAllAttachmentsFailure failure) {
if (failure.exception is! CancelDownloadFileException) {
popBack();
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastErrorMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).attachment_download_failed);
}
}
}
void _exportAllAttachmentsSuccessAction(ExportAllAttachmentsSuccess success) {
popBack();
_saveFileToStorage(success.downloadedResponse.filePath);
}
void _openDownloadedPreviewWorkGroupDocument(DownloadedResponse downloadedResponse) async {
log('SingleEmailController::_openDownloadedPreviewWorkGroupDocument(): $downloadedResponse');
final filePath = downloadedResponse.filePath;
final mediaType = downloadedResponse.mediaType;
if (mediaType == null) {
_saveFileToStorage(filePath);
return;
}
final openResult = await open_file.OpenFile.open(
filePath,
type: Platform.isAndroid ? mediaType.mimeType : null,
// "xdg" is default value
linuxDesktopName: Platform.isIOS
? mediaType.getDocumentUti().value ?? 'xdg'
: 'xdg',
);
if (openResult.type != open_file.ResultType.done) {
logError('SingleEmailController::_openDownloadedPreviewWorkGroupDocument(): no preview available');
_saveFileToStorage(filePath);
}
}
Future<void> _saveFileToStorage(String filePath) async {
final params = SaveFileDialogParams(sourceFilePath: filePath);
await FlutterFileDialog.saveFile(params: params);
}
bool isDownloadAllSupported() {
return session?.isDownloadAllSupported(accountId) ?? false;
}
@@ -1059,7 +870,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_printEmail(presentationEmail);
break;
case EmailActionType.downloadMessageAsEML:
mailboxDashBoardController.downloadMessageAsEML(presentationEmail);
mailboxDashBoardController.downloadMessageAsEML(
presentationEmail: presentationEmail,
showBottomDownloadProgressBar: true,
);
break;
case EmailActionType.editAsNewEmail:
_editAsNewEmail(presentationEmail);
@@ -1100,8 +914,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
);
}
Future<void> openMailToLink(Uri? uri) =>
mailboxDashBoardController.openMailToLink(uri);
void openMailToLink(Uri? uri) {
if (uri == null) return;
mailboxDashBoardController.openComposerFromMailToLink(uri);
}
void deleteEmailPermanently(PresentationEmail email) {
emailActionReactor.deleteEmailPermanently(
@@ -1618,68 +1434,36 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
Attachment attachment,
{bool previewerSupported = false}
) {
if (PlatformInfo.isWeb) {
mailboxDashBoardController.downloadAttachmentForWeb(
attachment: attachment,
previewerSupported: previewerSupported,
);
} else if (PlatformInfo.isMobile) {
exportAttachment(attachment);
} else {
log('$runtimeType::handleDownloadAttachmentAction: THE PLATFORM IS SUPPORTED');
}
mailboxDashBoardController.downloadAttachment(
attachment: attachment,
previewerSupported: previewerSupported,
showBottomDownloadProgressBar: true,
sourceView: DownloadSourceView.emailView,
);
}
void handleDownloadAllAttachmentsAction(String outputFileName) {
if (PlatformInfo.isWeb) {
mailboxDashBoardController.downloadAllAttachmentsForWeb(
outputFileName: outputFileName,
currentEmail: currentEmail,
);
} else if (PlatformInfo.isMobile) {
exportAllAttachments(outputFileName);
} else {
log('EmailView::handleDownloadAllAttachmentsAction: THE PLATFORM IS SUPPORTED');
}
mailboxDashBoardController.downloadAllAttachments(
outputFileName: outputFileName,
emailId: currentEmail?.id,
showBottomDownloadProgressBar: true,
);
}
void handleViewAttachmentAction(BuildContext context, Attachment attachment) {
mailboxDashBoardController.previewAttachmentAction(
mailboxDashBoardController.previewAttachment(
context: context,
attachment: attachment,
onDownloadAttachment: (attachment) {
sourceView: DownloadSourceView.emailView,
onPreviewOrDownloadAction: (attachment, isPreview) {
handleDownloadAttachmentAction(
attachment,
previewerSupported: attachment.isPreviewSupported,
previewerSupported: isPreview,
);
},
);
}
Future<void> _openEMLPreviewer(BuildContext context, Uri? uri) async {
log('SingleEmailController::_openEMLPreviewer:uri = $uri');
if (uri == null) return;
final blobId = uri.path;
log('SingleEmailController::_openEMLPreviewer:blobId = $blobId');
if (blobId.isEmpty) return;
mailboxDashBoardController.previewEMLFileAction(
appLocalizations: AppLocalizations.of(context),
blobId: Id(blobId),
);
}
Future<void> _downloadAttachmentInEMLPreview(Uri? uri) async {
log('SingleEmailController::_downloadAttachmentInEMLPreview:uri = $uri');
if (uri == null) return;
final attachment = EmailUtils.parsingAttachmentByUri(uri);
if (attachment == null) return;
handleDownloadAttachmentAction(attachment);
}
void handleMailToAttendees(CalendarOrganizer? organizer, List<CalendarAttendee>? attendees) {
List<EmailAddress> listEmailAddressAttendees = [];
@@ -1745,9 +1529,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
content: success.messageDocument,
),
imagePaths: imagePaths,
onMailtoAction: openMailToLink,
onPreviewAction: (uri) => _openEMLPreviewer(context, uri),
onDownloadAction: _downloadAttachmentInEMLPreview,
onMailtoAction: (uri) async => openMailToLink(uri),
onDownloadFileAction: handleDownloadAttachmentAction,
);
},
onFailure: (_) {
@@ -336,7 +336,7 @@ class EmailView extends GetWidget<SingleEmailController> {
Obx(() => CalendarEventDetailWidget(
calendarEvent: calendarEvent,
emailContent: controller.currentEmailLoaded.value?.htmlContent ?? '',
onMailtoDelegateAction: controller.openMailToLink,
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
presentationEmail: controller.currentEmail,
scrollController: scrollController,
isInsideThreadDetailView: isInsideThreadDetailView,
@@ -385,7 +385,7 @@ class EmailView extends GetWidget<SingleEmailController> {
contentPadding: 0,
useDefaultFontStyle: true,
maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight,
onMailtoDelegateAction: controller.openMailToLink,
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
onHtmlContentClippedAction: controller.onHtmlContentClippedAction,
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
keepAlive: isInsideThreadDetailView,
@@ -423,7 +423,7 @@ class EmailView extends GetWidget<SingleEmailController> {
direction: AppUtils.getCurrentDirection(context),
contentPadding: 0,
useDefaultFontStyle: true,
onMailtoDelegateAction: controller.openMailToLink,
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
keepAlive: isInsideThreadDetailView,
enableQuoteToggle: true,
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
@@ -474,8 +474,7 @@ class EmailView extends GetWidget<SingleEmailController> {
),
onTapShowAllAttachmentFile: controller.showAllAttachmentsAction,
onTapHideAllAttachments: controller.hideAllAttachmentsAction,
showDownloadAllAttachmentsButton:
controller.downloadAllButtonIsEnabled(),
showDownloadAllAttachmentsButton: controller.downloadAllButtonIsEnabled(),
onTapDownloadAllButton: () =>
controller.handleDownloadAllAttachmentsAction(
'TwakeMail-${DateTime.now()}',
@@ -1,444 +0,0 @@
import 'dart:typed_data';
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.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/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
import 'package:model/extensions/session_extension.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_html_content_from_attachment_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart';
import 'package:tmail_ui_user/features/email_previewer/email_previewer_dialog_view.dart';
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart';
import 'package:tmail_ui_user/main/utils/toast_manager.dart';
typedef OnDownloadAttachmentAction = void Function(Attachment attachment);
mixin PreviewAttachmentMixin {
final DownloadManager _downloadManager = Get.find<DownloadManager>();
final PrintUtils _printUtils = Get.find<PrintUtils>();
final AppToast _appToast = Get.find<AppToast>();
final ToastManager _toastManager = Get.find<ToastManager>();
final DynamicUrlInterceptors _dynamicUrlInterceptors =
Get.find<DynamicUrlInterceptors>();
void previewAttachmentAction({
required BuildContext context,
required Attachment attachment,
required AccountId? accountId,
required Session? session,
required String ownEmailAddress,
required BaseController controller,
required ParseEmailByBlobIdInteractor parseEmailInteractor,
required GetHtmlContentFromAttachmentInteractor getHtmlInteractor,
required OnDownloadAttachmentAction onDownloadAttachment,
}) {
if (PlatformInfo.isWeb && attachment.isPDFFile) {
_previewPDFFile(
context: context,
attachment: attachment,
accountId: accountId,
session: session,
);
} else if (attachment.isEMLFile) {
previewEMLFileAction(
appLocalizations: AppLocalizations.of(context),
accountId: accountId,
session: session,
ownEmailAddress: ownEmailAddress,
blobId: attachment.blobId,
controller: controller,
parseEmailByBlobIdInteractor: parseEmailInteractor,
);
} else if (attachment.isHTMLFile) {
_previewHtmlFileAction(
session: session,
accountId: accountId,
attachment: attachment,
controller: controller,
getHtmlInteractor: getHtmlInteractor,
);
} else {
onDownloadAttachment(attachment);
}
}
Future<void> _previewPDFFile({
required BuildContext context,
required Attachment attachment,
required AccountId? accountId,
required Session? session,
}) async {
if (accountId == null || session == null) {
_appToast.showToastErrorMessage(
context,
AppLocalizations.of(context).noPreviewAvailable,
);
return;
}
try {
final downloadUrl = session.getDownloadUrl(
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
);
await Get.generalDialog(
barrierColor: Colors.black.withValues(alpha: 0.8),
pageBuilder: (_, __, ___) {
return PointerInterceptor(
child: PDFViewer(
attachment: attachment,
accountId: accountId,
downloadUrl: downloadUrl,
downloadAction: _downloadPDFFile,
printAction: _printPDFFile,
),
);
},
);
} catch (e) {
if (context.mounted) {
_appToast.showToastErrorMessage(
context,
AppLocalizations.of(context).noPreviewAvailable,
);
}
}
}
void _downloadPDFFile(Uint8List bytes, String fileName) {
_downloadManager.createAnchorElementDownloadFileWeb(bytes, fileName);
}
Future<void> _printPDFFile(Uint8List bytes, String fileName) async {
await _printUtils.printPDFFile(bytes, fileName);
}
void previewEMLFileAction({
required AppLocalizations appLocalizations,
required AccountId? accountId,
required Session? session,
required String ownEmailAddress,
required Id? blobId,
required ParseEmailByBlobIdInteractor parseEmailByBlobIdInteractor,
required BaseController controller,
}) {
SmartDialog.showLoading(
msg: appLocalizations.loadingPleaseWait,
maskColor: Colors.black38,
);
if (session == null) {
_emitFailure(
controller: controller,
failure: ParseEmailByBlobIdFailure(NotFoundSessionException()),
);
return;
}
if (accountId == null) {
_emitFailure(
controller: controller,
failure: ParseEmailByBlobIdFailure(NotFoundAccountIdException()),
);
return;
}
if (blobId == null) {
_emitFailure(
controller: controller,
failure: ParseEmailByBlobIdFailure(NotFoundBlobIdException([])),
);
return;
}
controller.consumeState(
parseEmailByBlobIdInteractor.execute(
accountId,
session,
ownEmailAddress,
blobId,
),
);
}
({
bool canDownloadAttachment,
AccountId? accountId,
String? downloadUrl,
Id? blobId,
}) evaluateAttachment({
required Session? session,
required AccountId? accountId,
required Attachment attachment,
}) {
String? downloadUrl;
try {
downloadUrl = session?.getDownloadUrl(
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
);
} catch (e) {
downloadUrl = null;
}
final blobId = attachment.blobId;
if (accountId == null || downloadUrl == null || blobId == null) {
return (
canDownloadAttachment: false,
accountId: accountId,
downloadUrl: downloadUrl,
blobId: blobId,
);
}
return (
canDownloadAttachment: true,
accountId: accountId,
downloadUrl: downloadUrl,
blobId: blobId,
);
}
void _previewHtmlFileAction({
required Session? session,
required AccountId? accountId,
required Attachment attachment,
required BaseController controller,
required GetHtmlContentFromAttachmentInteractor getHtmlInteractor,
}) {
final attachmentEvaluation = evaluateAttachment(
accountId: accountId,
session: session,
attachment: attachment,
);
if (!attachmentEvaluation.canDownloadAttachment) {
_emitFailure(
controller: controller,
failure: GetHtmlContentFromAttachmentFailure(
exception: null,
attachment: attachment,
),
);
return;
}
controller.consumeState(
getHtmlInteractor.execute(
attachmentEvaluation.accountId!,
attachment,
DownloadTaskId(attachmentEvaluation.blobId!.value),
attachmentEvaluation.downloadUrl!,
TransformConfiguration.create(
customDomTransformers: [SanitizeHyperLinkTagInHtmlTransformer()],
customTextTransformers: [
const StandardizeHtmlSanitizingTransformers()
],
),
),
);
}
void _emitFailure({
required BaseController controller,
required FeatureFailure failure,
}) {
controller.consumeState(Stream.value(Left(failure)));
}
void handleParseEmailByBlobIdSuccess({
required BuildContext? context,
required AccountId? accountId,
required Session? session,
required String ownEmailAddress,
required Id blobId,
required Email email,
required BaseController controller,
required PreviewEmailFromEmlFileInteractor previewInteractor,
}) {
if (session == null) {
_emitFailure(
controller: controller,
failure: PreviewEmailFromEmlFileFailure(NotFoundSessionException()),
);
return;
}
if (accountId == null) {
_emitFailure(
controller: controller,
failure: PreviewEmailFromEmlFileFailure(NotFoundAccountIdException()),
);
return;
}
if (context == null) {
_emitFailure(
controller: controller,
failure: PreviewEmailFromEmlFileFailure(NotFoundContextException()),
);
return;
}
try {
controller.consumeState(previewInteractor.execute(
PreviewEmailEMLRequest(
accountId: accountId,
session: session,
ownEmailAddress: ownEmailAddress,
blobId: blobId,
email: email,
locale: Localizations.localeOf(context),
appLocalizations: AppLocalizations.of(context),
baseDownloadUrl: session.getDownloadUrl(
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
),
),
));
} catch (e) {
_emitFailure(
controller: controller,
failure: PreviewEmailFromEmlFileFailure(e),
);
}
}
void handleParseEmailByBlobIdFailure(ParseEmailByBlobIdFailure failure) {
SmartDialog.dismiss();
_toastManager.showMessageFailure(failure);
}
void handlePreviewEmailFromEMLFileFailure(
PreviewEmailFromEmlFileFailure failure,
) {
SmartDialog.dismiss();
_toastManager.showMessageFailure(failure);
}
void handlePreviewEmailFromEMLFileSuccess({
required EMLPreviewer emlPreviewer,
required BuildContext? context,
required ImagePaths imagePaths,
required OnMailtoDelegateAction onMailtoAction,
required OnDownloadAttachmentDelegateAction onDownloadAction,
required OnPreviewEMLDelegateAction onPreviewAction,
}) {
SmartDialog.dismiss();
if (PlatformInfo.isWeb) {
bool isOpen = HtmlUtils.openNewWindowByUrl(
RouteUtils.createUrlWebLocationBar(
AppRoutes.emailEMLPreviewer,
previewId: emlPreviewer.id,
).toString(),
);
if (!isOpen) {
_toastManager.showMessageFailure(
PreviewEmailFromEmlFileFailure(CannotOpenNewWindowException()),
);
}
} else if (PlatformInfo.isMobile) {
if (context == null) {
_toastManager.showMessageFailure(
PreviewEmailFromEmlFileFailure(NotFoundContextException()),
);
return;
}
if (PlatformInfo.isAndroid) {
showModalSheetToPreviewEMLAttachment(
context: context,
emlPreviewer: emlPreviewer,
imagePaths: imagePaths,
onMailtoAction: onMailtoAction,
onDownloadAction: onDownloadAction,
onPreviewAction: onPreviewAction,
);
} else if (PlatformInfo.isIOS) {
showDialogToPreviewEMLAttachment(
context: context,
emlPreviewer: emlPreviewer,
imagePaths: imagePaths,
onMailtoAction: onMailtoAction,
onDownloadAction: onDownloadAction,
onPreviewAction: onPreviewAction,
);
}
}
}
void showModalSheetToPreviewEMLAttachment({
required BuildContext context,
required EMLPreviewer emlPreviewer,
required ImagePaths imagePaths,
required OnMailtoDelegateAction onMailtoAction,
required OnDownloadAttachmentDelegateAction onDownloadAction,
required OnPreviewEMLDelegateAction onPreviewAction,
}) {
showModalBottomSheet(
context: context,
showDragHandle: true,
useSafeArea: true,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
builder: (_) {
return DraggableScrollableSheet(
initialChildSize: 1.0,
builder: (context, ___) => EmailPreviewerDialogView(
emlPreviewer: emlPreviewer,
imagePaths: imagePaths,
onMailtoDelegateAction: onMailtoAction,
onPreviewEMLDelegateAction: onPreviewAction,
onDownloadAttachmentDelegateAction: onDownloadAction,
),
);
},
);
}
void showDialogToPreviewEMLAttachment({
required BuildContext context,
required EMLPreviewer emlPreviewer,
required ImagePaths imagePaths,
required OnMailtoDelegateAction onMailtoAction,
required OnDownloadAttachmentDelegateAction onDownloadAction,
required OnPreviewEMLDelegateAction onPreviewAction,
}) {
Get.dialog(
EmailPreviewerDialogView(
emlPreviewer: emlPreviewer,
imagePaths: imagePaths,
onMailtoDelegateAction: onMailtoAction,
onPreviewEMLDelegateAction: onPreviewAction,
onDownloadAttachmentDelegateAction: onDownloadAction,
),
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
);
}
}
@@ -14,8 +14,8 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/email/attachment.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/get_html_content_from_attachment_state.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_and_get_html_content_from_attachment_state.dart';
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
@@ -83,11 +83,11 @@ class EmailUtils {
return state?.fold(
(failure) {
return failure is DownloadAttachmentForWebFailure
|| failure is GetHtmlContentFromAttachmentFailure;
|| failure is DownloadAndGetHtmlContentFromAttachmentFailure;
},
(success) {
return success is DownloadAttachmentForWebSuccess
|| success is GetHtmlContentFromAttachmentSuccess
|| success is DownloadAndGetHtmlContentFromAttachmentSuccess
|| success is IdleDownloadAttachmentForWeb;
}) ?? false;
}
@@ -13,9 +13,9 @@ import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:model/download/download_task_id.dart';
import 'package:model/email/attachment.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/download_attachment_exceptions.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_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/download/domain/exceptions/download_attachment_exceptions.dart';
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
import 'package:tmail_ui_user/features/download/domain/usecase/download_attachment_for_web_interactor.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:twake_previewer_flutter/core/previewer_options/options/loading_options.dart';