TF-4050 Preview and download uploaded file in composer on web
This commit is contained in:
@@ -16,6 +16,7 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:rule_filter/rule_filter/capability_rule_filter.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/emit_state_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/logout_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
||||
@@ -63,7 +64,7 @@ import 'package:tmail_ui_user/main/utils/twake_app_manager.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
abstract class BaseController extends GetxController
|
||||
with PopupContextMenuActionMixin, LogoutMixin {
|
||||
with PopupContextMenuActionMixin, LogoutMixin, EmitStateMixin {
|
||||
|
||||
final CachingManager cachingManager = Get.find<CachingManager>();
|
||||
final LanguageCacheManager languageCacheManager = Get.find<LanguageCacheManager>();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
|
||||
mixin EmitStateMixin {
|
||||
void emitFailure({
|
||||
required BaseController controller,
|
||||
required FeatureFailure failure,
|
||||
}) {
|
||||
controller.consumeState(Stream.value(Left(failure)));
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_e
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_keyboard_shortcut_actions_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/preview_upload_file_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
|
||||
@@ -70,6 +71,22 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
}
|
||||
});
|
||||
|
||||
final attachmentWidget = Obx(() {
|
||||
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
|
||||
return AttachmentComposerWidget(
|
||||
listFileUploaded: controller.uploadController.listUploadAttachments,
|
||||
isCollapsed: controller.isAttachmentCollapsed,
|
||||
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
|
||||
onPreviewAttachmentAction: (id) =>
|
||||
controller.previewUploadFile(context, id),
|
||||
onToggleExpandAttachmentAction: (isCollapsed) =>
|
||||
controller.isAttachmentCollapsed = isCollapsed,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
});
|
||||
|
||||
final bodyWidget = ResponsiveWidget(
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
mobile: MobileResponsiveContainerView(
|
||||
@@ -251,18 +268,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
}
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
|
||||
return AttachmentComposerWidget(
|
||||
listFileUploaded: controller.uploadController.listUploadAttachments,
|
||||
isCollapsed: controller.isAttachmentCollapsed,
|
||||
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
|
||||
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
attachmentWidget,
|
||||
Obx(() {
|
||||
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
|
||||
return ToolbarRichTextWidget(
|
||||
@@ -504,18 +510,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
}
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
|
||||
return AttachmentComposerWidget(
|
||||
listFileUploaded: controller.uploadController.listUploadAttachments,
|
||||
isCollapsed: controller.isAttachmentCollapsed,
|
||||
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
|
||||
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
attachmentWidget,
|
||||
Obx(() {
|
||||
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
|
||||
return ToolbarRichTextWidget(
|
||||
@@ -785,18 +780,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
}
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
|
||||
return AttachmentComposerWidget(
|
||||
listFileUploaded: controller.uploadController.listUploadAttachments,
|
||||
isCollapsed: controller.isAttachmentCollapsed,
|
||||
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
|
||||
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
attachmentWidget,
|
||||
Obx(() {
|
||||
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
|
||||
return ToolbarRichTextWidget(
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preview_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
extension PreviewUploadFileExtension on ComposerController {
|
||||
void previewUploadFile(BuildContext context, UploadTaskId uploadId) {
|
||||
final uploadFile = uploadController.getUploadFileId(uploadId);
|
||||
|
||||
if (uploadFile == null || uploadFile.attachment == null) {
|
||||
appToast.showToastWarningMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).noPreviewAvailable,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
mailboxDashBoardController.previewUploadFile(
|
||||
context: context,
|
||||
uploadFile: uploadFile,
|
||||
isDialogLoadingVisible: true,
|
||||
onPreviewOrDownloadAction: (attachment, isPreview) {
|
||||
mailboxDashBoardController.downloadAttachment(
|
||||
attachment: attachment,
|
||||
previewerSupported: isPreview,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/presentation/views/text/middle_ellipsis_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_item_composer_widget_style.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_progress_loading_composer_widget.dart';
|
||||
@@ -11,11 +10,11 @@ import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
||||
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_status.dart';
|
||||
|
||||
typedef OnDeleteAttachmentAction = void Function(UploadTaskId uploadTaskId);
|
||||
typedef OnPreviewAttachmentAction = void Function(UploadTaskId uploadTaskId);
|
||||
|
||||
class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
|
||||
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
final ImagePaths imagePaths;
|
||||
final String fileIcon;
|
||||
final String fileName;
|
||||
final String fileSize;
|
||||
@@ -26,10 +25,12 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
|
||||
final EdgeInsetsGeometry? itemMargin;
|
||||
final EdgeInsetsGeometry? itemPadding;
|
||||
final OnDeleteAttachmentAction? onDeleteAttachmentAction;
|
||||
final OnPreviewAttachmentAction? onPreviewAttachmentAction;
|
||||
final Widget? buttonAction;
|
||||
|
||||
AttachmentItemComposerWidget({
|
||||
const AttachmentItemComposerWidget({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.fileIcon,
|
||||
required this.fileName,
|
||||
required this.fileSize,
|
||||
@@ -41,10 +42,65 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
|
||||
this.itemPadding,
|
||||
this.buttonAction,
|
||||
this.onDeleteAttachmentAction,
|
||||
this.onPreviewAttachmentAction,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget bodyItem = Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
fileIcon,
|
||||
width: AttachmentItemComposerWidgetStyle.iconSize,
|
||||
height: AttachmentItemComposerWidgetStyle.iconSize,
|
||||
fit: BoxFit.fill
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
Flexible(
|
||||
child: MiddleEllipsisText(
|
||||
fileName,
|
||||
style: AttachmentItemComposerWidgetStyle.labelTextStyle,
|
||||
)
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
Text(
|
||||
fileSize,
|
||||
style: AttachmentItemComposerWidgetStyle.sizeLabelTextStyle
|
||||
),
|
||||
],
|
||||
),
|
||||
AttachmentProgressLoadingComposerWidget(
|
||||
uploadStatus: uploadStatus,
|
||||
percentUploading: percentUploading,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icCancel,
|
||||
iconSize: AttachmentItemComposerWidgetStyle.deleteIconSize,
|
||||
borderRadius: AttachmentItemComposerWidgetStyle.deleteIconRadius,
|
||||
padding: AttachmentItemComposerWidgetStyle.deleteIconPadding,
|
||||
iconColor: AttachmentItemComposerWidgetStyle.deleteIconColor,
|
||||
onTapActionCallback: () => onDeleteAttachmentAction?.call(uploadTaskId),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
if (onPreviewAttachmentAction != null) {
|
||||
bodyItem = InkWell(
|
||||
onTap: () => onPreviewAttachmentAction!(uploadTaskId),
|
||||
child: bodyItem,
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(AttachmentItemComposerWidgetStyle.radius)),
|
||||
@@ -54,52 +110,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
|
||||
width: AttachmentItemComposerWidgetStyle.width,
|
||||
padding: itemPadding ?? AttachmentItemComposerWidgetStyle.padding,
|
||||
margin: itemMargin,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
fileIcon,
|
||||
width: AttachmentItemComposerWidgetStyle.iconSize,
|
||||
height: AttachmentItemComposerWidgetStyle.iconSize,
|
||||
fit: BoxFit.fill
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
Flexible(
|
||||
child: MiddleEllipsisText(
|
||||
fileName,
|
||||
style: AttachmentItemComposerWidgetStyle.labelTextStyle,
|
||||
)
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
Text(
|
||||
fileSize,
|
||||
style: AttachmentItemComposerWidgetStyle.sizeLabelTextStyle
|
||||
),
|
||||
],
|
||||
),
|
||||
AttachmentProgressLoadingComposerWidget(
|
||||
uploadStatus: uploadStatus,
|
||||
percentUploading: percentUploading,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: _imagePaths.icCancel,
|
||||
iconSize: AttachmentItemComposerWidgetStyle.deleteIconSize,
|
||||
borderRadius: AttachmentItemComposerWidgetStyle.deleteIconRadius,
|
||||
padding: AttachmentItemComposerWidgetStyle.deleteIconPadding,
|
||||
iconColor: AttachmentItemComposerWidgetStyle.deleteIconColor,
|
||||
onTapActionCallback: () => onDeleteAttachmentAction?.call(uploadTaskId),
|
||||
)
|
||||
],
|
||||
),
|
||||
child: bodyItem,
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
@@ -76,6 +76,7 @@ class _MobileAttachmentComposerWidgetState extends State<MobileAttachmentCompose
|
||||
itemBuilder: (context, index) {
|
||||
final file = _listFileDisplayed[index];
|
||||
return AttachmentItemComposerWidget(
|
||||
imagePaths: _imagePaths,
|
||||
fileIcon: file.getIcon(_imagePaths),
|
||||
fileName: file.fileName,
|
||||
fileSize: filesize(file.fileSize),
|
||||
@@ -139,6 +140,7 @@ class _MobileAttachmentComposerWidgetState extends State<MobileAttachmentCompose
|
||||
itemBuilder: (context, index) {
|
||||
final file = _listFileDisplayed[index];
|
||||
return AttachmentItemComposerWidget(
|
||||
imagePaths: _imagePaths,
|
||||
fileIcon: file.getIcon(_imagePaths),
|
||||
fileName: file.fileName,
|
||||
fileSize: filesize(file.fileSize),
|
||||
|
||||
@@ -16,6 +16,7 @@ class AttachmentComposerWidget extends StatefulWidget {
|
||||
final bool isCollapsed;
|
||||
final OnDeleteAttachmentAction onDeleteAttachmentAction;
|
||||
final OnToggleExpandAttachmentAction onToggleExpandAttachmentAction;
|
||||
final OnPreviewAttachmentAction onPreviewAttachmentAction;
|
||||
|
||||
const AttachmentComposerWidget({
|
||||
super.key,
|
||||
@@ -23,6 +24,7 @@ class AttachmentComposerWidget extends StatefulWidget {
|
||||
required this.isCollapsed,
|
||||
required this.onDeleteAttachmentAction,
|
||||
required this.onToggleExpandAttachmentAction,
|
||||
required this.onPreviewAttachmentAction,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -76,6 +78,7 @@ class _AttachmentComposerWidgetState extends State<AttachmentComposerWidget> {
|
||||
runSpacing: AttachmentComposerWidgetStyle.listItemSpace,
|
||||
children: widget.listFileUploaded
|
||||
.map((file) => AttachmentItemComposerWidget(
|
||||
imagePaths: _imagePaths,
|
||||
fileIcon: file.getIcon(_imagePaths),
|
||||
fileName: file.fileName,
|
||||
fileSize: filesize(file.fileSize),
|
||||
@@ -83,6 +86,7 @@ class _AttachmentComposerWidgetState extends State<AttachmentComposerWidget> {
|
||||
percentUploading: file.percentUploading,
|
||||
uploadTaskId: file.uploadTaskId,
|
||||
onDeleteAttachmentAction: widget.onDeleteAttachmentAction,
|
||||
onPreviewAttachmentAction: widget.onPreviewAttachmentAction,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ 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/mailbox_dashboard/data/datasource/download_datasource.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 {
|
||||
+38
-2
@@ -10,12 +10,12 @@ 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';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/download_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
|
||||
class DownloadRepositoryImpl extends DownloadRepository {
|
||||
final DownloadDatasource _downloadDatasource;
|
||||
@@ -131,4 +131,40 @@ class DownloadRepositoryImpl extends DownloadRepository {
|
||||
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;
|
||||
}
|
||||
+18
@@ -1,6 +1,7 @@
|
||||
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';
|
||||
@@ -59,4 +60,21 @@ abstract class DownloadRepository {
|
||||
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,
|
||||
);
|
||||
}
|
||||
+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];
|
||||
}
|
||||
+47
-9
@@ -4,6 +4,7 @@ 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 {}
|
||||
|
||||
@@ -13,11 +14,24 @@ class StartDownloadAttachmentForWeb extends UIState {
|
||||
final Attachment attachment;
|
||||
final CancelToken? cancelToken;
|
||||
final bool previewerSupported;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
StartDownloadAttachmentForWeb(this.taskId, this.attachment, [this.cancelToken, this.previewerSupported = false]);
|
||||
StartDownloadAttachmentForWeb(
|
||||
this.taskId,
|
||||
this.attachment, [
|
||||
this.cancelToken,
|
||||
this.previewerSupported = false,
|
||||
this.sourceView,
|
||||
]);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [taskId, attachment, cancelToken, previewerSupported];
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
cancelToken,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadingAttachmentForWeb extends UIState {
|
||||
@@ -27,22 +41,25 @@ class DownloadingAttachmentForWeb extends UIState {
|
||||
final double progress;
|
||||
final int downloaded;
|
||||
final int total;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadingAttachmentForWeb(
|
||||
this.taskId,
|
||||
this.attachment,
|
||||
this.progress,
|
||||
this.downloaded,
|
||||
this.total
|
||||
this.total,
|
||||
this.sourceView,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
progress,
|
||||
downloaded,
|
||||
total
|
||||
total,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -52,11 +69,24 @@ class DownloadAttachmentForWebSuccess extends UIState {
|
||||
final Attachment attachment;
|
||||
final Uint8List bytes;
|
||||
final bool previewerSupported;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadAttachmentForWebSuccess(this.taskId, this.attachment, this.bytes, this.previewerSupported);
|
||||
DownloadAttachmentForWebSuccess(
|
||||
this.taskId,
|
||||
this.attachment,
|
||||
this.bytes,
|
||||
this.previewerSupported,
|
||||
this.sourceView,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [taskId, attachment, bytes, previewerSupported];
|
||||
List<Object?> get props => [
|
||||
taskId,
|
||||
attachment,
|
||||
bytes,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
];
|
||||
}
|
||||
|
||||
class DownloadAttachmentForWebFailure extends FeatureFailure {
|
||||
@@ -64,14 +94,22 @@ class DownloadAttachmentForWebFailure extends FeatureFailure {
|
||||
final DownloadTaskId? taskId;
|
||||
final Attachment? attachment;
|
||||
final CancelToken? cancelToken;
|
||||
final DownloadSourceView? sourceView;
|
||||
|
||||
DownloadAttachmentForWebFailure({
|
||||
this.attachment,
|
||||
this.taskId,
|
||||
this.cancelToken,
|
||||
super.exception
|
||||
this.sourceView,
|
||||
super.exception,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [attachment, taskId, cancelToken, ...super.props];
|
||||
List<Object?> get props => [
|
||||
attachment,
|
||||
taskId,
|
||||
cancelToken,
|
||||
sourceView,
|
||||
...super.props,
|
||||
];
|
||||
}
|
||||
@@ -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});
|
||||
}
|
||||
+2
-2
@@ -8,8 +8,8 @@ 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 AccountId accountId;
|
||||
final Session session;
|
||||
final String ownEmailAddress;
|
||||
final Email email;
|
||||
final Id blobId;
|
||||
+6
-2
@@ -3,20 +3,23 @@ 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 AccountId accountId;
|
||||
final Session session;
|
||||
final String ownEmailAddress;
|
||||
final AppLocalizations appLocalizations;
|
||||
|
||||
PreviewEmailFromEmlFileSuccess(
|
||||
this.emlPreviewer,
|
||||
this.accountId,
|
||||
this.session,
|
||||
this.ownEmailAddress,
|
||||
this.appLocalizations,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -25,6 +28,7 @@ class PreviewEmailFromEmlFileSuccess extends UIState {
|
||||
accountId,
|
||||
session,
|
||||
ownEmailAddress,
|
||||
appLocalizations,
|
||||
];
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,11 +13,11 @@ import 'package:model/account/authentication_type.dart';
|
||||
import 'package:model/account/password.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/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/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
|
||||
class DownloadAllAttachmentsForWebInteractor {
|
||||
const DownloadAllAttachmentsForWebInteractor(
|
||||
+42
-19
@@ -7,14 +7,16 @@ 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/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
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 GetHtmlContentFromAttachmentInteractor {
|
||||
GetHtmlContentFromAttachmentInteractor(
|
||||
class DownloadAndGetHtmlContentFromAttachmentInteractor {
|
||||
DownloadAndGetHtmlContentFromAttachmentInteractor(
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
@@ -22,31 +24,41 @@ class GetHtmlContentFromAttachmentInteractor {
|
||||
|
||||
Stream<Either<Failure, Success>> execute(
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
Attachment attachment,
|
||||
DownloadTaskId taskId,
|
||||
String baseDownloadUrl,
|
||||
TransformConfiguration transformConfiguration,
|
||||
) async* {
|
||||
TransformConfiguration transformConfiguration, {
|
||||
DownloadSourceView? sourceView,
|
||||
}) async* {
|
||||
try {
|
||||
yield Right(GettingHtmlContentFromAttachment(attachment: attachment));
|
||||
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(GetHtmlContentFromAttachmentFailure(
|
||||
sanitizeState = Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: failure is FeatureFailure ? failure.exception : null,
|
||||
attachment: attachment,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
},
|
||||
(success) async {
|
||||
if (success is! DownloadAttachmentForWebSuccess) {
|
||||
sanitizeState = Right(GettingHtmlContentFromAttachment(attachment: attachment));
|
||||
sanitizeState = Right(DownloadAndGettingHtmlContentFromAttachment(
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
} else {
|
||||
final htmlContent = StringConvert.decodeFromBytes(
|
||||
success.bytes,
|
||||
@@ -57,6 +69,9 @@ class GetHtmlContentFromAttachmentInteractor {
|
||||
htmlContent,
|
||||
transformConfiguration,
|
||||
attachment,
|
||||
accountId,
|
||||
session,
|
||||
sourceView,
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -65,17 +80,18 @@ class GetHtmlContentFromAttachmentInteractor {
|
||||
if (sanitizeState != null) {
|
||||
yield sanitizeState!;
|
||||
} else {
|
||||
yield Left(GetHtmlContentFromAttachmentFailure(
|
||||
yield Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: null,
|
||||
attachment: attachment,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
logError('GetHtmlContentFromAttachmentInteractor:exception: $e');
|
||||
yield Left(GetHtmlContentFromAttachmentFailure(
|
||||
yield Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: e,
|
||||
attachment: attachment,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -84,21 +100,28 @@ class GetHtmlContentFromAttachmentInteractor {
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
DownloadSourceView? sourceView,
|
||||
) async {
|
||||
try {
|
||||
final sanitizedHtmlContent = await _downloadAttachmentForWebInteractor
|
||||
.downloadRepository
|
||||
.sanitizeHtmlContent(htmlContent, transformConfiguration);
|
||||
|
||||
return Right(GetHtmlContentFromAttachmentSuccess(
|
||||
return Right(DownloadAndGetHtmlContentFromAttachmentSuccess(
|
||||
sanitizedHtmlContent: sanitizedHtmlContent,
|
||||
htmlAttachmentTitle: attachment.generateFileName(),
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
} catch (e) {
|
||||
return Left(GetHtmlContentFromAttachmentFailure(
|
||||
return Left(DownloadAndGetHtmlContentFromAttachmentFailure(
|
||||
exception: e,
|
||||
attachment: attachment,
|
||||
blobId: attachment.blobId,
|
||||
sourceView: sourceView,
|
||||
));
|
||||
}
|
||||
}
|
||||
+18
-5
@@ -11,11 +11,12 @@ import 'package:model/account/authentication_type.dart';
|
||||
import 'package:model/account/password.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/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/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
|
||||
class DownloadAttachmentForWebInteractor {
|
||||
final DownloadRepository downloadRepository;
|
||||
@@ -37,10 +38,20 @@ class DownloadAttachmentForWebInteractor {
|
||||
StreamController<Either<Failure, Success>>? onReceiveController,
|
||||
CancelToken? cancelToken,
|
||||
bool previewerSupported = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) async* {
|
||||
try {
|
||||
yield Right<Failure, Success>(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported));
|
||||
onReceiveController?.add(Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported)));
|
||||
final loadingState = Right<Failure, Success>(
|
||||
StartDownloadAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
cancelToken,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
),
|
||||
);
|
||||
yield loadingState;
|
||||
onReceiveController?.add(loadingState);
|
||||
|
||||
final currentAccount = await _accountRepository.getCurrentAccount();
|
||||
AccountRequest? accountRequest;
|
||||
@@ -72,6 +83,7 @@ class DownloadAttachmentForWebInteractor {
|
||||
attachment,
|
||||
bytesDownloaded,
|
||||
previewerSupported,
|
||||
sourceView,
|
||||
)
|
||||
);
|
||||
} catch (exception) {
|
||||
@@ -79,8 +91,9 @@ class DownloadAttachmentForWebInteractor {
|
||||
DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
taskId: taskId,
|
||||
exception: exception,
|
||||
sourceView: sourceView,
|
||||
cancelToken: cancelToken,
|
||||
exception: exception,
|
||||
)
|
||||
);
|
||||
}
|
||||
+10
-10
@@ -9,31 +9,31 @@ import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/account/authentication_type.dart';
|
||||
import 'package:model/account/password.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/export_all_attachments_state.dart';
|
||||
import 'package:tmail_ui_user/features/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._emailRepository,
|
||||
this._downloadRepository,
|
||||
this._accountRepository,
|
||||
this._authenticationOIDCRepository,
|
||||
this.credentialRepository,
|
||||
this._credentialRepository,
|
||||
);
|
||||
|
||||
final EmailRepository _emailRepository;
|
||||
final DownloadRepository _downloadRepository;
|
||||
final AccountRepository _accountRepository;
|
||||
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
||||
final CredentialRepository credentialRepository;
|
||||
final CredentialRepository _credentialRepository;
|
||||
|
||||
Stream<Either<Failure, Success>> execute(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
{CancelToken? cancelToken}
|
||||
CancelToken cancelToken,
|
||||
) async* {
|
||||
try {
|
||||
yield Right(ExportingAllAttachments());
|
||||
@@ -43,20 +43,20 @@ class ExportAllAttachmentsInteractor {
|
||||
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
|
||||
accountRequest = AccountRequest.withOidc(token: tokenOidc);
|
||||
} else {
|
||||
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
|
||||
final authenticationInfoCache = await _credentialRepository.getAuthenticationInfoStored();
|
||||
accountRequest = AccountRequest.withBasic(
|
||||
userName: UserName(authenticationInfoCache.username),
|
||||
password: Password(authenticationInfoCache.password),
|
||||
);
|
||||
}
|
||||
|
||||
final result = await _emailRepository.exportAllAttachments(
|
||||
final result = await _downloadRepository.exportAllAttachments(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
cancelToken: cancelToken,
|
||||
cancelToken,
|
||||
);
|
||||
|
||||
yield Right(ExportAllAttachmentsSuccess(result));
|
||||
+8
-8
@@ -6,21 +6,21 @@ import 'package:dio/dio.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/export_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/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 EmailRepository emailRepository;
|
||||
final CredentialRepository credentialRepository;
|
||||
final DownloadRepository _downloadRepository;
|
||||
final CredentialRepository _credentialRepository;
|
||||
final AccountRepository _accountRepository;
|
||||
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
||||
|
||||
ExportAttachmentInteractor(
|
||||
this.emailRepository,
|
||||
this.credentialRepository,
|
||||
this._downloadRepository,
|
||||
this._credentialRepository,
|
||||
this._accountRepository,
|
||||
this._authenticationOIDCRepository,
|
||||
);
|
||||
@@ -40,14 +40,14 @@ class ExportAttachmentInteractor {
|
||||
final tokenOidc = await _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id);
|
||||
accountRequest = AccountRequest.withOidc(token: tokenOidc);
|
||||
} else {
|
||||
final authenticationInfoCache = await credentialRepository.getAuthenticationInfoStored();
|
||||
final authenticationInfoCache = await _credentialRepository.getAuthenticationInfoStored();
|
||||
accountRequest = AccountRequest.withBasic(
|
||||
userName: UserName(authenticationInfoCache.username),
|
||||
password: Password(authenticationInfoCache.password),
|
||||
);
|
||||
}
|
||||
|
||||
final downloadedResponse = await emailRepository.exportAttachment(
|
||||
final downloadedResponse = await _downloadRepository.exportAttachment(
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
+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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
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;
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_eml_content_in_memory_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
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;
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/move_preview_eml_content_from_persistent_to_memory_state.dart';
|
||||
import 'package:tmail_ui_user/features/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/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
|
||||
class MovePreviewEmlContentFromPersistentToMemoryInteractor {
|
||||
final DownloadRepository _downloadRepository;
|
||||
+2
-2
@@ -4,8 +4,8 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
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;
|
||||
+3
-2
@@ -3,9 +3,9 @@ import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/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/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
|
||||
class PreviewEmailFromEmlFileInteractor {
|
||||
final DownloadRepository _downloadRepository;
|
||||
@@ -43,6 +43,7 @@ class PreviewEmailFromEmlFileInteractor {
|
||||
previewEmailEMLRequest.accountId,
|
||||
previewEmailEMLRequest.session,
|
||||
previewEmailEMLRequest.ownEmailAddress,
|
||||
previewEmailEMLRequest.appLocalizations,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/remove_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
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;
|
||||
+38
-14
@@ -3,6 +3,22 @@ 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';
|
||||
@@ -11,22 +27,9 @@ import 'package:tmail_ui_user/features/email/data/datasource_impl/email_session_
|
||||
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/email/domain/usecases/download_all_attachments_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_eml_content_in_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_preview_eml_content_from_persistent_to_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/remove_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/download_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/download_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/download_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
||||
|
||||
@@ -84,6 +87,22 @@ class DownloadInteractorBindings extends InteractorsBindings {
|
||||
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>()),
|
||||
);
|
||||
@@ -91,7 +110,7 @@ class DownloadInteractorBindings extends InteractorsBindings {
|
||||
() => PreviewEmailFromEmlFileInteractor(Get.find<DownloadRepository>()),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => GetHtmlContentFromAttachmentInteractor(
|
||||
() => DownloadAndGetHtmlContentFromAttachmentInteractor(
|
||||
Get.find<DownloadAttachmentForWebInteractor>(),
|
||||
),
|
||||
);
|
||||
@@ -116,6 +135,11 @@ class DownloadInteractorBindings extends InteractorsBindings {
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => GetHtmlContentFromUploadFileInteractor(
|
||||
Get.find<DownloadRepository>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -57,11 +57,12 @@ import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/mail_api_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_all_attachments_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
@@ -343,12 +344,18 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin {
|
||||
progress = (downloaded / total) * 100;
|
||||
}
|
||||
log('EmailAPI::downloadFileForWeb(): progress = ${progress.round()}%');
|
||||
onReceiveController?.add(Right(DownloadingAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
progress,
|
||||
downloaded,
|
||||
total)));
|
||||
onReceiveController?.add(
|
||||
Right(
|
||||
DownloadingAttachmentForWeb(
|
||||
taskId,
|
||||
attachment,
|
||||
progress,
|
||||
downloaded,
|
||||
total,
|
||||
DownloadSourceView.emailView,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/model/source_type/data_source_type.dart';
|
||||
import 'package:core/data/network/download/downloaded_response.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@@ -14,8 +13,6 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:model/email/mark_star_action.dart';
|
||||
import 'package:model/email/read_actions.dart';
|
||||
@@ -135,22 +132,6 @@ class EmailRepositoryImpl extends EmailRepository {
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DownloadedResponse> exportAttachment(
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest,
|
||||
CancelToken cancelToken
|
||||
) {
|
||||
return emailDataSource[DataSourceType.network]!.exportAttachment(
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
accountRequest,
|
||||
cancelToken);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<({
|
||||
List<EmailId> emailIdsSuccess,
|
||||
@@ -494,22 +475,6 @@ class EmailRepositoryImpl extends EmailRepository {
|
||||
return _printFileDataSource.printEmail(emailPrint);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DownloadedResponse> exportAllAttachments(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest, {
|
||||
CancelToken? cancelToken,
|
||||
}) => emailDataSource[DataSourceType.network]!.exportAllAttachments(
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
accountRequest,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
|
||||
return emailDataSource[DataSourceType.local]!.generateEntireMessageAsDocument(entireMessageRequest);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
class DownloadAttachmentInteractorIsNull implements Exception {}
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/network/download/downloaded_response.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:email_recovery/email_recovery/email_recovery_action.dart';
|
||||
@@ -12,8 +11,6 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/account/account_request.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:model/email/mark_star_action.dart';
|
||||
import 'package:model/email/read_actions.dart';
|
||||
@@ -52,14 +49,6 @@ abstract class EmailRepository {
|
||||
ReadActions readActions,
|
||||
);
|
||||
|
||||
Future<DownloadedResponse> exportAttachment(
|
||||
Attachment attachment,
|
||||
AccountId accountId,
|
||||
String baseDownloadUrl,
|
||||
AccountRequest accountRequest,
|
||||
CancelToken cancelToken
|
||||
);
|
||||
|
||||
Future<({
|
||||
List<EmailId> emailIdsSuccess,
|
||||
Map<Id, SetError> mapErrors,
|
||||
@@ -170,14 +159,5 @@ abstract class EmailRepository {
|
||||
|
||||
Future<void> printEmail(EmailPrint emailPrint);
|
||||
|
||||
Future<DownloadedResponse> exportAllAttachments(
|
||||
AccountId accountId,
|
||||
EmailId emailId,
|
||||
String baseDownloadAllUrl,
|
||||
String outputFileName,
|
||||
AccountRequest accountRequest,
|
||||
{CancelToken? cancelToken}
|
||||
);
|
||||
|
||||
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
|
||||
class GettingHtmlContentFromAttachment extends LoadingState {
|
||||
GettingHtmlContentFromAttachment({required this.attachment});
|
||||
|
||||
final Attachment attachment;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [attachment];
|
||||
}
|
||||
|
||||
class GetHtmlContentFromAttachmentSuccess extends UIState {
|
||||
GetHtmlContentFromAttachmentSuccess({
|
||||
required this.sanitizedHtmlContent,
|
||||
required this.htmlAttachmentTitle,
|
||||
required this.attachment,
|
||||
});
|
||||
|
||||
final String sanitizedHtmlContent;
|
||||
final String htmlAttachmentTitle;
|
||||
final Attachment attachment;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
sanitizedHtmlContent,
|
||||
htmlAttachmentTitle,
|
||||
attachment,
|
||||
];
|
||||
}
|
||||
|
||||
class GetHtmlContentFromAttachmentFailure extends FeatureFailure {
|
||||
GetHtmlContentFromAttachmentFailure({super.exception, required this.attachment});
|
||||
|
||||
final Attachment attachment;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [attachment];
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
|
||||
@@ -22,12 +20,10 @@ class EmailBindings extends Bindings {
|
||||
Get.put(SingleEmailController(
|
||||
Get.find<GetEmailContentInteractor>(),
|
||||
Get.find<MarkAsEmailReadInteractor>(),
|
||||
Get.find<ExportAttachmentInteractor>(),
|
||||
Get.find<MarkAsStarEmailInteractor>(),
|
||||
Get.find<GetAllIdentitiesInteractor>(),
|
||||
Get.find<StoreOpenedEmailInteractor>(),
|
||||
Get.find<PrintEmailInteractor>(),
|
||||
Get.find<ExportAllAttachmentsInteractor>(),
|
||||
currentEmailId: currentEmailId,
|
||||
), tag: tag);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_entire_message_as_document_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart';
|
||||
@@ -26,9 +24,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart';
|
||||
@@ -111,23 +106,12 @@ class EmailInteractorBindings extends InteractorsBindings {
|
||||
void bindingsInteractor() {
|
||||
Get.lazyPut(() => GetEmailContentInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => MarkAsEmailReadInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => ExportAttachmentInteractor(
|
||||
Get.find<EmailRepository>(),
|
||||
Get.find<CredentialRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
));
|
||||
Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => GetStoredEmailStateInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => StoreOpenedEmailInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => PrintEmailInteractor(Get.find<EmailRepository>()));
|
||||
IdentityInteractorsBindings().dependencies();
|
||||
Get.lazyPut(() => ExportAllAttachmentsInteractor(
|
||||
Get.find<EmailRepository>(),
|
||||
Get.find<AccountRepository>(),
|
||||
Get.find<AuthenticationOIDCRepository>(),
|
||||
Get.find<CredentialRepository>()));
|
||||
if (PlatformInfo.isIOS) {
|
||||
Get.lazyPut(() => GetEntireMessageAsDocumentInteractor(
|
||||
Get.find<EmailRepository>(),
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/text/new_line_transformer.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
@@ -26,12 +23,12 @@ import 'package:jmap_dart_client/jmap/mdn/disposition.dart';
|
||||
import 'package:jmap_dart_client/jmap/mdn/mdn.dart';
|
||||
import 'package:model/error_type_handler/unknown_uri_exception.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:open_file/open_file.dart' as open_file;
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
|
||||
import 'package:tmail_ui_user/features/base/state/button_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
|
||||
@@ -43,9 +40,6 @@ import 'package:tmail_ui_user/features/email/domain/state/calendar_event_counter
|
||||
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_maybe_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reject_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/export_all_attachments_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/export_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_entire_message_as_document_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
||||
@@ -57,8 +51,6 @@ import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_stat
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_entire_message_as_document_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
@@ -71,7 +63,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_
|
||||
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/bindings/calendar_event_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/bindings/mdn_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_attendee_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_organizer_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/handle_mail_action_by_shortcut_action_extension.dart';
|
||||
@@ -84,12 +75,11 @@ import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscrib
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preview_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
|
||||
@@ -121,12 +111,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
|
||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
||||
final ExportAttachmentInteractor _exportAttachmentInteractor;
|
||||
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
|
||||
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
|
||||
final StoreOpenedEmailInteractor _storeOpenedEmailInteractor;
|
||||
final PrintEmailInteractor _printEmailInteractor;
|
||||
final ExportAllAttachmentsInteractor _exportAllAttachmentsInteractor;
|
||||
final EmailId? _currentEmailId;
|
||||
|
||||
CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
|
||||
@@ -193,12 +181,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
SingleEmailController(
|
||||
this._getEmailContentInteractor,
|
||||
this._markAsEmailReadInteractor,
|
||||
this._exportAttachmentInteractor,
|
||||
this._markAsStarEmailInteractor,
|
||||
this._getAllIdentitiesInteractor,
|
||||
this._storeOpenedEmailInteractor,
|
||||
this._printEmailInteractor,
|
||||
this._exportAllAttachmentsInteractor, {
|
||||
this._printEmailInteractor, {
|
||||
EmailId? currentEmailId,
|
||||
}) : _currentEmailId = currentEmailId;
|
||||
|
||||
@@ -236,10 +222,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_getEmailContentOfflineSuccess(success);
|
||||
} else if (success is MarkAsEmailReadSuccess) {
|
||||
_handleMarkAsEmailReadCompleted(success);
|
||||
} else if (success is ExportAttachmentSuccess) {
|
||||
_exportAttachmentSuccessAction(success);
|
||||
} else if (success is ExportAllAttachmentsSuccess) {
|
||||
_exportAllAttachmentsSuccessAction(success);
|
||||
} else if (success is MarkAsStarEmailSuccess) {
|
||||
_markAsEmailStarSuccess(success);
|
||||
} else if (success is GetAllIdentitiesSuccess) {
|
||||
@@ -267,10 +249,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
void handleFailureViewState(Failure failure) {
|
||||
if (failure is MarkAsEmailReadFailure) {
|
||||
_handleMarkAsEmailReadFailure(failure);
|
||||
} else if (failure is ExportAttachmentFailure) {
|
||||
_exportAttachmentFailureAction(failure);
|
||||
} else if (failure is ExportAllAttachmentsFailure) {
|
||||
_exportAllAttachmentsFailureAction(failure);
|
||||
} else if (failure is ParseCalendarEventFailure) {
|
||||
_handleParseCalendarEventFailure(failure);
|
||||
} else if (failure is GetEmailContentFailure) {
|
||||
@@ -697,173 +675,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_threadDetailController?.markCollapsedEmailReadSuccess(success);
|
||||
}
|
||||
|
||||
void exportAttachment(Attachment attachment) {
|
||||
final cancelToken = CancelToken();
|
||||
_showDownloadingFileDialog(attachment.name ?? '', cancelToken: cancelToken);
|
||||
_exportAttachmentAction(attachment, cancelToken);
|
||||
}
|
||||
|
||||
void _showDownloadingFileDialog(String attachmentName, {CancelToken? cancelToken}) {
|
||||
if (cancelToken != null) {
|
||||
Get.dialog(
|
||||
PointerInterceptor(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
return (DownloadingFileDialogBuilder()
|
||||
..key(const Key('downloading_file_dialog'))
|
||||
..title(appLocalizations.preparing_to_export)
|
||||
..content(appLocalizations.downloading_file(attachmentName))
|
||||
..actionText(appLocalizations.cancel)
|
||||
..addCancelDownloadActionClick(() {
|
||||
cancelToken.cancel([
|
||||
appLocalizations.user_cancel_download_file,
|
||||
]);
|
||||
popBack();
|
||||
}))
|
||||
.build();
|
||||
},
|
||||
),
|
||||
),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
} else {
|
||||
Get.dialog(
|
||||
PointerInterceptor(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
return (DownloadingFileDialogBuilder()
|
||||
..key(const Key('downloading_file_for_web_dialog'))
|
||||
..title(appLocalizations.preparing_to_save)
|
||||
..content(
|
||||
appLocalizations.downloading_file(attachmentName),
|
||||
))
|
||||
.build();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _exportAttachmentAction(Attachment attachment, CancelToken cancelToken) {
|
||||
if (accountId != null && session != null) {
|
||||
try {
|
||||
final baseDownloadUrl = session!.getDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
consumeState(_exportAttachmentInteractor.execute(
|
||||
attachment,
|
||||
accountId!,
|
||||
baseDownloadUrl,
|
||||
cancelToken,
|
||||
));
|
||||
} catch (e) {
|
||||
logError('SingleEmailController::_exportAttachmentAction(): $e');
|
||||
consumeState(Stream.value(Left(ExportAttachmentFailure(e))));
|
||||
}
|
||||
} else {
|
||||
consumeState(Stream.value(Left(ExportAttachmentFailure(NotFoundAccountIdException()))));
|
||||
}
|
||||
}
|
||||
|
||||
void exportAllAttachments(String outputFileName) {
|
||||
final cancelToken = CancelToken();
|
||||
_showDownloadingFileDialog(outputFileName, cancelToken: cancelToken);
|
||||
_exportAllAttachmentsAction(outputFileName, cancelToken);
|
||||
}
|
||||
|
||||
void _exportAllAttachmentsAction(String outputFileName, CancelToken cancelToken) {
|
||||
if (accountId == null || session == null) {
|
||||
consumeState(Stream.value(Left(ExportAllAttachmentsFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
))));
|
||||
return;
|
||||
}
|
||||
|
||||
final downloadAllSupported = session!.isDownloadAllSupported(accountId);
|
||||
if (!downloadAllSupported) {
|
||||
consumeState(Stream.value(Left(ExportAllAttachmentsFailure())));
|
||||
return;
|
||||
}
|
||||
|
||||
final baseDownloadAllUrl = session!.getDownloadAllCapability(accountId)!.endpoint!;
|
||||
consumeState(_exportAllAttachmentsInteractor.execute(
|
||||
accountId!,
|
||||
currentEmail!.id!,
|
||||
baseDownloadAllUrl,
|
||||
outputFileName,
|
||||
cancelToken: cancelToken,
|
||||
));
|
||||
}
|
||||
|
||||
void _exportAttachmentFailureAction(ExportAttachmentFailure failure) {
|
||||
if (failure.exception is! CancelDownloadFileException) {
|
||||
if (Get.isDialogOpen == true) {
|
||||
popBack();
|
||||
}
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).attachment_download_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _exportAttachmentSuccessAction(ExportAttachmentSuccess success) async {
|
||||
popBack();
|
||||
_openDownloadedPreviewWorkGroupDocument(success.downloadedResponse);
|
||||
}
|
||||
|
||||
void _exportAllAttachmentsFailureAction(ExportAllAttachmentsFailure failure) {
|
||||
if (failure.exception is! CancelDownloadFileException) {
|
||||
popBack();
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).attachment_download_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _exportAllAttachmentsSuccessAction(ExportAllAttachmentsSuccess success) {
|
||||
popBack();
|
||||
_saveFileToStorage(success.downloadedResponse.filePath);
|
||||
}
|
||||
|
||||
void _openDownloadedPreviewWorkGroupDocument(DownloadedResponse downloadedResponse) async {
|
||||
log('SingleEmailController::_openDownloadedPreviewWorkGroupDocument(): $downloadedResponse');
|
||||
final filePath = downloadedResponse.filePath;
|
||||
final mediaType = downloadedResponse.mediaType;
|
||||
|
||||
if (mediaType == null) {
|
||||
_saveFileToStorage(filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
final openResult = await open_file.OpenFile.open(
|
||||
filePath,
|
||||
type: Platform.isAndroid ? mediaType.mimeType : null,
|
||||
// "xdg" is default value
|
||||
linuxDesktopName: Platform.isIOS
|
||||
? mediaType.getDocumentUti().value ?? 'xdg'
|
||||
: 'xdg',
|
||||
);
|
||||
|
||||
if (openResult.type != open_file.ResultType.done) {
|
||||
logError('SingleEmailController::_openDownloadedPreviewWorkGroupDocument(): no preview available');
|
||||
_saveFileToStorage(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveFileToStorage(String filePath) async {
|
||||
final params = SaveFileDialogParams(sourceFilePath: filePath);
|
||||
await FlutterFileDialog.saveFile(params: params);
|
||||
}
|
||||
|
||||
bool isDownloadAllSupported() {
|
||||
return session?.isDownloadAllSupported(accountId) ?? false;
|
||||
}
|
||||
@@ -1059,7 +870,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_printEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.downloadMessageAsEML:
|
||||
mailboxDashBoardController.downloadMessageAsEML(presentationEmail);
|
||||
mailboxDashBoardController.downloadMessageAsEML(
|
||||
presentationEmail: presentationEmail,
|
||||
showBottomDownloadProgressBar: true,
|
||||
);
|
||||
break;
|
||||
case EmailActionType.editAsNewEmail:
|
||||
_editAsNewEmail(presentationEmail);
|
||||
@@ -1100,8 +914,10 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> openMailToLink(Uri? uri) =>
|
||||
mailboxDashBoardController.openMailToLink(uri);
|
||||
void openMailToLink(Uri? uri) {
|
||||
if (uri == null) return;
|
||||
mailboxDashBoardController.openComposerFromMailToLink(uri);
|
||||
}
|
||||
|
||||
void deleteEmailPermanently(PresentationEmail email) {
|
||||
emailActionReactor.deleteEmailPermanently(
|
||||
@@ -1618,68 +1434,36 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
Attachment attachment,
|
||||
{bool previewerSupported = false}
|
||||
) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
mailboxDashBoardController.downloadAttachmentForWeb(
|
||||
attachment: attachment,
|
||||
previewerSupported: previewerSupported,
|
||||
);
|
||||
} else if (PlatformInfo.isMobile) {
|
||||
exportAttachment(attachment);
|
||||
} else {
|
||||
log('$runtimeType::handleDownloadAttachmentAction: THE PLATFORM IS SUPPORTED');
|
||||
}
|
||||
mailboxDashBoardController.downloadAttachment(
|
||||
attachment: attachment,
|
||||
previewerSupported: previewerSupported,
|
||||
showBottomDownloadProgressBar: true,
|
||||
sourceView: DownloadSourceView.emailView,
|
||||
);
|
||||
}
|
||||
|
||||
void handleDownloadAllAttachmentsAction(String outputFileName) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
mailboxDashBoardController.downloadAllAttachmentsForWeb(
|
||||
outputFileName: outputFileName,
|
||||
currentEmail: currentEmail,
|
||||
);
|
||||
} else if (PlatformInfo.isMobile) {
|
||||
exportAllAttachments(outputFileName);
|
||||
} else {
|
||||
log('EmailView::handleDownloadAllAttachmentsAction: THE PLATFORM IS SUPPORTED');
|
||||
}
|
||||
mailboxDashBoardController.downloadAllAttachments(
|
||||
outputFileName: outputFileName,
|
||||
emailId: currentEmail?.id,
|
||||
showBottomDownloadProgressBar: true,
|
||||
);
|
||||
}
|
||||
|
||||
void handleViewAttachmentAction(BuildContext context, Attachment attachment) {
|
||||
mailboxDashBoardController.previewAttachmentAction(
|
||||
mailboxDashBoardController.previewAttachment(
|
||||
context: context,
|
||||
attachment: attachment,
|
||||
onDownloadAttachment: (attachment) {
|
||||
sourceView: DownloadSourceView.emailView,
|
||||
onPreviewOrDownloadAction: (attachment, isPreview) {
|
||||
handleDownloadAttachmentAction(
|
||||
attachment,
|
||||
previewerSupported: attachment.isPreviewSupported,
|
||||
previewerSupported: isPreview,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openEMLPreviewer(BuildContext context, Uri? uri) async {
|
||||
log('SingleEmailController::_openEMLPreviewer:uri = $uri');
|
||||
if (uri == null) return;
|
||||
|
||||
final blobId = uri.path;
|
||||
log('SingleEmailController::_openEMLPreviewer:blobId = $blobId');
|
||||
if (blobId.isEmpty) return;
|
||||
|
||||
mailboxDashBoardController.previewEMLFileAction(
|
||||
appLocalizations: AppLocalizations.of(context),
|
||||
blobId: Id(blobId),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _downloadAttachmentInEMLPreview(Uri? uri) async {
|
||||
log('SingleEmailController::_downloadAttachmentInEMLPreview:uri = $uri');
|
||||
if (uri == null) return;
|
||||
|
||||
final attachment = EmailUtils.parsingAttachmentByUri(uri);
|
||||
if (attachment == null) return;
|
||||
|
||||
handleDownloadAttachmentAction(attachment);
|
||||
}
|
||||
|
||||
void handleMailToAttendees(CalendarOrganizer? organizer, List<CalendarAttendee>? attendees) {
|
||||
List<EmailAddress> listEmailAddressAttendees = [];
|
||||
|
||||
@@ -1745,9 +1529,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
content: success.messageDocument,
|
||||
),
|
||||
imagePaths: imagePaths,
|
||||
onMailtoAction: openMailToLink,
|
||||
onPreviewAction: (uri) => _openEMLPreviewer(context, uri),
|
||||
onDownloadAction: _downloadAttachmentInEMLPreview,
|
||||
onMailtoAction: (uri) async => openMailToLink(uri),
|
||||
onDownloadFileAction: handleDownloadAttachmentAction,
|
||||
);
|
||||
},
|
||||
onFailure: (_) {
|
||||
|
||||
@@ -336,7 +336,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
Obx(() => CalendarEventDetailWidget(
|
||||
calendarEvent: calendarEvent,
|
||||
emailContent: controller.currentEmailLoaded.value?.htmlContent ?? '',
|
||||
onMailtoDelegateAction: controller.openMailToLink,
|
||||
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
|
||||
presentationEmail: controller.currentEmail,
|
||||
scrollController: scrollController,
|
||||
isInsideThreadDetailView: isInsideThreadDetailView,
|
||||
@@ -385,7 +385,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
contentPadding: 0,
|
||||
useDefaultFontStyle: true,
|
||||
maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight,
|
||||
onMailtoDelegateAction: controller.openMailToLink,
|
||||
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
|
||||
onHtmlContentClippedAction: controller.onHtmlContentClippedAction,
|
||||
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
|
||||
keepAlive: isInsideThreadDetailView,
|
||||
@@ -423,7 +423,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
direction: AppUtils.getCurrentDirection(context),
|
||||
contentPadding: 0,
|
||||
useDefaultFontStyle: true,
|
||||
onMailtoDelegateAction: controller.openMailToLink,
|
||||
onMailtoDelegateAction: (uri) async => controller.openMailToLink(uri),
|
||||
keepAlive: isInsideThreadDetailView,
|
||||
enableQuoteToggle: true,
|
||||
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
|
||||
@@ -474,8 +474,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
),
|
||||
onTapShowAllAttachmentFile: controller.showAllAttachmentsAction,
|
||||
onTapHideAllAttachments: controller.hideAllAttachmentsAction,
|
||||
showDownloadAllAttachmentsButton:
|
||||
controller.downloadAllButtonIsEnabled(),
|
||||
showDownloadAllAttachmentsButton: controller.downloadAllButtonIsEnabled(),
|
||||
onTapDownloadAllButton: () =>
|
||||
controller.handleDownloadAllAttachmentsAction(
|
||||
'TwakeMail-${DateTime.now()}',
|
||||
|
||||
@@ -1,444 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart';
|
||||
import 'package:tmail_ui_user/features/email_previewer/email_previewer_dialog_view.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/utils/toast_manager.dart';
|
||||
|
||||
typedef OnDownloadAttachmentAction = void Function(Attachment attachment);
|
||||
|
||||
mixin PreviewAttachmentMixin {
|
||||
final DownloadManager _downloadManager = Get.find<DownloadManager>();
|
||||
final PrintUtils _printUtils = Get.find<PrintUtils>();
|
||||
final AppToast _appToast = Get.find<AppToast>();
|
||||
final ToastManager _toastManager = Get.find<ToastManager>();
|
||||
final DynamicUrlInterceptors _dynamicUrlInterceptors =
|
||||
Get.find<DynamicUrlInterceptors>();
|
||||
|
||||
void previewAttachmentAction({
|
||||
required BuildContext context,
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required BaseController controller,
|
||||
required ParseEmailByBlobIdInteractor parseEmailInteractor,
|
||||
required GetHtmlContentFromAttachmentInteractor getHtmlInteractor,
|
||||
required OnDownloadAttachmentAction onDownloadAttachment,
|
||||
}) {
|
||||
if (PlatformInfo.isWeb && attachment.isPDFFile) {
|
||||
_previewPDFFile(
|
||||
context: context,
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
);
|
||||
} else if (attachment.isEMLFile) {
|
||||
previewEMLFileAction(
|
||||
appLocalizations: AppLocalizations.of(context),
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: attachment.blobId,
|
||||
controller: controller,
|
||||
parseEmailByBlobIdInteractor: parseEmailInteractor,
|
||||
);
|
||||
} else if (attachment.isHTMLFile) {
|
||||
_previewHtmlFileAction(
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
attachment: attachment,
|
||||
controller: controller,
|
||||
getHtmlInteractor: getHtmlInteractor,
|
||||
);
|
||||
} else {
|
||||
onDownloadAttachment(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _previewPDFFile({
|
||||
required BuildContext context,
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
}) async {
|
||||
if (accountId == null || session == null) {
|
||||
_appToast.showToastErrorMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).noPreviewAvailable,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final downloadUrl = session.getDownloadUrl(
|
||||
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
|
||||
await Get.generalDialog(
|
||||
barrierColor: Colors.black.withValues(alpha: 0.8),
|
||||
pageBuilder: (_, __, ___) {
|
||||
return PointerInterceptor(
|
||||
child: PDFViewer(
|
||||
attachment: attachment,
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl,
|
||||
downloadAction: _downloadPDFFile,
|
||||
printAction: _printPDFFile,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
_appToast.showToastErrorMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).noPreviewAvailable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _downloadPDFFile(Uint8List bytes, String fileName) {
|
||||
_downloadManager.createAnchorElementDownloadFileWeb(bytes, fileName);
|
||||
}
|
||||
|
||||
Future<void> _printPDFFile(Uint8List bytes, String fileName) async {
|
||||
await _printUtils.printPDFFile(bytes, fileName);
|
||||
}
|
||||
|
||||
void previewEMLFileAction({
|
||||
required AppLocalizations appLocalizations,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required Id? blobId,
|
||||
required ParseEmailByBlobIdInteractor parseEmailByBlobIdInteractor,
|
||||
required BaseController controller,
|
||||
}) {
|
||||
SmartDialog.showLoading(
|
||||
msg: appLocalizations.loadingPleaseWait,
|
||||
maskColor: Colors.black38,
|
||||
);
|
||||
|
||||
if (session == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundSessionException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundAccountIdException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blobId == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: ParseEmailByBlobIdFailure(NotFoundBlobIdException([])),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
controller.consumeState(
|
||||
parseEmailByBlobIdInteractor.execute(
|
||||
accountId,
|
||||
session,
|
||||
ownEmailAddress,
|
||||
blobId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
({
|
||||
bool canDownloadAttachment,
|
||||
AccountId? accountId,
|
||||
String? downloadUrl,
|
||||
Id? blobId,
|
||||
}) evaluateAttachment({
|
||||
required Session? session,
|
||||
required AccountId? accountId,
|
||||
required Attachment attachment,
|
||||
}) {
|
||||
String? downloadUrl;
|
||||
try {
|
||||
downloadUrl = session?.getDownloadUrl(
|
||||
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
} catch (e) {
|
||||
downloadUrl = null;
|
||||
}
|
||||
final blobId = attachment.blobId;
|
||||
|
||||
if (accountId == null || downloadUrl == null || blobId == null) {
|
||||
return (
|
||||
canDownloadAttachment: false,
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl,
|
||||
blobId: blobId,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
canDownloadAttachment: true,
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl,
|
||||
blobId: blobId,
|
||||
);
|
||||
}
|
||||
|
||||
void _previewHtmlFileAction({
|
||||
required Session? session,
|
||||
required AccountId? accountId,
|
||||
required Attachment attachment,
|
||||
required BaseController controller,
|
||||
required GetHtmlContentFromAttachmentInteractor getHtmlInteractor,
|
||||
}) {
|
||||
final attachmentEvaluation = evaluateAttachment(
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
attachment: attachment,
|
||||
);
|
||||
|
||||
if (!attachmentEvaluation.canDownloadAttachment) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: GetHtmlContentFromAttachmentFailure(
|
||||
exception: null,
|
||||
attachment: attachment,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
controller.consumeState(
|
||||
getHtmlInteractor.execute(
|
||||
attachmentEvaluation.accountId!,
|
||||
attachment,
|
||||
DownloadTaskId(attachmentEvaluation.blobId!.value),
|
||||
attachmentEvaluation.downloadUrl!,
|
||||
TransformConfiguration.create(
|
||||
customDomTransformers: [SanitizeHyperLinkTagInHtmlTransformer()],
|
||||
customTextTransformers: [
|
||||
const StandardizeHtmlSanitizingTransformers()
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _emitFailure({
|
||||
required BaseController controller,
|
||||
required FeatureFailure failure,
|
||||
}) {
|
||||
controller.consumeState(Stream.value(Left(failure)));
|
||||
}
|
||||
|
||||
void handleParseEmailByBlobIdSuccess({
|
||||
required BuildContext? context,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
required String ownEmailAddress,
|
||||
required Id blobId,
|
||||
required Email email,
|
||||
required BaseController controller,
|
||||
required PreviewEmailFromEmlFileInteractor previewInteractor,
|
||||
}) {
|
||||
if (session == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: PreviewEmailFromEmlFileFailure(NotFoundSessionException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountId == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: PreviewEmailFromEmlFileFailure(NotFoundAccountIdException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: PreviewEmailFromEmlFileFailure(NotFoundContextException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
controller.consumeState(previewInteractor.execute(
|
||||
PreviewEmailEMLRequest(
|
||||
accountId: accountId,
|
||||
session: session,
|
||||
ownEmailAddress: ownEmailAddress,
|
||||
blobId: blobId,
|
||||
email: email,
|
||||
locale: Localizations.localeOf(context),
|
||||
appLocalizations: AppLocalizations.of(context),
|
||||
baseDownloadUrl: session.getDownloadUrl(
|
||||
jmapUrl: _dynamicUrlInterceptors.jmapUrl,
|
||||
),
|
||||
),
|
||||
));
|
||||
} catch (e) {
|
||||
_emitFailure(
|
||||
controller: controller,
|
||||
failure: PreviewEmailFromEmlFileFailure(e),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void handleParseEmailByBlobIdFailure(ParseEmailByBlobIdFailure failure) {
|
||||
SmartDialog.dismiss();
|
||||
_toastManager.showMessageFailure(failure);
|
||||
}
|
||||
|
||||
void handlePreviewEmailFromEMLFileFailure(
|
||||
PreviewEmailFromEmlFileFailure failure,
|
||||
) {
|
||||
SmartDialog.dismiss();
|
||||
_toastManager.showMessageFailure(failure);
|
||||
}
|
||||
|
||||
void handlePreviewEmailFromEMLFileSuccess({
|
||||
required EMLPreviewer emlPreviewer,
|
||||
required BuildContext? context,
|
||||
required ImagePaths imagePaths,
|
||||
required OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
}) {
|
||||
SmartDialog.dismiss();
|
||||
|
||||
if (PlatformInfo.isWeb) {
|
||||
bool isOpen = HtmlUtils.openNewWindowByUrl(
|
||||
RouteUtils.createUrlWebLocationBar(
|
||||
AppRoutes.emailEMLPreviewer,
|
||||
previewId: emlPreviewer.id,
|
||||
).toString(),
|
||||
);
|
||||
|
||||
if (!isOpen) {
|
||||
_toastManager.showMessageFailure(
|
||||
PreviewEmailFromEmlFileFailure(CannotOpenNewWindowException()),
|
||||
);
|
||||
}
|
||||
} else if (PlatformInfo.isMobile) {
|
||||
if (context == null) {
|
||||
_toastManager.showMessageFailure(
|
||||
PreviewEmailFromEmlFileFailure(NotFoundContextException()),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlatformInfo.isAndroid) {
|
||||
showModalSheetToPreviewEMLAttachment(
|
||||
context: context,
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoAction: onMailtoAction,
|
||||
onDownloadAction: onDownloadAction,
|
||||
onPreviewAction: onPreviewAction,
|
||||
);
|
||||
} else if (PlatformInfo.isIOS) {
|
||||
showDialogToPreviewEMLAttachment(
|
||||
context: context,
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoAction: onMailtoAction,
|
||||
onDownloadAction: onDownloadAction,
|
||||
onPreviewAction: onPreviewAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showModalSheetToPreviewEMLAttachment({
|
||||
required BuildContext context,
|
||||
required EMLPreviewer emlPreviewer,
|
||||
required ImagePaths imagePaths,
|
||||
required OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
}) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(20.0),
|
||||
topRight: Radius.circular(20.0),
|
||||
),
|
||||
),
|
||||
builder: (_) {
|
||||
return DraggableScrollableSheet(
|
||||
initialChildSize: 1.0,
|
||||
builder: (context, ___) => EmailPreviewerDialogView(
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoDelegateAction: onMailtoAction,
|
||||
onPreviewEMLDelegateAction: onPreviewAction,
|
||||
onDownloadAttachmentDelegateAction: onDownloadAction,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void showDialogToPreviewEMLAttachment({
|
||||
required BuildContext context,
|
||||
required EMLPreviewer emlPreviewer,
|
||||
required ImagePaths imagePaths,
|
||||
required OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
}) {
|
||||
Get.dialog(
|
||||
EmailPreviewerDialogView(
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoDelegateAction: onMailtoAction,
|
||||
onPreviewEMLDelegateAction: onPreviewAction,
|
||||
onDownloadAttachmentDelegateAction: onDownloadAction,
|
||||
),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,8 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_and_get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
@@ -83,11 +83,11 @@ class EmailUtils {
|
||||
return state?.fold(
|
||||
(failure) {
|
||||
return failure is DownloadAttachmentForWebFailure
|
||||
|| failure is GetHtmlContentFromAttachmentFailure;
|
||||
|| failure is DownloadAndGetHtmlContentFromAttachmentFailure;
|
||||
},
|
||||
(success) {
|
||||
return success is DownloadAttachmentForWebSuccess
|
||||
|| success is GetHtmlContentFromAttachmentSuccess
|
||||
|| success is DownloadAndGetHtmlContentFromAttachmentSuccess
|
||||
|| success is IdleDownloadAttachmentForWeb;
|
||||
}) ?? false;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:model/download/download_task_id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/download_attachment_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/exceptions/download_attachment_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/usecase/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:twake_previewer_flutter/core/previewer_options/options/loading_options.dart';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/state/download_attachment_for_web_state.dart';
|
||||
|
||||
class DownloadAttachmentLoadingBar extends StatelessWidget {
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import 'package:core/data/network/download/download_manager.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_eml_content_in_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_preview_eml_content_from_persistent_to_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/remove_preview_email_eml_content_shared_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/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_previewer/email_previewer_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/download_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/bindings/download_interactor_bindings.dart';
|
||||
|
||||
class EmailPreviewerBindings extends Bindings {
|
||||
@override
|
||||
|
||||
@@ -20,18 +20,18 @@ import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dar
|
||||
import 'package:tmail_ui_user/features/caching/exceptions/local_storage_exception.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_eml_content_in_memory_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_email_eml_content_shared_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_preview_eml_content_in_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_preview_eml_content_from_persistent_to_memory_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/remove_preview_email_eml_content_shared_interactor.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/get_preview_email_eml_content_shared_state.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/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_attachment_for_web_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/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/utils/email_utils.dart';
|
||||
|
||||
@@ -3,9 +3,9 @@ import 'package:core/presentation/views/html_viewer/html_content_viewer_on_web_w
|
||||
import 'package:core/presentation/views/loading/cupertino_loading_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_email_eml_content_shared_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_preview_eml_content_in_memory_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.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/state/get_preview_eml_content_in_memory_state.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/email_previewer/download_attachment_loading_bar.dart';
|
||||
import 'package:tmail_ui_user/features/email_previewer/email_previewer_controller.dart';
|
||||
|
||||
@@ -2,7 +2,6 @@ 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/core/id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
|
||||
|
||||
class DownloadUIAction extends UIAction {
|
||||
@@ -24,19 +23,10 @@ class UpdateAttachmentsViewStateAction extends DownloadUIAction {
|
||||
List<Object?> get props => [blobId, viewState];
|
||||
}
|
||||
|
||||
class DownloadAttachmentsQuicklyAction extends DownloadUIAction {
|
||||
DownloadAttachmentsQuicklyAction(this.attachment);
|
||||
class OpenComposerFromMailtoLinkAction extends DownloadUIAction {
|
||||
OpenComposerFromMailtoLinkAction(this.uri);
|
||||
|
||||
final Attachment attachment;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [attachment];
|
||||
}
|
||||
|
||||
class OpenMailtoLinkFromPreviewAttachmentAction extends DownloadUIAction {
|
||||
OpenMailtoLinkFromPreviewAttachmentAction(this.uri);
|
||||
|
||||
final Uri? uri;
|
||||
final Uri uri;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [uri];
|
||||
|
||||
+16
-9
@@ -17,6 +17,8 @@ import 'package:tmail_ui_user/features/composer/data/repository/contact_reposito
|
||||
import 'package:tmail_ui_user/features/composer/domain/repository/contact_repository.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/manager/composer_manager.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/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/print_file_datasource.dart';
|
||||
@@ -32,15 +34,16 @@ import 'package:tmail_ui_user/features/email/data/repository/email_repository_im
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_permanently_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/delete_multiple_emails_permanently_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_all_attachments_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.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_attachment_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/get_html_content_from_upload_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_restored_deleted_message_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/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/email/domain/usecases/restore_deleted_message_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/bindings/email_bindings.dart';
|
||||
@@ -99,10 +102,10 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_re
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_email_sort_order_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_spam_report_state_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/download_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/bindings/download_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
|
||||
@@ -175,12 +178,16 @@ class MailboxDashBoardBindings extends BaseBindings {
|
||||
Get.find<GetAppGridLinagraEcosystemInteractor>(),
|
||||
));
|
||||
Get.put(DownloadController(
|
||||
Get.find<DownloadManager>(),
|
||||
Get.find<PrintUtils>(),
|
||||
Get.find<DownloadAttachmentForWebInteractor>(),
|
||||
Get.find<DownloadAllAttachmentsForWebInteractor>(),
|
||||
Get.find<DownloadManager>(),
|
||||
Get.find<ParseEmailByBlobIdInteractor>(),
|
||||
Get.find<PreviewEmailFromEmlFileInteractor>(),
|
||||
Get.find<GetHtmlContentFromAttachmentInteractor>(),
|
||||
Get.find<DownloadAndGetHtmlContentFromAttachmentInteractor>(),
|
||||
Get.find<GetHtmlContentFromUploadFileInteractor>(),
|
||||
Get.find<ExportAttachmentInteractor>(),
|
||||
Get.find<ExportAllAttachmentsInteractor>(),
|
||||
));
|
||||
Get.put(SearchController(
|
||||
Get.find<QuickSearchEmailInteractor>(),
|
||||
|
||||
-617
@@ -1,617 +0,0 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/network/config/dynamic_url_interceptors.dart';
|
||||
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/platform_info.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
||||
import 'package:http_parser/http_parser.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/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:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_html_content_from_attachment_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_all_attachments_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/mixin/preview_attachment_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/html_attachment_previewer.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/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';
|
||||
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';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
typedef UpdateDownloadTaskStateCallback = DownloadTaskState Function(DownloadTaskState currentState);
|
||||
|
||||
class DownloadController extends BaseController with PreviewAttachmentMixin {
|
||||
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
|
||||
final DownloadAllAttachmentsForWebInteractor
|
||||
_downloadAllAttachmentsForWebInteractor;
|
||||
final DownloadManager _downloadManager;
|
||||
final ParseEmailByBlobIdInteractor parseEmailByBlobIdInteractor;
|
||||
final PreviewEmailFromEmlFileInteractor previewEmailFromEmlFileInteractor;
|
||||
final GetHtmlContentFromAttachmentInteractor
|
||||
getHtmlContentFromAttachmentInteractor;
|
||||
|
||||
DownloadController(
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
this._downloadAllAttachmentsForWebInteractor,
|
||||
this._downloadManager,
|
||||
this.parseEmailByBlobIdInteractor,
|
||||
this.previewEmailFromEmlFileInteractor,
|
||||
this.getHtmlContentFromAttachmentInteractor,
|
||||
);
|
||||
|
||||
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 downloadAttachmentForWeb({
|
||||
required Attachment attachment,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool previewerSupported = false,
|
||||
}) {
|
||||
if (accountId == null || session == null) {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
exception: NotFoundSessionException(),
|
||||
)),
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
final generateTaskId = DownloadTaskId(uuid.v4());
|
||||
try {
|
||||
final baseDownloadUrl = session.getDownloadUrl(
|
||||
jmapUrl: dynamicUrlInterceptors.jmapUrl,
|
||||
);
|
||||
final cancelToken = CancelToken();
|
||||
consumeState(_downloadAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
onReceiveController: _downloadProgressStateController,
|
||||
cancelToken: cancelToken,
|
||||
previewerSupported: previewerSupported,
|
||||
));
|
||||
} catch (e) {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAttachmentForWebFailure(
|
||||
attachment: attachment,
|
||||
taskId: generateTaskId,
|
||||
exception: e,
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void downloadAllAttachmentsForWeb({
|
||||
required String outputFileName,
|
||||
required PresentationEmail? currentEmail,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
bool previewerSupported = false,
|
||||
}) {
|
||||
final taskId = DownloadTaskId(uuid.v4());
|
||||
|
||||
if (accountId == null || session == null) {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAllAttachmentsForWebFailure(
|
||||
exception: NotFoundSessionException(),
|
||||
taskId: taskId,
|
||||
)),
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
final downloadAllSupported = session.isDownloadAllSupported(accountId);
|
||||
final emailId = currentEmail?.id;
|
||||
|
||||
if (!downloadAllSupported || emailId == null) {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAllAttachmentsForWebFailure(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: _downloadProgressStateController,
|
||||
cancelToken: cancelToken,
|
||||
));
|
||||
}
|
||||
|
||||
void downloadMessageAsEML({
|
||||
required PresentationEmail presentationEmail,
|
||||
required AccountId? accountId,
|
||||
required Session? session,
|
||||
}) {
|
||||
if (accountId == null || session == null) return;
|
||||
|
||||
final emlAttachment = presentationEmail.createEMLAttachment();
|
||||
if (emlAttachment.blobId == null) {
|
||||
consumeState(Stream.value(
|
||||
Left(DownloadAttachmentForWebFailure(
|
||||
exception: NotFoundEmailBlobIdException(),
|
||||
)),
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
final generateTaskId = DownloadTaskId(const Uuid().v4());
|
||||
try {
|
||||
final baseDownloadUrl = session.getDownloadUrl(
|
||||
jmapUrl: getBinding<DynamicUrlInterceptors>()?.jmapUrl,
|
||||
);
|
||||
final cancelToken = CancelToken();
|
||||
consumeState(_downloadAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
emlAttachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
onReceiveController: _downloadProgressStateController,
|
||||
cancelToken: cancelToken,
|
||||
previewerSupported: false,
|
||||
));
|
||||
} catch (e) {
|
||||
consumeState(Stream.value(Left(DownloadAttachmentForWebFailure(
|
||||
attachment: emlAttachment,
|
||||
taskId: generateTaskId,
|
||||
exception: e,
|
||||
))));
|
||||
}
|
||||
}
|
||||
|
||||
void _pushDownloadUIAction(DownloadUIAction action) {
|
||||
downloadUIAction.value = action;
|
||||
}
|
||||
|
||||
void _handleDownloadAttachmentForWebSuccess(
|
||||
DownloadAttachmentForWebSuccess success,
|
||||
) {
|
||||
_pushDownloadUIAction(UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
));
|
||||
|
||||
deleteDownloadTask(success.taskId);
|
||||
|
||||
if (!success.previewerSupported) {
|
||||
_downloadManager.createAnchorElementDownloadFileWeb(
|
||||
success.bytes,
|
||||
success.attachment.generateFileName(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (success.attachment.isImage) {
|
||||
_previewImageFile(attachment: success.attachment, bytes: success.bytes);
|
||||
} else if (success.attachment.isText || success.attachment.isJson) {
|
||||
_previewTextPlainFile(
|
||||
attachment: success.attachment,
|
||||
bytes: success.bytes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _downloadAttachmentQuickly(Attachment attachment) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
_pushDownloadUIAction(DownloadAttachmentsQuicklyAction(attachment));
|
||||
}
|
||||
}
|
||||
|
||||
void _previewImageFile({
|
||||
required Uint8List bytes,
|
||||
required Attachment attachment,
|
||||
}) {
|
||||
if (currentContext == null) return;
|
||||
|
||||
Navigator.of(currentContext!).push(GetDialogRoute(
|
||||
pageBuilder: (context, _, __) => PointerInterceptor(
|
||||
child: TwakeImagePreviewer(
|
||||
bytes: bytes,
|
||||
zoomable: true,
|
||||
previewerOptions: const PreviewerOptions(
|
||||
previewerState: PreviewerState.success,
|
||||
),
|
||||
topBarOptions: TopBarOptions(
|
||||
title: attachment.generateFileName(),
|
||||
onClose: () => Navigator.maybePop(context),
|
||||
onDownload: currentContext == null
|
||||
? null
|
||||
: () => _downloadAttachmentQuickly(attachment),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: false,
|
||||
));
|
||||
}
|
||||
|
||||
void _previewTextPlainFile({
|
||||
required Uint8List bytes,
|
||||
required Attachment attachment,
|
||||
}) {
|
||||
if (currentContext == null) return;
|
||||
|
||||
Navigator.of(currentContext!).push(GetDialogRoute(
|
||||
pageBuilder: (context, _, __) => PointerInterceptor(
|
||||
child: TwakePlainTextPreviewer(
|
||||
supportedCharset: SupportedCharset.utf8,
|
||||
bytes: bytes,
|
||||
previewerOptions: PreviewerOptions(
|
||||
previewerState: PreviewerState.success,
|
||||
width: currentContext == null ? 200 : currentContext!.width * 0.8,
|
||||
),
|
||||
topBarOptions: TopBarOptions(
|
||||
title: attachment.generateFileName(),
|
||||
onClose: () => Navigator.maybePop(context),
|
||||
onDownload: currentContext == null
|
||||
? null
|
||||
: () => _downloadAttachmentQuickly(attachment),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: false,
|
||||
));
|
||||
}
|
||||
|
||||
void clearDownloadUIAction() {
|
||||
downloadUIAction.value = null;
|
||||
}
|
||||
|
||||
void _downloadAllAttachmentsForWebFailure(
|
||||
DownloadAllAttachmentsForWebFailure failure,
|
||||
) {
|
||||
deleteDownloadTask(failure.taskId);
|
||||
|
||||
if (currentOverlayContext == null || currentContext == null) return;
|
||||
|
||||
final appLocalizations = AppLocalizations.of(currentContext!);
|
||||
|
||||
String message = failure.cancelToken?.isCancelled == true
|
||||
? appLocalizations.downloadAttachmentHasBeenCancelled
|
||||
: appLocalizations.attachment_download_failed;
|
||||
|
||||
appToast.showToastErrorMessage(currentOverlayContext!, message);
|
||||
}
|
||||
|
||||
void _downloadAttachmentForWebFailureAction(DownloadAttachmentForWebFailure failure) {
|
||||
if (failure.taskId != null) {
|
||||
deleteDownloadTask(failure.taskId!);
|
||||
}
|
||||
|
||||
if (failure.attachment != null) {
|
||||
_pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
failure.attachment?.blobId,
|
||||
Left<Failure, Success>(failure),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (currentOverlayContext == null || currentContext == null) return;
|
||||
|
||||
final appLocalizations = AppLocalizations.of(currentContext!);
|
||||
|
||||
String message = appLocalizations.attachment_download_failed;
|
||||
if (failure.attachment is EMLAttachment) {
|
||||
message = appLocalizations.downloadMessageAsEMLFailed;
|
||||
} else if (failure.cancelToken?.isCancelled == true) {
|
||||
message = appLocalizations.downloadAttachmentHasBeenCancelled;
|
||||
}
|
||||
|
||||
appToast.showToastErrorMessage(currentOverlayContext!, message);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleSuccessViewState(Success success) {
|
||||
if (success is DownloadAttachmentForWebSuccess) {
|
||||
_handleDownloadAttachmentForWebSuccess(success);
|
||||
} else if (success is StartDownloadAttachmentForWeb) {
|
||||
_pushDownloadUIAction(UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
));
|
||||
} else if (success is DownloadingAttachmentForWeb) {
|
||||
_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,
|
||||
controller: this,
|
||||
previewInteractor: previewEmailFromEmlFileInteractor,
|
||||
);
|
||||
} else if (success is PreviewEmailFromEmlFileSuccess) {
|
||||
handlePreviewEmailFromEMLFileSuccess(
|
||||
emlPreviewer: success.emlPreviewer,
|
||||
context: currentContext,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoAction: _openMailtoLink,
|
||||
onDownloadAction: (uri) async {
|
||||
if (uri == null) return;
|
||||
|
||||
final attachment = EmailUtils.parsingAttachmentByUri(uri);
|
||||
if (attachment == null) return;
|
||||
|
||||
_downloadAttachmentQuickly(attachment);
|
||||
},
|
||||
onPreviewAction: (uri) async {
|
||||
if (currentContext != null && uri?.path.isNotEmpty == true) {
|
||||
previewEMLFileAction(
|
||||
appLocalizations: AppLocalizations.of(currentContext!),
|
||||
accountId: success.accountId,
|
||||
session: success.session,
|
||||
ownEmailAddress: success.ownEmailAddress,
|
||||
blobId: Id(uri!.path),
|
||||
controller: this,
|
||||
parseEmailByBlobIdInteractor: parseEmailByBlobIdInteractor,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
} else if (success is GetHtmlContentFromAttachmentSuccess) {
|
||||
_pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
),
|
||||
);
|
||||
|
||||
Get.dialog(HtmlAttachmentPreviewer(
|
||||
title: success.htmlAttachmentTitle,
|
||||
htmlContent: success.sanitizedHtmlContent,
|
||||
mailToClicked: _openMailtoLink,
|
||||
downloadAttachmentClicked: () =>
|
||||
_downloadAttachmentQuickly(success.attachment),
|
||||
responsiveUtils: responsiveUtils,
|
||||
));
|
||||
} else if (success is GettingHtmlContentFromAttachment) {
|
||||
_pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
success.attachment.blobId,
|
||||
Right<Failure, Success>(success),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
super.handleSuccessViewState(success);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleFailureViewState(Failure failure) {
|
||||
if (failure is DownloadAllAttachmentsForWebFailure) {
|
||||
_downloadAllAttachmentsForWebFailure(failure);
|
||||
} else if (failure is DownloadAttachmentForWebFailure) {
|
||||
_downloadAttachmentForWebFailureAction(failure);
|
||||
} else if (failure is ParseEmailByBlobIdFailure) {
|
||||
handleParseEmailByBlobIdFailure(failure);
|
||||
} else if (failure is PreviewEmailFromEmlFileFailure) {
|
||||
handlePreviewEmailFromEMLFileFailure(failure);
|
||||
} else if (failure is GetHtmlContentFromAttachmentFailure) {
|
||||
_handleGetHtmlContentFromAttachmentFailure(failure);
|
||||
} else {
|
||||
super.handleFailureViewState(failure);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleGetHtmlContentFromAttachmentFailure(
|
||||
GetHtmlContentFromAttachmentFailure failure,
|
||||
) {
|
||||
_pushDownloadUIAction(
|
||||
UpdateAttachmentsViewStateAction(
|
||||
failure.attachment.blobId,
|
||||
Left<Failure, Success>(failure),
|
||||
),
|
||||
);
|
||||
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!)
|
||||
.thisHtmlAttachmentCannotBePreviewed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _openMailtoLink(Uri? uri) async {
|
||||
_pushDownloadUIAction(OpenMailtoLinkFromPreviewAttachmentAction(uri));
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_downloadProgressStateSubscription?.cancel();
|
||||
_downloadProgressStateSubscription = null;
|
||||
_downloadProgressStateController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
+3
-7
@@ -50,6 +50,7 @@ import 'package:tmail_ui_user/features/composer/presentation/manager/composer_ma
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/compose_action_mode.dart';
|
||||
import 'package:tmail_ui_user/features/contact/presentation/model/contact_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/mark_read_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
|
||||
@@ -113,7 +114,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_e
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart' as search;
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/cleanup_recent_search_extension.dart';
|
||||
@@ -121,7 +121,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_action_type_for_email_selection.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_clear_mailbox_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_create_new_rule_filter.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preferences_setting_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preview_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_reactive_obx_variable_extension.dart';
|
||||
@@ -765,11 +764,8 @@ class MailboxDashBoardController extends ReloadableController
|
||||
_downloadUIActionWorker = ever(
|
||||
downloadController.downloadUIAction,
|
||||
(action) {
|
||||
if (action is DownloadAttachmentsQuicklyAction) {
|
||||
downloadAttachmentForWeb(attachment: action.attachment);
|
||||
downloadController.clearDownloadUIAction();
|
||||
} else if (action is OpenMailtoLinkFromPreviewAttachmentAction) {
|
||||
openMailToLink(action.uri);
|
||||
if (action is OpenComposerFromMailtoLinkAction) {
|
||||
openComposerFromMailToLink(action.uri);
|
||||
downloadController.clearDownloadUIAction();
|
||||
}
|
||||
},
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/extensions/download_attachment_download_controller_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
|
||||
extension HandleDownloadAttachmentExtension on MailboxDashBoardController {
|
||||
void downloadMessageAsEML({
|
||||
required PresentationEmail presentationEmail,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
}) =>
|
||||
downloadController.downloadMessageAsEML(
|
||||
presentationEmail: presentationEmail,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
showBottomDownloadProgressBar: showBottomDownloadProgressBar,
|
||||
);
|
||||
|
||||
void downloadAttachment({
|
||||
required Attachment attachment,
|
||||
bool previewerSupported = false,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) =>
|
||||
downloadController.downloadAttachment(
|
||||
attachment: attachment,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
previewerSupported: previewerSupported,
|
||||
showBottomDownloadProgressBar: showBottomDownloadProgressBar,
|
||||
sourceView: sourceView,
|
||||
);
|
||||
|
||||
void downloadAllAttachments({
|
||||
required String outputFileName,
|
||||
required EmailId? emailId,
|
||||
bool showBottomDownloadProgressBar = false,
|
||||
}) =>
|
||||
downloadController.downloadAllAttachments(
|
||||
outputFileName: outputFileName,
|
||||
emailId: emailId,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
showBottomDownloadProgressBar: showBottomDownloadProgressBar,
|
||||
);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
|
||||
extension HandleDownloadExtension on MailboxDashBoardController {
|
||||
void downloadMessageAsEML(PresentationEmail presentationEmail) {
|
||||
downloadController.downloadMessageAsEML(
|
||||
presentationEmail: presentationEmail,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
);
|
||||
}
|
||||
|
||||
void downloadAttachmentForWeb({
|
||||
required Attachment attachment,
|
||||
bool previewerSupported = false,
|
||||
}) {
|
||||
downloadController.downloadAttachmentForWeb(
|
||||
attachment: attachment,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
previewerSupported: previewerSupported,
|
||||
);
|
||||
}
|
||||
|
||||
void downloadAllAttachmentsForWeb({
|
||||
required String outputFileName,
|
||||
PresentationEmail? currentEmail,
|
||||
}) {
|
||||
downloadController.downloadAllAttachmentsForWeb(
|
||||
outputFileName: outputFileName,
|
||||
currentEmail: currentEmail,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
);
|
||||
}
|
||||
}
|
||||
+40
-27
@@ -2,48 +2,53 @@ import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/mixin/preview_attachment_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/model/download_source_view.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/email/presentation/model/composer_arguments.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/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_download_attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.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/route_utils.dart';
|
||||
|
||||
extension HandlePreviewAttachmentExtension on MailboxDashBoardController {
|
||||
void previewAttachmentAction({
|
||||
void previewAttachment({
|
||||
required BuildContext context,
|
||||
required Attachment attachment,
|
||||
required OnDownloadAttachmentAction onDownloadAttachment,
|
||||
required OnPreviewOrDownloadAttachmentAction onPreviewOrDownloadAction,
|
||||
bool isDialogLoadingVisible = false,
|
||||
DownloadSourceView? sourceView,
|
||||
}) =>
|
||||
downloadController.previewAttachmentAction(
|
||||
downloadController.previewAttachment(
|
||||
context: context,
|
||||
attachment: attachment,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
ownEmailAddress: ownEmailAddress.value,
|
||||
controller: downloadController,
|
||||
parseEmailInteractor: downloadController.parseEmailByBlobIdInteractor,
|
||||
getHtmlInteractor:
|
||||
downloadController.getHtmlContentFromAttachmentInteractor,
|
||||
onDownloadAttachment: onDownloadAttachment,
|
||||
sourceView: sourceView,
|
||||
onPreviewOrDownloadAction: onPreviewOrDownloadAction,
|
||||
isDialogLoadingVisible: isDialogLoadingVisible,
|
||||
);
|
||||
|
||||
void previewEMLFileAction({
|
||||
required AppLocalizations appLocalizations,
|
||||
required Id? blobId,
|
||||
void previewUploadFile({
|
||||
required BuildContext context,
|
||||
required UploadFileState uploadFile,
|
||||
required OnPreviewOrDownloadAttachmentAction onPreviewOrDownloadAction,
|
||||
bool isDialogLoadingVisible = false,
|
||||
}) =>
|
||||
downloadController.previewEMLFileAction(
|
||||
appLocalizations: appLocalizations,
|
||||
downloadController.previewUploadFile(
|
||||
context: context,
|
||||
uploadFile: uploadFile,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
ownEmailAddress: ownEmailAddress.value,
|
||||
blobId: blobId,
|
||||
controller: downloadController,
|
||||
parseEmailByBlobIdInteractor:
|
||||
downloadController.parseEmailByBlobIdInteractor,
|
||||
onPreviewOrDownloadAction: onPreviewOrDownloadAction,
|
||||
isDialogLoadingVisible: isDialogLoadingVisible,
|
||||
);
|
||||
|
||||
void showDialogToPreviewEMLAttachment({
|
||||
@@ -51,24 +56,32 @@ extension HandlePreviewAttachmentExtension on MailboxDashBoardController {
|
||||
required EMLPreviewer emlPreviewer,
|
||||
required ImagePaths imagePaths,
|
||||
required OnMailtoDelegateAction onMailtoAction,
|
||||
required OnDownloadAttachmentDelegateAction onDownloadAction,
|
||||
required OnPreviewEMLDelegateAction onPreviewAction,
|
||||
required OnDownloadAttachmentFileAction onDownloadFileAction,
|
||||
}) =>
|
||||
downloadController.showDialogToPreviewEMLAttachment(
|
||||
context: context,
|
||||
emlPreviewer: emlPreviewer,
|
||||
imagePaths: imagePaths,
|
||||
onMailtoAction: onMailtoAction,
|
||||
onDownloadAction: onDownloadAction,
|
||||
onPreviewAction: onPreviewAction,
|
||||
onPreviewAction: (uri) => downloadController.openEMLPreviewer(
|
||||
appLocalizations: AppLocalizations.of(context),
|
||||
uri: uri,
|
||||
accountId: accountId.value,
|
||||
session: sessionCurrent,
|
||||
ownEmailAddress: ownEmailAddress.value,
|
||||
),
|
||||
onDownloadAction: (uri) async => downloadController.downloadAttachmentInEMLPreview(
|
||||
uri: uri,
|
||||
onDownloadAction: (attachment) => downloadAttachment(
|
||||
attachment: attachment,
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> openMailToLink(Uri? uri) async {
|
||||
if (uri == null) return;
|
||||
void openComposerFromMailToLink(Uri uri) {
|
||||
final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(
|
||||
uri.toString(),
|
||||
);
|
||||
log('$runtimeType::openMailToLink(): ${uri.toString()}');
|
||||
log('$runtimeType::openComposerFromMailToLink(): ${uri.toString()}');
|
||||
if (!RouteUtils.canOpenComposerFromNavigationRouter(navigationRouter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,6 +267,11 @@ class UploadController extends BaseController {
|
||||
.toList();
|
||||
}
|
||||
|
||||
UploadFileState? getUploadFileId(UploadTaskId id) {
|
||||
return listUploadAttachments
|
||||
.firstWhereOrNull((fileState) => fileState.uploadTaskId == id);
|
||||
}
|
||||
|
||||
Set<EmailBodyPart>? generateAttachments() {
|
||||
if (attachmentsUploaded.isEmpty) {
|
||||
return null;
|
||||
|
||||
@@ -23,8 +23,8 @@ import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_ex
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
|
||||
import 'package:tmail_ui_user/features/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/home/data/exceptions/session_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
|
||||
|
||||
@@ -40,6 +40,14 @@ extension SessionExtension on Session {
|
||||
return downloadUrlDecode;
|
||||
}
|
||||
|
||||
String getSafetyDownloadUrl({String? jmapUrl}) {
|
||||
try {
|
||||
return getDownloadUrl(jmapUrl: jmapUrl);
|
||||
} catch(_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
Uri getUploadUri(AccountId accountId, {String? jmapUrl}) {
|
||||
final Uri uploadUrlValid;
|
||||
if (jmapUrl != null) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/download_repository.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/usecase/parse_email_by_blob_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/download/domain/repository/download_repository.dart';
|
||||
|
||||
import '../../../../fixtures/account_fixtures.dart';
|
||||
import '../../../../fixtures/email_fixtures.dart';
|
||||
|
||||
@@ -29,8 +29,6 @@ import 'package:tmail_ui_user/features/email/domain/state/get_email_content_stat
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
|
||||
@@ -45,7 +43,7 @@ import 'package:tmail_ui_user/features/login/data/network/interceptors/authoriza
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
|
||||
@@ -72,7 +70,6 @@ const fallbackGenerators = {
|
||||
@GenerateNiceMocks([
|
||||
MockSpec<GetEmailContentInteractor>(),
|
||||
MockSpec<MarkAsEmailReadInteractor>(),
|
||||
MockSpec<ExportAttachmentInteractor>(),
|
||||
MockSpec<MarkAsStarEmailInteractor>(),
|
||||
MockSpec<GetAllIdentitiesInteractor>(),
|
||||
MockSpec<StoreOpenedEmailInteractor>(),
|
||||
@@ -100,7 +97,6 @@ const fallbackGenerators = {
|
||||
MockSpec<CalendarEventDataSource>(),
|
||||
MockSpec<DioClient>(),
|
||||
MockSpec<TwakeAppManager>(),
|
||||
MockSpec<ExportAllAttachmentsInteractor>(),
|
||||
MockSpec<FileUploader>(),
|
||||
])
|
||||
void main() {
|
||||
@@ -108,7 +104,6 @@ void main() {
|
||||
|
||||
final getEmailContentInteractor = MockGetEmailContentInteractor();
|
||||
final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor();
|
||||
final exportAttachmentInteractor = MockExportAttachmentInteractor();
|
||||
final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor();
|
||||
final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor();
|
||||
final storeOpenedEmailInteractor = MockStoreOpenedEmailInteractor();
|
||||
@@ -132,8 +127,6 @@ void main() {
|
||||
final mockToastManager = MockToastManager();
|
||||
final mockTwakeAppManager = MockTwakeAppManager();
|
||||
|
||||
final exportAllAttachmentsInteractor = MockExportAllAttachmentsInteractor();
|
||||
|
||||
late SingleEmailController singleEmailController;
|
||||
|
||||
final testAccountId = AccountId(Id('123'));
|
||||
@@ -178,12 +171,10 @@ void main() {
|
||||
singleEmailController = SingleEmailController(
|
||||
getEmailContentInteractor,
|
||||
markAsEmailReadInteractor,
|
||||
exportAttachmentInteractor,
|
||||
markAsStarEmailInteractor,
|
||||
getAllIdentitiesInteractor,
|
||||
storeOpenedEmailInteractor,
|
||||
printEmailInteractor,
|
||||
exportAllAttachmentsInteractor,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_e
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_re
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_email_sort_order_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
|
||||
|
||||
@@ -54,7 +54,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_re
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_email_sort_order_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
|
||||
|
||||
Reference in New Issue
Block a user