TF-4050 Preview and download uploaded file in composer on web
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
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/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
|
||||
abstract class DownloadDatasource {
|
||||
Future<Uint8List> downloadAttachmentForWeb(
|
||||
DownloadTaskId taskId,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<void> downloadAllAttachmentsForWeb(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
DownloadTaskId taskId, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
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/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
||||
import 'package:tmail_ui_user/features/download/data/datasource/download_datasource.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
|
||||
|
||||
class DownloadDatasourceImpl extends DownloadDatasource {
|
||||
final EmailAPI _emailAPI;
|
||||
final ExceptionThrower _exceptionThrower;
|
||||
|
||||
DownloadDatasourceImpl(this._emailAPI, this._exceptionThrower);
|
||||
|
||||
@override
|
||||
Future<Uint8List> downloadAttachmentForWeb(
|
||||
DownloadTaskId taskId,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
}) {
|
||||
return Future.sync(() async {
|
||||
return await _emailAPI.downloadAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
accountRequest,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
}).catchError((error, stackTrace) async {
|
||||
await _exceptionThrower.throwException(error, stackTrace);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> downloadAllAttachmentsForWeb(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
DownloadTaskId taskId,
|
||||
{StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken}) {
|
||||
return Future.sync(() async {
|
||||
return await _emailAPI.downloadAllAttachmentsForWeb(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
taskId,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
}).catchError((error, stackTrace) async {
|
||||
await _exceptionThrower.throwException(error, stackTrace);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
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/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/download/data/datasource/download_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
|
||||
|
||||
class DownloadRepositoryImpl extends DownloadRepository {
|
||||
final DownloadDatasource _downloadDatasource;
|
||||
final Map<DataSourceType, EmailDataSource> _emailDataSource;
|
||||
final HtmlDataSource _htmlDataSource;
|
||||
|
||||
DownloadRepositoryImpl(
|
||||
this._downloadDatasource,
|
||||
this._emailDataSource,
|
||||
this._htmlDataSource,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Uint8List> downloadAttachmentForWeb(
|
||||
DownloadTaskId taskId,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
}) {
|
||||
return _downloadDatasource.downloadAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
accountRequest,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> downloadAllAttachmentsForWeb(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
DownloadTaskId taskId, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
}) {
|
||||
return _downloadDatasource.downloadAllAttachmentsForWeb(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
taskId,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> sanitizeHtmlContent(
|
||||
String htmlContent,
|
||||
TransformConfiguration configuration,
|
||||
) {
|
||||
return _htmlDataSource.transformHtmlEmailContent(
|
||||
htmlContent,
|
||||
configuration,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Email>> parseEmailByBlobIds(
|
||||
AccountId accountId,
|
||||
Set<Id> blobIds,
|
||||
) {
|
||||
return _emailDataSource[DataSourceType.network]!
|
||||
.parseEmailByBlobIds(accountId, blobIds);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> generatePreviewEmailEMLContent(
|
||||
PreviewEmailEMLRequest previewEmailEMLRequest,
|
||||
) {
|
||||
return _emailDataSource[DataSourceType.network]!
|
||||
.generatePreviewEmailEMLContent(previewEmailEMLRequest);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> storePreviewEMLContentToSessionStorage(
|
||||
EMLPreviewer emlPreviewer,
|
||||
) {
|
||||
return _emailDataSource[DataSourceType.session]!
|
||||
.storePreviewEMLContentToSessionStorage(emlPreviewer);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sharePreviewEmailEMLContent(EMLPreviewer emlPreviewer) {
|
||||
return _emailDataSource[DataSourceType.local]!
|
||||
.sharePreviewEmailEMLContent(emlPreviewer);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EMLPreviewer> getPreviewEmailEMLContentShared(String keyStored) {
|
||||
return _emailDataSource[DataSourceType.local]!
|
||||
.getPreviewEmailEMLContentShared(keyStored);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removePreviewEmailEMLContentShared(String keyStored) {
|
||||
return _emailDataSource[DataSourceType.local]!
|
||||
.removePreviewEmailEMLContentShared(keyStored);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EMLPreviewer> getPreviewEMLContentInMemory(String keyStored) {
|
||||
return _emailDataSource[DataSourceType.session]!
|
||||
.getPreviewEMLContentInMemory(keyStored);
|
||||
}
|
||||
|
||||
@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<DownloadedResponse> exportAllAttachments(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
CancelToken cancelToken,
|
||||
) {
|
||||
return _emailDataSource[DataSourceType.network]!.exportAllAttachments(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class DownloadAttachmentInteractorIsNull implements Exception {}
|
||||
|
||||
class CapabilityDownloadAllNotSupportedException implements Exception {}
|
||||
|
||||
class DownloadUrlIsNullException implements Exception {}
|
||||
@@ -0,0 +1,4 @@
|
||||
enum DownloadSourceView {
|
||||
emailView,
|
||||
composerView;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:core/data/network/download/downloaded_response.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.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/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
|
||||
|
||||
abstract class DownloadRepository {
|
||||
Future<Uint8List> downloadAttachmentForWeb(
|
||||
DownloadTaskId taskId,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<void> downloadAllAttachmentsForWeb(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
DownloadTaskId taskId, {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<String> sanitizeHtmlContent(
|
||||
String htmlContent,
|
||||
TransformConfiguration configuration,
|
||||
);
|
||||
|
||||
Future<List<Email>> parseEmailByBlobIds(AccountId accountId, Set<Id> blobIds);
|
||||
|
||||
Future<String> generatePreviewEmailEMLContent(
|
||||
PreviewEmailEMLRequest previewEmailEMLRequest,
|
||||
);
|
||||
|
||||
Future<void> sharePreviewEmailEMLContent(EMLPreviewer emlPreviewer);
|
||||
|
||||
Future<void> storePreviewEMLContentToSessionStorage(
|
||||
EMLPreviewer emlPreviewer,
|
||||
);
|
||||
|
||||
Future<EMLPreviewer> getPreviewEmailEMLContentShared(String keyStored);
|
||||
|
||||
Future<void> removePreviewEmailEMLContentShared(String keyStored);
|
||||
|
||||
Future<EMLPreviewer> getPreviewEMLContentInMemory(String keyStored);
|
||||
|
||||
Future<DownloadedResponse> exportAttachment(
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest,
|
||||
CancelToken cancelToken,
|
||||
);
|
||||
|
||||
Future<DownloadedResponse> exportAllAttachments(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
CancelToken cancelToken,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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];
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
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:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
|
||||
|
||||
class DownloadAndGettingHtmlContentFromAttachment extends LoadingState {
|
||||
DownloadAndGettingHtmlContentFromAttachment({
|
||||
required this.blobId,
|
||||
this.sourceView,
|
||||
});
|
||||
|
||||
final Id? blobId;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [blobId, sourceView];
|
||||
}
|
||||
|
||||
class DownloadAndGetHtmlContentFromAttachmentSuccess extends UIState {
|
||||
DownloadAndGetHtmlContentFromAttachmentSuccess({
|
||||
required this.sanitizedHtmlContent,
|
||||
required this.htmlAttachmentTitle,
|
||||
required this.attachment,
|
||||
required this.accountId,
|
||||
required this.session,
|
||||
this.sourceView,
|
||||
});
|
||||
|
||||
final String sanitizedHtmlContent;
|
||||
final String htmlAttachmentTitle;
|
||||
final Attachment attachment;
|
||||
final AccountId accountId;
|
||||
final Session session;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
sanitizedHtmlContent,
|
||||
htmlAttachmentTitle,
|
||||
attachment,
|
||||
accountId,
|
||||
session,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadAndGetHtmlContentFromAttachmentFailure extends FeatureFailure {
|
||||
DownloadAndGetHtmlContentFromAttachmentFailure({
|
||||
super.exception,
|
||||
required this.blobId,
|
||||
this.sourceView,
|
||||
});
|
||||
|
||||
final Id? blobId;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [blobId, sourceView];
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
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';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
|
||||
|
||||
class IdleDownloadAttachmentForWeb extends UIState {}
|
||||
|
||||
class StartDownloadAttachmentForWeb extends UIState {
|
||||
|
||||
final DownloadTaskId taskId;
|
||||
final Attachment attachment;
|
||||
final CancelToken? cancelToken;
|
||||
final bool previewerSupported;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
StartDownloadAttachmentForWeb(
|
||||
this.taskId,
|
||||
this.attachment, [
|
||||
this.cancelToken,
|
||||
this.previewerSupported = false,
|
||||
this.sourceView,
|
||||
]);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
cancelToken,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadingAttachmentForWeb extends UIState {
|
||||
|
||||
final DownloadTaskId taskId;
|
||||
final Attachment attachment;
|
||||
final double progress;
|
||||
final int downloaded;
|
||||
final int total;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadingAttachmentForWeb(
|
||||
this.taskId,
|
||||
this.attachment,
|
||||
this.progress,
|
||||
this.downloaded,
|
||||
this.total,
|
||||
this.sourceView,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
progress,
|
||||
downloaded,
|
||||
total,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadAttachmentForWebSuccess extends UIState {
|
||||
|
||||
final DownloadTaskId taskId;
|
||||
final Attachment attachment;
|
||||
final Uint8List bytes;
|
||||
final bool previewerSupported;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadAttachmentForWebSuccess(
|
||||
this.taskId,
|
||||
this.attachment,
|
||||
this.bytes,
|
||||
this.previewerSupported,
|
||||
this.sourceView,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
bytes,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadAttachmentForWebFailure extends FeatureFailure {
|
||||
|
||||
final DownloadTaskId? taskId;
|
||||
final Attachment? attachment;
|
||||
final CancelToken? cancelToken;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadAttachmentForWebFailure({
|
||||
this.attachment,
|
||||
this.taskId,
|
||||
this.cancelToken,
|
||||
this.sourceView,
|
||||
super.exception,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
attachment,
|
||||
taskId,
|
||||
cancelToken,
|
||||
sourceView,
|
||||
...super.props,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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});
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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:model/email/attachment.dart';
|
||||
|
||||
class GettingHtmlContentFromUploadFile extends LoadingState {}
|
||||
|
||||
class GetHtmlContentFromUploadFileSuccess extends UIState {
|
||||
GetHtmlContentFromUploadFileSuccess({
|
||||
required this.sanitizedHtmlContent,
|
||||
required this.htmlAttachmentTitle,
|
||||
required this.attachment,
|
||||
required this.accountId,
|
||||
required this.session,
|
||||
});
|
||||
|
||||
final String sanitizedHtmlContent;
|
||||
final String htmlAttachmentTitle;
|
||||
final Attachment attachment;
|
||||
final AccountId? accountId;
|
||||
final Session? session;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
sanitizedHtmlContent,
|
||||
htmlAttachmentTitle,
|
||||
attachment,
|
||||
accountId,
|
||||
session,
|
||||
];
|
||||
}
|
||||
|
||||
class GetHtmlContentFromUploadFileFailure extends FeatureFailure {
|
||||
GetHtmlContentFromUploadFileFailure({super.exception});
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
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];
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
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];
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
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';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class PreviewingEmailFromEmlFile extends LoadingState {}
|
||||
|
||||
class PreviewEmailFromEmlFileSuccess extends UIState {
|
||||
final EMLPreviewer emlPreviewer;
|
||||
final AccountId accountId;
|
||||
final Session session;
|
||||
final String ownEmailAddress;
|
||||
final AppLocalizations appLocalizations;
|
||||
|
||||
PreviewEmailFromEmlFileSuccess(
|
||||
this.emlPreviewer,
|
||||
this.accountId,
|
||||
this.session,
|
||||
this.ownEmailAddress,
|
||||
this.appLocalizations,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
emlPreviewer,
|
||||
accountId,
|
||||
session,
|
||||
ownEmailAddress,
|
||||
appLocalizations,
|
||||
];
|
||||
}
|
||||
|
||||
class PreviewEmailFromEmlFileFailure extends FeatureFailure {
|
||||
PreviewEmailFromEmlFileFailure(dynamic exception)
|
||||
: super(exception: exception);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
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/download/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/download/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,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
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:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.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/download/domain/state/download_and_get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_attachment_for_web_interactor.dart';
|
||||
|
||||
class DownloadAndGetHtmlContentFromAttachmentInteractor {
|
||||
DownloadAndGetHtmlContentFromAttachmentInteractor(
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
|
||||
|
||||
Stream<Either<Failure, Success>> execute(
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
Attachment attachment,
|
||||
DownloadTaskId taskId,
|
||||
String baseDownloadUrl,
|
||||
TransformConfiguration transformConfiguration, {
|
||||
DownloadSourceView? sourceView,
|
||||
}) async* {
|
||||
try {
|
||||
yield Right(DownloadAndGettingHtmlContentFromAttachment(
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
final downloadState = await _downloadAttachmentForWebInteractor.execute(
|
||||
taskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
sourceView: sourceView,
|
||||
).last;
|
||||
|
||||
Either<Failure, Success>? sanitizeState;
|
||||
await downloadState.fold(
|
||||
(failure) {
|
||||
sanitizeState = Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: failure is FeatureFailure ? failure.exception : null,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
},
|
||||
(success) async {
|
||||
if (success is! DownloadAttachmentForWebSuccess) {
|
||||
sanitizeState = Right(DownloadAndGettingHtmlContentFromAttachment(
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
} else {
|
||||
final htmlContent = StringConvert.decodeFromBytes(
|
||||
success.bytes,
|
||||
charset: success.attachment.charset,
|
||||
isHtml: true,
|
||||
);
|
||||
sanitizeState = await _sanitizeHtmlContent(
|
||||
htmlContent,
|
||||
transformConfiguration,
|
||||
attachment,
|
||||
accountId,
|
||||
session,
|
||||
sourceView,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (sanitizeState != null) {
|
||||
yield sanitizeState!;
|
||||
} else {
|
||||
yield Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: null,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
logError('GetHtmlContentFromAttachmentInteractor:exception: $e');
|
||||
yield Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: e,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, Success>?> _sanitizeHtmlContent(
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
DownloadSourceView? sourceView,
|
||||
) async {
|
||||
try {
|
||||
final sanitizedHtmlContent = await _downloadAttachmentForWebInteractor
|
||||
.downloadRepository
|
||||
.sanitizeHtmlContent(htmlContent, transformConfiguration);
|
||||
|
||||
return Right(DownloadAndGetHtmlContentFromAttachmentSuccess(
|
||||
sanitizedHtmlContent: sanitizedHtmlContent,
|
||||
htmlAttachmentTitle: attachment.generateFileName(),
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
} catch (e) {
|
||||
return Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: e,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
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/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/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/download/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,
|
||||
DownloadSourceView? sourceView,
|
||||
}) async* {
|
||||
try {
|
||||
final loadingState = Right<Failure, Success>(
|
||||
StartDownloadAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
cancelToken,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
),
|
||||
);
|
||||
yield loadingState;
|
||||
onReceiveController?.add(loadingState);
|
||||
|
||||
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,
|
||||
sourceView,
|
||||
)
|
||||
);
|
||||
} catch (exception) {
|
||||
yield Left<Failure, Success>(
|
||||
DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
taskId: taskId,
|
||||
sourceView: sourceView,
|
||||
cancelToken: cancelToken,
|
||||
exception: exception,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
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/download/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/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._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,
|
||||
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 _downloadRepository.exportAllAttachments(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
cancelToken,
|
||||
);
|
||||
|
||||
yield Right(ExportAllAttachmentsSuccess(result));
|
||||
} catch (e) {
|
||||
logError('ExportAllAttachmentsInteractor::execute():EXCEPTION: $e');
|
||||
yield Left(ExportAllAttachmentsFailure(exception: e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
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/download/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/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 DownloadRepository _downloadRepository;
|
||||
final CredentialRepository _credentialRepository;
|
||||
final AccountRepository _accountRepository;
|
||||
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
||||
|
||||
ExportAttachmentInteractor(
|
||||
this._downloadRepository,
|
||||
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 _downloadRepository.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/dom/sanitize_hyper_link_tag_in_html_transformers.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/text/standardize_html_sanitizing_transformers.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:core/utils/string_convert.dart';
|
||||
import 'package:dartz/dartz.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/download/domain/state/get_html_content_from_upload_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart';
|
||||
|
||||
class GetHtmlContentFromUploadFileInteractor {
|
||||
final DownloadRepository _downloadRepository;
|
||||
|
||||
GetHtmlContentFromUploadFileInteractor(this._downloadRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute({
|
||||
required UploadFileState uploadFile,
|
||||
required Session? session,
|
||||
required AccountId? accountId,
|
||||
}) async* {
|
||||
try {
|
||||
yield Right(GettingHtmlContentFromUploadFile());
|
||||
|
||||
final htmlContent = StringConvert.decodeFromBytes(
|
||||
uploadFile.file!.bytes!,
|
||||
charset: uploadFile.attachment!.charset,
|
||||
isHtml: true,
|
||||
);
|
||||
|
||||
final sanitizedHtmlContent =
|
||||
await _downloadRepository.sanitizeHtmlContent(
|
||||
htmlContent,
|
||||
TransformConfiguration.create(
|
||||
customDomTransformers: [SanitizeHyperLinkTagInHtmlTransformer()],
|
||||
customTextTransformers: [
|
||||
const StandardizeHtmlSanitizingTransformers()
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
yield Right(GetHtmlContentFromUploadFileSuccess(
|
||||
sanitizedHtmlContent: sanitizedHtmlContent,
|
||||
htmlAttachmentTitle: uploadFile.attachment!.generateFileName(),
|
||||
attachment: uploadFile.attachment!,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
));
|
||||
} catch (e) {
|
||||
yield Left(GetHtmlContentFromUploadFileFailure(exception: e));
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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/download/domain/state/get_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/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,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
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/download/domain/state/get_preview_eml_content_in_memory_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/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,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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/download/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/download/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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
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/download/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
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/download/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/download/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,
|
||||
previewEmailEMLRequest.appLocalizations,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
yield Left<Failure, Success>(PreviewEmailFromEmlFileFailure(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
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/download/domain/state/remove_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/caching/utils/local_storage_manager.dart';
|
||||
import 'package:tmail_ui_user/features/caching/utils/session_storage_manager.dart';
|
||||
import 'package:tmail_ui_user/features/download/data/datasource/download_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/download/data/datasource_impl/download_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/download/data/repository/download_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_all_attachments_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_and_get_html_content_from_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/get_html_content_from_upload_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/get_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/get_preview_eml_content_in_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/move_preview_eml_content_from_persistent_to_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/remove_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/network/email_api.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/main/exceptions/cache_exception_thrower.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
||||
|
||||
class DownloadInteractorBindings extends InteractorsBindings {
|
||||
@override
|
||||
void bindingsDataSourceImpl() {
|
||||
Get.lazyPut(
|
||||
() => DownloadDatasourceImpl(
|
||||
Get.find<EmailAPI>(),
|
||||
Get.find<RemoteExceptionThrower>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => EmailDataSourceImpl(
|
||||
Get.find<EmailAPI>(),
|
||||
Get.find<RemoteExceptionThrower>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<CacheExceptionThrower>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => EmailSessionStorageDatasourceImpl(
|
||||
Get.find<SessionStorageManager>(),
|
||||
Get.find<CacheExceptionThrower>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => EmailLocalStorageDataSourceImpl(
|
||||
Get.find<LocalStorageManager>(),
|
||||
Get.find<PreviewEmlFileUtils>(),
|
||||
Get.find<CacheExceptionThrower>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsInteractor() {
|
||||
Get.lazyPut(
|
||||
() => DownloadAttachmentForWebInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
Get.find<CredentialRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => DownloadAllAttachmentsForWebInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
Get.find<CredentialRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => ExportAttachmentInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
Get.find<CredentialRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => ExportAllAttachmentsInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
Get.find<CredentialRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => ParseEmailByBlobIdInteractor(Get.find<DownloadRepository>()),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => PreviewEmailFromEmlFileInteractor(Get.find<DownloadRepository>()),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => DownloadAndGetHtmlContentFromAttachmentInteractor(
|
||||
Get.find<DownloadAttachmentForWebInteractor>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => MovePreviewEmlContentFromPersistentToMemoryInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => RemovePreviewEmailEmlContentSharedInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
|
||||
Get.lazyPut(
|
||||
() => GetPreviewEmailEMLContentSharedInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => GetPreviewEmlContentInMemoryInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => GetHtmlContentFromUploadFileInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsRepository() {
|
||||
Get.lazyPut<DownloadRepository>(() => Get.find<DownloadRepositoryImpl>());
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsRepositoryImpl() {
|
||||
Get.lazyPut(
|
||||
() => DownloadRepositoryImpl(
|
||||
Get.find<DownloadDatasource>(),
|
||||
{
|
||||
DataSourceType.session: Get.find<EmailSessionStorageDatasourceImpl>(),
|
||||
DataSourceType.local: Get.find<EmailLocalStorageDataSourceImpl>(),
|
||||
DataSourceType.network: Get.find<EmailDataSource>(),
|
||||
},
|
||||
Get.find<HtmlDataSource>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsDataSource() {
|
||||
Get.lazyPut<DownloadDatasource>(() => Get.find<DownloadDatasourceImpl>());
|
||||
Get.lazyPut<EmailDataSource>(() => Get.find<EmailDataSourceImpl>());
|
||||
Get.lazyPut<HtmlDataSource>(() => Get.find<HtmlDataSourceImpl>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/network/download/download_manager.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/print_utils.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.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_and_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/export_all_attachments_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/export_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/get_html_content_from_upload_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_all_attachments_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_and_get_html_content_from_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/get_html_content_from_upload_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/extensions/download_attachment_download_controller_extension.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/extensions/preview_attachment_download_controller_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/download/download_task_state.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
typedef UpdateDownloadTaskStateCallback = DownloadTaskState Function(DownloadTaskState currentState);
|
||||
|
||||
class DownloadController extends BaseController {
|
||||
final DownloadManager downloadManager;
|
||||
final PrintUtils printUtils;
|
||||
final DownloadAttachmentForWebInteractor downloadAttachmentForWebInteractor;
|
||||
final DownloadAllAttachmentsForWebInteractor
|
||||
downloadAllAttachmentsForWebInteractor;
|
||||
final ParseEmailByBlobIdInteractor parseEmailByBlobIdInteractor;
|
||||
final PreviewEmailFromEmlFileInteractor previewEmailFromEmlFileInteractor;
|
||||
final DownloadAndGetHtmlContentFromAttachmentInteractor
|
||||
downloadAndGetHtmlContentFromAttachmentInteractor;
|
||||
final GetHtmlContentFromUploadFileInteractor
|
||||
getHtmlContentFromUploadFileInteractor;
|
||||
final ExportAttachmentInteractor exportAttachmentInteractor;
|
||||
final ExportAllAttachmentsInteractor exportAllAttachmentsInteractor;
|
||||
|
||||
DownloadController(
|
||||
this.downloadManager,
|
||||
this.printUtils,
|
||||
this.downloadAttachmentForWebInteractor,
|
||||
this.downloadAllAttachmentsForWebInteractor,
|
||||
this.parseEmailByBlobIdInteractor,
|
||||
this.previewEmailFromEmlFileInteractor,
|
||||
this.downloadAndGetHtmlContentFromAttachmentInteractor,
|
||||
this.getHtmlContentFromUploadFileInteractor,
|
||||
this.exportAttachmentInteractor,
|
||||
this.exportAllAttachmentsInteractor,
|
||||
);
|
||||
|
||||
final listDownloadTaskState = RxList<DownloadTaskState>();
|
||||
final hideDownloadTaskbar = RxBool(false);
|
||||
final downloadUIAction = Rxn<DownloadUIAction>();
|
||||
|
||||
final downloadProgressStateController =
|
||||
StreamController<Either<Failure, Success>>.broadcast();
|
||||
StreamSubscription<Either<Failure, Success>>?
|
||||
_downloadProgressStateSubscription;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_registerDownloadProgressState();
|
||||
}
|
||||
|
||||
void _registerDownloadProgressState() {
|
||||
_downloadProgressStateSubscription = downloadProgressStateController.stream
|
||||
.listen(_onDownloadProgressStateChanged);
|
||||
}
|
||||
|
||||
void _onDownloadProgressStateChanged(Either<Failure, Success> state) {
|
||||
state.fold((_) => null, (success) {
|
||||
if (success is StartDownloadAttachmentForWeb) {
|
||||
_handleStartSingleDownload(success);
|
||||
} else if (success is DownloadingAttachmentForWeb) {
|
||||
_updateDownloadProgress(
|
||||
success.taskId,
|
||||
success.progress,
|
||||
success.downloaded,
|
||||
success.total,
|
||||
);
|
||||
} else if (success is StartDownloadAllAttachmentsForWeb) {
|
||||
_handleStartAllDownload(success);
|
||||
} else if (success is DownloadingAllAttachmentsForWeb) {
|
||||
_updateDownloadProgress(
|
||||
success.taskId,
|
||||
success.progress,
|
||||
success.downloaded,
|
||||
success.total,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _handleStartSingleDownload(StartDownloadAttachmentForWeb success) {
|
||||
if (success.previewerSupported) return;
|
||||
|
||||
addDownloadTask(
|
||||
DownloadTaskState(
|
||||
taskId: success.taskId,
|
||||
attachment: success.attachment,
|
||||
onCancel: success.cancelToken?.cancel,
|
||||
),
|
||||
);
|
||||
|
||||
if (_hasValidContext) {
|
||||
appToast.showToastMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).your_download_has_started,
|
||||
leadingSVGIconColor: AppColor.primaryColor,
|
||||
leadingSVGIcon: imagePaths.icDownload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleStartAllDownload(StartDownloadAllAttachmentsForWeb success) {
|
||||
addDownloadTask(
|
||||
DownloadTaskState(
|
||||
taskId: success.taskId,
|
||||
attachment: success.attachment,
|
||||
onCancel: () => success.cancelToken?.cancel(),
|
||||
),
|
||||
);
|
||||
|
||||
if (_hasValidContext) {
|
||||
appToast.showToastSuccessMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).creatingAnArchiveForDownloading,
|
||||
leadingSVGIconColor: Colors.white,
|
||||
leadingSVGIcon: imagePaths.icDownloadAll,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _updateDownloadProgress(
|
||||
DownloadTaskId taskId,
|
||||
double progress,
|
||||
int downloaded,
|
||||
int total,
|
||||
) {
|
||||
final percent = progress.round();
|
||||
log('$runtimeType::_updateDownloadProgress(): $percent%');
|
||||
|
||||
updateDownloadTaskByTaskId(taskId, (currentTask) {
|
||||
return currentTask.copyWith(
|
||||
progress: progress,
|
||||
downloaded: downloaded,
|
||||
total: total,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
bool get _hasValidContext =>
|
||||
currentOverlayContext != null && currentContext != null;
|
||||
|
||||
bool get notEmptyListDownloadTask => listDownloadTaskState.isNotEmpty;
|
||||
|
||||
void addDownloadTask(DownloadTaskState task) {
|
||||
log('DownloadController::addDownloadTask(): ${task.taskId}');
|
||||
listDownloadTaskState.add(task);
|
||||
hideDownloadTaskbar.value = false;
|
||||
}
|
||||
|
||||
void updateDownloadTaskByTaskId(
|
||||
DownloadTaskId downloadTaskId,
|
||||
UpdateDownloadTaskStateCallback updateDownloadTaskCallback,
|
||||
) {
|
||||
final matchIndex = listDownloadTaskState
|
||||
.indexWhere((task) => task.taskId == downloadTaskId);
|
||||
if (matchIndex >= 0) {
|
||||
listDownloadTaskState[matchIndex] = updateDownloadTaskCallback(listDownloadTaskState[matchIndex]);
|
||||
listDownloadTaskState.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void deleteDownloadTask(DownloadTaskId taskId) {
|
||||
log('DownloadController::deleteDownloadTask(): $taskId');
|
||||
final matchIndex = listDownloadTaskState
|
||||
.indexWhere((task) => task.taskId == taskId);
|
||||
if (matchIndex >= 0) {
|
||||
listDownloadTaskState.removeAt(matchIndex);
|
||||
listDownloadTaskState.refresh();
|
||||
}
|
||||
if (listDownloadTaskState.isEmpty) {
|
||||
hideDownloadTaskbar.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
void pushDownloadUIAction(DownloadUIAction action) {
|
||||
downloadUIAction.value = action;
|
||||
}
|
||||
|
||||
void clearDownloadUIAction() {
|
||||
downloadUIAction.value = null;
|
||||
}
|
||||
|
||||
@override
|
||||
void handleSuccessViewState(Success success) {
|
||||
if (success is DownloadAttachmentForWebSuccess) {
|
||||
handleDownloadAttachmentForWebSuccess(success);
|
||||
} else if (success is StartDownloadAttachmentForWeb &&
|
||||
success.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
));
|
||||
} else if (success is DownloadingAttachmentForWeb &&
|
||||
success.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
));
|
||||
} else if (success is DownloadAllAttachmentsForWebSuccess) {
|
||||
deleteDownloadTask(success.taskId);
|
||||
} else if (success is ParseEmailByBlobIdSuccess) {
|
||||
handleParseEmailByBlobIdSuccess(
|
||||
context: currentContext,
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
ownEmailAddress: success.ownEmailAddress,
|
||||
blobId: success.blobId,
|
||||
email: success.email,
|
||||
);
|
||||
} else if (success is PreviewEmailFromEmlFileSuccess) {
|
||||
handlePreviewEmailFromEmlFileSuccess(success);
|
||||
} else if (success is DownloadAndGetHtmlContentFromAttachmentSuccess) {
|
||||
handleDownloadAndGetHtmlContentFromAttachmentSuccess(success);
|
||||
} else if (success is DownloadAndGettingHtmlContentFromAttachment &&
|
||||
success.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
success.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
),
|
||||
);
|
||||
} else if (success is ExportAttachmentSuccess) {
|
||||
exportAttachmentSuccessAction(success.downloadedResponse);
|
||||
} else if (success is ExportAllAttachmentsSuccess) {
|
||||
exportAllAttachmentsSuccessAction(success.downloadedResponse.filePath);
|
||||
} else if (success is GetHtmlContentFromUploadFileSuccess) {
|
||||
handleGetHtmlContentFromUploadFileSuccess(success);
|
||||
} else {
|
||||
super.handleSuccessViewState(success);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleFailureViewState(Failure failure) {
|
||||
if (failure is DownloadAllAttachmentsForWebFailure) {
|
||||
downloadAllAttachmentsForWebFailure(failureState: failure);
|
||||
} else if (failure is DownloadAttachmentForWebFailure) {
|
||||
downloadAttachmentForWebFailureAction(failureState: failure);
|
||||
} else if (failure is ParseEmailByBlobIdFailure) {
|
||||
handleParseEmailByBlobIdFailure(failure);
|
||||
} else if (failure is PreviewEmailFromEmlFileFailure) {
|
||||
handlePreviewEmailFromEMLFileFailure(failure);
|
||||
} else if (failure is GetHtmlContentFromUploadFileFailure ||
|
||||
failure is DownloadAndGetHtmlContentFromAttachmentFailure) {
|
||||
handlePreviewHtmlFileFailure(failureState: failure);
|
||||
} else if (failure is ExportAttachmentFailure) {
|
||||
exportAttachmentFailureAction(failure);
|
||||
} else if (failure is ExportAllAttachmentsFailure) {
|
||||
exportAllAttachmentsFailureAction(failure);
|
||||
} else {
|
||||
super.handleFailureViewState(failure);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_downloadProgressStateSubscription?.cancel();
|
||||
_downloadProgressStateSubscription = null;
|
||||
downloadProgressStateController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
+631
@@ -0,0 +1,631 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:core/data/network/download/downloaded_response.dart';
|
||||
import 'package:core/domain/exceptions/download_file_exception.dart';
|
||||
import 'package:core/presentation/extensions/media_type_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/views/dialog/downloading_file_dialog_builder.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_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/email/eml_attachment.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:open_file/open_file.dart' as open_file;
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/exceptions/download_attachment_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.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/download/domain/state/export_all_attachments_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/export_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/extensions/preview_attachment_download_controller_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_item_widget.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_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
typedef OnDownloadWebFileAction = void Function(String name, Uint8List bytes);
|
||||
|
||||
extension DownloadAttachmentDownloadControllerExtension on DownloadController {
|
||||
void downloadAttachment({
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool previewerSupported = false,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
downloadAttachmentForWeb(
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
previewerSupported: previewerSupported,
|
||||
onReceiveController: showBottomDownloadProgressBar
|
||||
? downloadProgressStateController
|
||||
: null,
|
||||
sourceView: sourceView,
|
||||
);
|
||||
} else if (PlatformInfo.isMobile) {
|
||||
exportAttachment(
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
);
|
||||
} else {
|
||||
log('$runtimeType::downloadAttachment: THE PLATFORM IS SUPPORTED');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> downloadAllAttachments({
|
||||
required String outputFileName,
|
||||
required EmailId? emailId,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
}) async {
|
||||
if (PlatformInfo.isWeb) {
|
||||
downloadAllAttachmentsForWeb(
|
||||
outputFileName: outputFileName,
|
||||
emailId: emailId,
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
onReceiveController: showBottomDownloadProgressBar
|
||||
? downloadProgressStateController
|
||||
: null,
|
||||
);
|
||||
} else if (PlatformInfo.isMobile) {
|
||||
exportAllAttachments(
|
||||
outputFileName: outputFileName,
|
||||
emailId: emailId,
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
);
|
||||
} else {
|
||||
log('$runtimeType::downloadAllAttachments: THE PLATFORM IS SUPPORTED');
|
||||
}
|
||||
}
|
||||
|
||||
void exportAttachment({
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
}) {
|
||||
final cancelToken = CancelToken();
|
||||
|
||||
showDownloadingFileDialog(
|
||||
attachmentName: attachment.name ?? '',
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAttachmentFailure(NotFoundSessionException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAttachmentFailure(NotFoundAccountIdException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final baseDownloadUrl = session.getSafetyDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
|
||||
consumeState(
|
||||
exportAttachmentInteractor.execute(
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
cancelToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showDownloadingFileDialog({
|
||||
required String attachmentName,
|
||||
required CancelToken cancelToken,
|
||||
}) {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
void downloadAttachmentForWeb({
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool previewerSupported = false,
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
DownloadSourceView? sourceView,
|
||||
}) {
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
exception: NotFoundSessionException(),
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
exception: NotFoundAccountIdException(),
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final generateTaskId = DownloadTaskId(uuid.v4());
|
||||
final baseDownloadUrl = session.getSafetyDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
final cancelToken = CancelToken();
|
||||
|
||||
consumeState(downloadAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
previewerSupported: previewerSupported,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
|
||||
void exportAttachmentSuccessAction(DownloadedResponse downloadedResponse) {
|
||||
popBack();
|
||||
_openDownloadedPreviewWorkGroupDocument(
|
||||
filePath: downloadedResponse.filePath,
|
||||
mediaType: downloadedResponse.mediaType,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openDownloadedPreviewWorkGroupDocument({
|
||||
required String filePath,
|
||||
MediaType? mediaType,
|
||||
}) async {
|
||||
if (mediaType == null) {
|
||||
await _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) {
|
||||
await _saveFileToStorage(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveFileToStorage(String filePath) async {
|
||||
final params = SaveFileDialogParams(sourceFilePath: filePath);
|
||||
await FlutterFileDialog.saveFile(params: params);
|
||||
}
|
||||
|
||||
void exportAllAttachmentsSuccessAction(String filePath) {
|
||||
popBack();
|
||||
_saveFileToStorage(filePath);
|
||||
}
|
||||
|
||||
void exportAllAttachmentsFailureAction(dynamic exception) {
|
||||
if (exception is CancelDownloadFileException) {
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastWarningMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).user_cancel_download_file,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
popBack();
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).attachment_download_failed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void exportAttachmentFailureAction(dynamic exception) {
|
||||
if (exception is CancelDownloadFileException) {
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastWarningMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).user_cancel_download_file,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Get.isDialogOpen == true) {
|
||||
popBack();
|
||||
}
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).attachment_download_failed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void downloadAttachmentForWebFailureAction({
|
||||
required DownloadAttachmentForWebFailure failureState,
|
||||
}) {
|
||||
closeDialogLoading();
|
||||
|
||||
if (failureState.taskId != null) {
|
||||
deleteDownloadTask(failureState.taskId!);
|
||||
}
|
||||
|
||||
if (failureState.attachment != null &&
|
||||
failureState.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
failureState.attachment?.blobId,
|
||||
Left<Failure, Success>(failureState),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (currentOverlayContext == null || currentContext == null) return;
|
||||
|
||||
final appLocalizations = AppLocalizations.of(currentContext!);
|
||||
String message = appLocalizations.attachment_download_failed;
|
||||
if (failureState.attachment is EMLAttachment) {
|
||||
message = appLocalizations.downloadMessageAsEMLFailed;
|
||||
} else if (failureState.cancelToken?.isCancelled == true) {
|
||||
message = appLocalizations.downloadAttachmentHasBeenCancelled;
|
||||
}
|
||||
|
||||
appToast.showToastErrorMessage(currentOverlayContext!, message);
|
||||
}
|
||||
|
||||
void downloadAllAttachmentsForWebFailure({
|
||||
required DownloadAllAttachmentsForWebFailure failureState,
|
||||
}) {
|
||||
deleteDownloadTask(failureState.taskId);
|
||||
|
||||
if (currentOverlayContext == null || currentContext == null) return;
|
||||
|
||||
final appLocalizations = AppLocalizations.of(currentContext!);
|
||||
final message = failureState.cancelToken?.isCancelled == true
|
||||
? appLocalizations.downloadAttachmentHasBeenCancelled
|
||||
: appLocalizations.attachment_download_failed;
|
||||
|
||||
appToast.showToastErrorMessage(currentOverlayContext!, message);
|
||||
}
|
||||
|
||||
void downloadFileWeb({
|
||||
required String fileName,
|
||||
required Uint8List fileBytes,
|
||||
}) {
|
||||
downloadManager.createAnchorElementDownloadFileWeb(
|
||||
fileBytes,
|
||||
fileName,
|
||||
);
|
||||
}
|
||||
|
||||
void downloadAttachmentInEMLPreview({
|
||||
required OnDownloadAttachmentFileAction onDownloadAction,
|
||||
required Uri? uri,
|
||||
}) {
|
||||
if (uri == null) return;
|
||||
|
||||
final attachment = EmailUtils.parsingAttachmentByUri(uri);
|
||||
if (attachment == null) return;
|
||||
|
||||
onDownloadAction(attachment);
|
||||
}
|
||||
|
||||
void exportAllAttachments({
|
||||
required String outputFileName,
|
||||
required EmailId? emailId,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
}) {
|
||||
final cancelToken = CancelToken();
|
||||
|
||||
showDownloadingFileDialog(
|
||||
attachmentName: outputFileName,
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAllAttachmentsFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAllAttachmentsFailure(
|
||||
exception: NotFoundAccountIdException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (emailId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAllAttachmentsFailure(
|
||||
exception: NotFoundEmailException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final downloadAllSupported = session.isDownloadAllSupported(accountId);
|
||||
if (!downloadAllSupported) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ExportAllAttachmentsFailure(
|
||||
exception: CapabilityDownloadAllNotSupportedException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final baseDownloadAllUrl =
|
||||
session.getDownloadAllCapability(accountId)!.endpoint!;
|
||||
|
||||
consumeState(
|
||||
exportAllAttachmentsInteractor.execute(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
cancelToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void downloadAllAttachmentsForWeb({
|
||||
required String outputFileName,
|
||||
required EmailId? emailId,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool previewerSupported = false,
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
}) {
|
||||
final taskId = DownloadTaskId(uuid.v4());
|
||||
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAllAttachmentsForWebFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
taskId: taskId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAllAttachmentsForWebFailure(
|
||||
exception: NotFoundAccountIdException(),
|
||||
taskId: taskId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (emailId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAllAttachmentsForWebFailure(
|
||||
exception: NotFoundEmailException(),
|
||||
taskId: taskId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final downloadAllSupported = session.isDownloadAllSupported(accountId);
|
||||
|
||||
if (!downloadAllSupported) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAllAttachmentsForWebFailure(
|
||||
exception: CapabilityDownloadAllNotSupportedException(),
|
||||
taskId: taskId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final baseDownloadAllUrl =
|
||||
session.getDownloadAllCapability(accountId)!.endpoint!;
|
||||
|
||||
final downloadAttachment = Attachment(
|
||||
name: outputFileName,
|
||||
type: MediaType('application', 'zip'),
|
||||
);
|
||||
|
||||
final cancelToken = CancelToken();
|
||||
|
||||
consumeState(
|
||||
downloadAllAttachmentsForWebInteractor.execute(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
downloadAttachment,
|
||||
taskId,
|
||||
onReceiveController: onReceiveController,
|
||||
cancelToken: cancelToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void downloadMessageAsEML({
|
||||
required PresentationEmail presentationEmail,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
}) {
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAttachmentForWebFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAttachmentForWebFailure(
|
||||
exception: NotFoundAccountIdException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final emlAttachment = presentationEmail.createEMLAttachment();
|
||||
if (emlAttachment.blobId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAttachmentForWebFailure(
|
||||
exception: NotFoundEmailBlobIdException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final generateTaskId = DownloadTaskId(uuid.v4());
|
||||
final baseDownloadUrl = session.getSafetyDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
final cancelToken = CancelToken();
|
||||
|
||||
consumeState(
|
||||
downloadAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
emlAttachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
onReceiveController: showBottomDownloadProgressBar
|
||||
? downloadProgressStateController
|
||||
: null,
|
||||
cancelToken: cancelToken,
|
||||
previewerSupported: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleDownloadAttachmentForWebSuccess(
|
||||
DownloadAttachmentForWebSuccess success,
|
||||
) {
|
||||
closeDialogLoading();
|
||||
|
||||
if (success.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
));
|
||||
}
|
||||
|
||||
deleteDownloadTask(success.taskId);
|
||||
|
||||
if (!success.previewerSupported) {
|
||||
downloadFileWeb(
|
||||
fileBytes: success.bytes,
|
||||
fileName: success.attachment.generateFileName(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (success.attachment.isImage) {
|
||||
previewImageFile(
|
||||
fileName: success.attachment.generateFileName(),
|
||||
imageBytes: success.bytes,
|
||||
context: currentContext,
|
||||
onDownloadWebFileAction: (name, bytes) => downloadFileWeb(
|
||||
fileName: name,
|
||||
fileBytes: bytes,
|
||||
),
|
||||
);
|
||||
} else if (success.attachment.isText || success.attachment.isJson) {
|
||||
previewPlainTextFile(
|
||||
fileName: success.attachment.generateFileName(),
|
||||
fileBytes: success.bytes,
|
||||
context: currentContext,
|
||||
onDownloadWebFileAction: (name, bytes) => downloadFileWeb(
|
||||
fileName: name,
|
||||
fileBytes: bytes,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+763
@@ -0,0 +1,763 @@
|
||||
import 'package:core/domain/exceptions/web_session_exception.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/dom/sanitize_hyper_link_tag_in_html_transformers.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/text/standardize_html_sanitizing_transformers.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/html/html_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_navigation/src/dialog/dialog_route.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/download/domain/exceptions/download_attachment_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.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/download/domain/state/get_html_content_from_upload_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/extensions/download_attachment_download_controller_extension.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/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/attachment_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/html_attachment_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/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.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_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:twake_previewer_flutter/core/constants/supported_charset.dart';
|
||||
import 'package:twake_previewer_flutter/core/previewer_options/options/previewer_state.dart';
|
||||
import 'package:twake_previewer_flutter/core/previewer_options/options/top_bar_options.dart';
|
||||
import 'package:twake_previewer_flutter/core/previewer_options/previewer_options.dart';
|
||||
import 'package:twake_previewer_flutter/twake_image_previewer/twake_image_previewer.dart';
|
||||
import 'package:twake_previewer_flutter/twake_plain_text_previewer/twake_plain_text_previewer.dart';
|
||||
|
||||
typedef OnPreviewOrDownloadAttachmentAction = void Function(
|
||||
Attachment attachment,
|
||||
bool isPreviewSupported,
|
||||
);
|
||||
|
||||
extension PreviewAttachmentDownloadControllerExtension on DownloadController {
|
||||
void previewAttachment({
|
||||
required BuildContext context,
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required OnPreviewOrDownloadAttachmentAction onPreviewOrDownloadAction,
|
||||
bool isDialogLoadingVisible = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) {
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
|
||||
if (PlatformInfo.isWeb && attachment.isPDFFile) {
|
||||
_previewPDFFile(
|
||||
context: context,
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
);
|
||||
} else if (attachment.isEMLFile) {
|
||||
_preparePreviewEMLFile(
|
||||
appLocalizations: appLocalizations,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: attachment.blobId,
|
||||
);
|
||||
} else if (attachment.isHTMLFile) {
|
||||
_preparePreviewHtmlFile(
|
||||
appLocalizations: appLocalizations,
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
attachment: attachment,
|
||||
isDialogLoadingVisible: isDialogLoadingVisible,
|
||||
sourceView: sourceView,
|
||||
);
|
||||
} else {
|
||||
if (isDialogLoadingVisible) {
|
||||
showDialogLoading(appLocalizations);
|
||||
}
|
||||
onPreviewOrDownloadAction(
|
||||
attachment,
|
||||
attachment.isPreviewSupported,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void previewUploadFile({
|
||||
required BuildContext context,
|
||||
required UploadFileState uploadFile,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required OnPreviewOrDownloadAttachmentAction onPreviewOrDownloadAction,
|
||||
bool isDialogLoadingVisible = false,
|
||||
}) {
|
||||
final attachment = uploadFile.attachment;
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
|
||||
if (attachment == null) {
|
||||
showPreviewNotAvailableToastMessage(context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlatformInfo.isWeb && attachment.isPDFFile == true) {
|
||||
_previewPDFFile(
|
||||
context: context,
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachment.isEMLFile == true) {
|
||||
_preparePreviewEMLFile(
|
||||
appLocalizations: appLocalizations,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: attachment.blobId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachment.isHTMLFile == true) {
|
||||
if (uploadFile.file?.bytes != null) {
|
||||
_preparePreviewHtmlFileByUploadFile(
|
||||
appLocalizations: appLocalizations,
|
||||
uploadFile: uploadFile,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
isDialogLoadingVisible: isDialogLoadingVisible,
|
||||
);
|
||||
} else {
|
||||
_preparePreviewHtmlFile(
|
||||
appLocalizations: appLocalizations,
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
isDialogLoadingVisible: isDialogLoadingVisible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachment.isImage == true && uploadFile.file?.bytes != null) {
|
||||
previewImageFile(
|
||||
fileName: attachment.generateFileName(),
|
||||
imageBytes: uploadFile.file!.bytes!,
|
||||
context: context,
|
||||
onDownloadWebFileAction: (fileName, fileBytes) => downloadFileWeb(
|
||||
fileName: fileName,
|
||||
fileBytes: fileBytes,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((attachment.isText == true || attachment.isJson == true) &&
|
||||
uploadFile.file?.bytes != null) {
|
||||
previewPlainTextFile(
|
||||
fileName: attachment.generateFileName(),
|
||||
fileBytes: uploadFile.file!.bytes!,
|
||||
context: context,
|
||||
onDownloadWebFileAction: (fileName, fileBytes) => downloadFileWeb(
|
||||
fileName: fileName,
|
||||
fileBytes: fileBytes,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadFile.file?.bytes != null) {
|
||||
downloadFileWeb(
|
||||
fileName: attachment.generateFileName(),
|
||||
fileBytes: uploadFile.file!.bytes!,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDialogLoadingVisible) {
|
||||
showDialogLoading(appLocalizations);
|
||||
}
|
||||
onPreviewOrDownloadAction(attachment, attachment.isPreviewSupported);
|
||||
}
|
||||
|
||||
Future<void> _previewPDFFile({
|
||||
required BuildContext context,
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
}) async {
|
||||
final downloadUrl = session?.getSafetyDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
|
||||
if (accountId == null || session == null || downloadUrl == null) {
|
||||
showPreviewNotAvailableToastMessage(context);
|
||||
return;
|
||||
}
|
||||
|
||||
await Get.generalDialog(
|
||||
barrierColor: Colors.black.withValues(alpha: 0.8),
|
||||
pageBuilder: (_, __, ___) {
|
||||
return PointerInterceptor(
|
||||
child: PDFViewer(
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl,
|
||||
downloadAction: (bytes, name) =>
|
||||
downloadFileWeb(fileName: name, fileBytes: bytes),
|
||||
printAction: printUtils.printPDFFile,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _preparePreviewEMLFile({
|
||||
required AppLocalizations appLocalizations,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required Id? blobId,
|
||||
}) {
|
||||
showDialogLoading(appLocalizations);
|
||||
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundSessionException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundAccountIdException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blobId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundBlobIdException([])),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
consumeState(
|
||||
parseEmailByBlobIdInteractor.execute(
|
||||
accountId,
|
||||
session,
|
||||
ownEmailAddress,
|
||||
blobId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _preparePreviewHtmlFile({
|
||||
required AppLocalizations appLocalizations,
|
||||
required Session? session,
|
||||
required AccountId? accountId,
|
||||
required Attachment attachment,
|
||||
bool isDialogLoadingVisible = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) {
|
||||
if (isDialogLoadingVisible) {
|
||||
showDialogLoading(appLocalizations);
|
||||
}
|
||||
|
||||
final downloadUrl = session?.getSafetyDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
final blobId = attachment.blobId;
|
||||
|
||||
if (session == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
blobId: blobId,
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: NotFoundAccountIdException(),
|
||||
blobId: blobId,
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blobId == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: NotFoundBlobIdException([]),
|
||||
blobId: blobId,
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (downloadUrl == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: DownloadUrlIsNullException(),
|
||||
blobId: blobId,
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
consumeState(
|
||||
downloadAndGetHtmlContentFromAttachmentInteractor.execute(
|
||||
accountId,
|
||||
session,
|
||||
attachment,
|
||||
DownloadTaskId(blobId.value),
|
||||
downloadUrl,
|
||||
TransformConfiguration.create(
|
||||
customDomTransformers: [SanitizeHyperLinkTagInHtmlTransformer()],
|
||||
customTextTransformers: [
|
||||
const StandardizeHtmlSanitizingTransformers()
|
||||
],
|
||||
),
|
||||
sourceView: sourceView,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _preparePreviewHtmlFileByUploadFile({
|
||||
required AppLocalizations appLocalizations,
|
||||
required UploadFileState uploadFile,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool isDialogLoadingVisible = false,
|
||||
}) {
|
||||
if (isDialogLoadingVisible) {
|
||||
showDialogLoading(appLocalizations);
|
||||
}
|
||||
consumeState(
|
||||
getHtmlContentFromUploadFileInteractor.execute(
|
||||
uploadFile: uploadFile,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleParseEmailByBlobIdSuccess({
|
||||
required BuildContext? context,
|
||||
required AccountId accountId,
|
||||
required Session session,
|
||||
required String ownEmailAddress,
|
||||
required Id blobId,
|
||||
required Email email,
|
||||
}) {
|
||||
if (context == null) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: PreviewEmailFromEmlFileFailure(NotFoundContextException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final downloadUrl = session.getDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
|
||||
if (downloadUrl.isEmpty) {
|
||||
emitFailure(
|
||||
controller: this,
|
||||
failure: PreviewEmailFromEmlFileFailure(DownloadUrlIsNullException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
consumeState(
|
||||
previewEmailFromEmlFileInteractor.execute(
|
||||
PreviewEmailEMLRequest(
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: blobId,
|
||||
email: email,
|
||||
locale: Localizations.localeOf(context),
|
||||
appLocalizations: AppLocalizations.of(context),
|
||||
baseDownloadUrl: downloadUrl,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleParseEmailByBlobIdFailure(ParseEmailByBlobIdFailure failure) {
|
||||
closeDialogLoading();
|
||||
toastManager.showMessageFailure(failure);
|
||||
}
|
||||
|
||||
void handlePreviewEmailFromEMLFileFailure(
|
||||
PreviewEmailFromEmlFileFailure failure,
|
||||
) {
|
||||
closeDialogLoading();
|
||||
toastManager.showMessageFailure(failure);
|
||||
}
|
||||
|
||||
void handleGetHtmlContentFromUploadFileSuccess(
|
||||
GetHtmlContentFromUploadFileSuccess success,
|
||||
) {
|
||||
closeDialogLoading();
|
||||
|
||||
previewHtmlFile(
|
||||
attachment: success.attachment,
|
||||
title: success.htmlAttachmentTitle,
|
||||
content: success.sanitizedHtmlContent,
|
||||
openMailToLink: (uri) async {
|
||||
if (uri == null) return;
|
||||
pushDownloadUIAction(OpenComposerFromMailtoLinkAction(uri));
|
||||
},
|
||||
onDownloadAction: (attachment) => downloadAttachment(
|
||||
attachment: attachment,
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleDownloadAndGetHtmlContentFromAttachmentSuccess(
|
||||
DownloadAndGetHtmlContentFromAttachmentSuccess success,
|
||||
) {
|
||||
if (success.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
closeDialogLoading();
|
||||
|
||||
previewHtmlFile(
|
||||
attachment: success.attachment,
|
||||
title: success.htmlAttachmentTitle,
|
||||
content: success.sanitizedHtmlContent,
|
||||
openMailToLink: (uri) async {
|
||||
if (uri == null) return;
|
||||
pushDownloadUIAction(OpenComposerFromMailtoLinkAction(uri));
|
||||
},
|
||||
onDownloadAction: (attachment) => downloadAttachment(
|
||||
attachment: attachment,
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handlePreviewEmailFromEmlFileSuccess(
|
||||
PreviewEmailFromEmlFileSuccess success,
|
||||
) {
|
||||
previewEMLFile(
|
||||
emlPreviewer: success.emlPreviewer,
|
||||
context: currentContext,
|
||||
onMailtoAction: (uri) async {
|
||||
if (uri == null) return;
|
||||
pushDownloadUIAction(OpenComposerFromMailtoLinkAction(uri));
|
||||
},
|
||||
onDownloadAction: (uri) async => downloadAttachmentInEMLPreview(
|
||||
uri: uri,
|
||||
onDownloadAction: (attachment) => downloadAttachment(
|
||||
attachment: attachment,
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
)),
|
||||
onPreviewAction: (uri) async => openEMLPreviewer(
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
ownEmailAddress: success.ownEmailAddress,
|
||||
uri: uri,
|
||||
appLocalizations: success.appLocalizations,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void previewEMLFile({
|
||||
required EMLPreviewer emlPreviewer,
|
||||
required BuildContext? context,
|
||||
required OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
}) {
|
||||
closeDialogLoading();
|
||||
|
||||
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,
|
||||
onMailtoAction: onMailtoAction,
|
||||
onDownloadAction: onDownloadAction,
|
||||
onPreviewAction: onPreviewAction,
|
||||
);
|
||||
} else if (PlatformInfo.isIOS) {
|
||||
showDialogToPreviewEMLAttachment(
|
||||
context: context,
|
||||
emlPreviewer: emlPreviewer,
|
||||
onMailtoAction: onMailtoAction,
|
||||
onDownloadAction: onDownloadAction,
|
||||
onPreviewAction: onPreviewAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showModalSheetToPreviewEMLAttachment({
|
||||
required BuildContext context,
|
||||
required EMLPreviewer emlPreviewer,
|
||||
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 OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
}) {
|
||||
Get.dialog(
|
||||
EmailPreviewerDialogView(
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoDelegateAction: onMailtoAction,
|
||||
onPreviewEMLDelegateAction: onPreviewAction,
|
||||
onDownloadAttachmentDelegateAction: onDownloadAction,
|
||||
),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
|
||||
void handlePreviewHtmlFileFailure({required Failure failureState}) {
|
||||
if (failureState is DownloadAndGetHtmlContentFromAttachmentFailure &&
|
||||
failureState.sourceView == DownloadSourceView.emailView) {
|
||||
pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
failureState.blobId,
|
||||
Left<Failure, Success>(failureState),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
closeDialogLoading();
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!)
|
||||
.thisHtmlAttachmentCannotBePreviewed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void previewImageFile({
|
||||
required String fileName,
|
||||
required Uint8List imageBytes,
|
||||
required BuildContext? context,
|
||||
required OnDownloadWebFileAction onDownloadWebFileAction,
|
||||
}) {
|
||||
log('$runtimeType::previewImageFile: Attachment fileName is $fileName');
|
||||
if (context == null) return;
|
||||
|
||||
Navigator.of(context).push(
|
||||
GetDialogRoute(
|
||||
pageBuilder: (context, _, __) => PointerInterceptor(
|
||||
child: TwakeImagePreviewer(
|
||||
bytes: imageBytes,
|
||||
zoomable: true,
|
||||
previewerOptions: const PreviewerOptions(
|
||||
previewerState: PreviewerState.success,
|
||||
),
|
||||
topBarOptions: TopBarOptions(
|
||||
title: fileName,
|
||||
onClose: () => Navigator.maybePop(context),
|
||||
onDownload: () => onDownloadWebFileAction(fileName, imageBytes),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void previewPlainTextFile({
|
||||
required String fileName,
|
||||
required Uint8List fileBytes,
|
||||
required BuildContext? context,
|
||||
required OnDownloadWebFileAction onDownloadWebFileAction,
|
||||
}) {
|
||||
log('$runtimeType::previewPlainTextFile: Attachment fileName is $fileName');
|
||||
if (context == null) return;
|
||||
|
||||
Navigator.of(context).push(
|
||||
GetDialogRoute(
|
||||
pageBuilder: (context, _, __) => PointerInterceptor(
|
||||
child: TwakePlainTextPreviewer(
|
||||
supportedCharset: SupportedCharset.utf8,
|
||||
bytes: fileBytes,
|
||||
previewerOptions: PreviewerOptions(
|
||||
previewerState: PreviewerState.success,
|
||||
width: context.width * 0.8,
|
||||
),
|
||||
topBarOptions: TopBarOptions(
|
||||
title: fileName,
|
||||
onClose: () => Navigator.maybePop(context),
|
||||
onDownload: () => onDownloadWebFileAction(fileName, fileBytes),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void previewHtmlFile({
|
||||
required Attachment attachment,
|
||||
required String title,
|
||||
required String content,
|
||||
required OnMailtoDelegateAction openMailToLink,
|
||||
required OnDownloadAttachmentFileAction onDownloadAction,
|
||||
}) {
|
||||
Get.dialog(
|
||||
HtmlAttachmentPreviewer(
|
||||
title: title,
|
||||
htmlContent: content,
|
||||
mailToClicked: openMailToLink,
|
||||
downloadAttachmentClicked: () => onDownloadAction(attachment),
|
||||
responsiveUtils: responsiveUtils,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> openEMLPreviewer({
|
||||
required AppLocalizations appLocalizations,
|
||||
required Uri? uri,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
}) async {
|
||||
if (uri == null) return;
|
||||
|
||||
final blobId = uri.path;
|
||||
if (blobId.isEmpty) return;
|
||||
|
||||
_preparePreviewEMLFile(
|
||||
appLocalizations: appLocalizations,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: Id(blobId),
|
||||
);
|
||||
}
|
||||
|
||||
void showDialogLoading(AppLocalizations appLocalizations) {
|
||||
SmartDialog.showLoading(
|
||||
msg: appLocalizations.loadingPleaseWait,
|
||||
maskColor: Colors.black38,
|
||||
);
|
||||
}
|
||||
|
||||
void closeDialogLoading() {
|
||||
if (SmartDialog.checkExist()) {
|
||||
SmartDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
void showPreviewNotAvailableToastMessage(BuildContext context) {
|
||||
appToast.showToastErrorMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).noPreviewAvailable,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user