From aabfe6a3a5449ba9142ecb241f60a1d5ac9c370b Mon Sep 17 00:00:00 2001 From: DatDang Date: Wed, 26 Feb 2025 11:19:25 +0700 Subject: [PATCH] TF-3450 Refactor image and text preview --- .../preview/supported_preview_file_types.dart | 5 + .../extensions/media_type_extension.dart | 2 + .../download_attachment_for_web_state.dart | 10 +- .../get_image_data_from_attachment_state.dart | 31 ---- .../get_text_data_from_attachment_state.dart | 31 ---- ...ownload_attachment_for_web_interactor.dart | 12 +- ...image_data_from_attachment_interactor.dart | 62 -------- ..._text_data_from_attachment_interactor.dart | 62 -------- .../presentation/bindings/email_bindings.dart | 10 -- .../controller/single_email_controller.dart | 137 +++++++++--------- .../extensions/attachment_extension.dart | 3 + .../email/presentation/utils/email_utils.dart | 4 - .../widgets/email_view_app_bar_widget.dart | 2 +- .../single_email_controller_test.dart | 8 - 14 files changed, 94 insertions(+), 285 deletions(-) delete mode 100644 lib/features/email/domain/state/get_image_data_from_attachment_state.dart delete mode 100644 lib/features/email/domain/state/get_text_data_from_attachment_state.dart delete mode 100644 lib/features/email/domain/usecases/get_image_data_from_attachment_interactor.dart delete mode 100644 lib/features/email/domain/usecases/get_text_data_from_attachment_interactor.dart diff --git a/core/lib/domain/preview/supported_preview_file_types.dart b/core/lib/domain/preview/supported_preview_file_types.dart index 3718f612f..57dd3bb25 100644 --- a/core/lib/domain/preview/supported_preview_file_types.dart +++ b/core/lib/domain/preview/supported_preview_file_types.dart @@ -3,6 +3,7 @@ class SupportedPreviewFileTypes { 'image/bmp', 'image/jpeg', 'image/gif', + 'image/webp', 'image/png',]; static const textMimeTypes = [ @@ -10,6 +11,10 @@ class SupportedPreviewFileTypes { 'text/markdown', ]; + static const jsonMimeTypes = [ + 'application/json', + ]; + static const docMimeTypes = [ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.oasis.opendocument.text', diff --git a/core/lib/presentation/extensions/media_type_extension.dart b/core/lib/presentation/extensions/media_type_extension.dart index 8c57b9985..3331fb019 100644 --- a/core/lib/presentation/extensions/media_type_extension.dart +++ b/core/lib/presentation/extensions/media_type_extension.dart @@ -23,6 +23,8 @@ extension MediaTypeExtension on MediaType { bool isTextFile() => SupportedPreviewFileTypes.textMimeTypes.contains(mimeType); + bool isJsonFile() => SupportedPreviewFileTypes.jsonMimeTypes.contains(mimeType); + DocumentUti getDocumentUti() => DocumentUti(SupportedPreviewFileTypes.iOSSupportedTypes[mimeType]); String getIcon(ImagePaths imagePaths, {String? fileName}) { diff --git a/lib/features/email/domain/state/download_attachment_for_web_state.dart b/lib/features/email/domain/state/download_attachment_for_web_state.dart index a5209dd38..ec8409c6a 100644 --- a/lib/features/email/domain/state/download_attachment_for_web_state.dart +++ b/lib/features/email/domain/state/download_attachment_for_web_state.dart @@ -12,11 +12,12 @@ class StartDownloadAttachmentForWeb extends UIState { final DownloadTaskId taskId; final Attachment attachment; final CancelToken? cancelToken; + final bool previewerSupported; - StartDownloadAttachmentForWeb(this.taskId, this.attachment, [this.cancelToken]); + StartDownloadAttachmentForWeb(this.taskId, this.attachment, [this.cancelToken, this.previewerSupported = false]); @override - List get props => [taskId, attachment, cancelToken]; + List get props => [taskId, attachment, cancelToken, previewerSupported]; } class DownloadingAttachmentForWeb extends UIState { @@ -50,11 +51,12 @@ class DownloadAttachmentForWebSuccess extends UIState { final DownloadTaskId taskId; final Attachment attachment; final Uint8List bytes; + final bool previewerSupported; - DownloadAttachmentForWebSuccess(this.taskId, this.attachment, this.bytes); + DownloadAttachmentForWebSuccess(this.taskId, this.attachment, this.bytes, this.previewerSupported); @override - List get props => [taskId, attachment, bytes]; + List get props => [taskId, attachment, bytes, previewerSupported]; } class DownloadAttachmentForWebFailure extends FeatureFailure { diff --git a/lib/features/email/domain/state/get_image_data_from_attachment_state.dart b/lib/features/email/domain/state/get_image_data_from_attachment_state.dart deleted file mode 100644 index a78c7b14d..000000000 --- a/lib/features/email/domain/state/get_image_data_from_attachment_state.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:typed_data'; - -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:model/email/attachment.dart'; - -class GettingImageDataFromAttachment extends LoadingState { - GettingImageDataFromAttachment({required this.attachment}); - - final Attachment attachment; - - @override - List get props => [attachment]; -} - -class GetImageDataFromAttachmentSuccess extends UIState { - GetImageDataFromAttachmentSuccess({ - required this.attachment, - required this.data, - }); - - final Attachment attachment; - final Uint8List data; - - @override - List get props => [attachment, data]; -} - -class GetImageDataFromAttachmentFailure extends FeatureFailure { - GetImageDataFromAttachmentFailure({super.exception}); -} \ No newline at end of file diff --git a/lib/features/email/domain/state/get_text_data_from_attachment_state.dart b/lib/features/email/domain/state/get_text_data_from_attachment_state.dart deleted file mode 100644 index 5cb6081fe..000000000 --- a/lib/features/email/domain/state/get_text_data_from_attachment_state.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:typed_data'; - -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:model/email/attachment.dart'; - -class GettingTextDataFromAttachment extends LoadingState { - GettingTextDataFromAttachment({required this.attachment}); - - final Attachment attachment; - - @override - List get props => [attachment]; -} - -class GetTextDataFromAttachmentSuccess extends UIState { - GetTextDataFromAttachmentSuccess({ - required this.attachment, - required this.data, - }); - - final Attachment attachment; - final Uint8List data; - - @override - List get props => [attachment, data]; -} - -class GetTextDataFromAttachmentFailure extends FeatureFailure { - GetTextDataFromAttachmentFailure({super.exception}); -} \ No newline at end of file diff --git a/lib/features/email/domain/usecases/download_attachment_for_web_interactor.dart b/lib/features/email/domain/usecases/download_attachment_for_web_interactor.dart index 4a4d304b2..b15bc4580 100644 --- a/lib/features/email/domain/usecases/download_attachment_for_web_interactor.dart +++ b/lib/features/email/domain/usecases/download_attachment_for_web_interactor.dart @@ -35,11 +35,12 @@ class DownloadAttachmentForWebInteractor { AccountId accountId, String baseDownloadUrl, StreamController> onReceiveController, - {CancelToken? cancelToken} - ) async* { + {CancelToken? cancelToken, + bool previewerSupported = false, + }) async* { try { - yield Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken)); - onReceiveController.add(Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken))); + yield Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported)); + onReceiveController.add(Right(StartDownloadAttachmentForWeb(taskId, attachment, cancelToken, previewerSupported))); final currentAccount = await _accountRepository.getCurrentAccount(); AccountRequest? accountRequest; @@ -69,7 +70,8 @@ class DownloadAttachmentForWebInteractor { DownloadAttachmentForWebSuccess( taskId, attachment, - bytesDownloaded + bytesDownloaded, + previewerSupported, ) ); } catch (exception) { diff --git a/lib/features/email/domain/usecases/get_image_data_from_attachment_interactor.dart b/lib/features/email/domain/usecases/get_image_data_from_attachment_interactor.dart deleted file mode 100644 index af578794b..000000000 --- a/lib/features/email/domain/usecases/get_image_data_from_attachment_interactor.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'dart:async'; - -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:core/utils/app_logger.dart'; -import 'package:dartz/dartz.dart'; -import 'package:dio/dio.dart'; -import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package: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_image_data_from_attachment_state.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart'; - -class GetImageDataFromAttachmentInteractor { - const GetImageDataFromAttachmentInteractor(this._downloadAttachmentForWebInteractor); - - final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor; - - Stream> execute( - DownloadTaskId taskId, - Attachment attachment, - AccountId accountId, - String baseDownloadUrl, - {CancelToken? cancelToken,} - ) async* { - final onProgressStream = StreamController>(); - try { - yield Right(GettingImageDataFromAttachment(attachment: attachment)); - final downloadState = await _downloadAttachmentForWebInteractor.execute( - taskId, - attachment, - accountId, - baseDownloadUrl, - onProgressStream, - cancelToken: cancelToken, - ).last; - - yield downloadState.fold( - (failure) { - return Left(GetImageDataFromAttachmentFailure( - exception: failure is FeatureFailure ? failure.exception : null, - )); - }, - (success) { - if (success is! DownloadAttachmentForWebSuccess) { - return Left(GetImageDataFromAttachmentFailure()); - } - - return Right(GetImageDataFromAttachmentSuccess( - attachment: attachment, - data: success.bytes, - )); - }, - ); - } catch (e) { - logError('GetImageDataFromAttachmentInteractor::execute(): $e'); - yield Left(GetImageDataFromAttachmentFailure(exception: e)); - } - onProgressStream.close(); - } -} \ No newline at end of file diff --git a/lib/features/email/domain/usecases/get_text_data_from_attachment_interactor.dart b/lib/features/email/domain/usecases/get_text_data_from_attachment_interactor.dart deleted file mode 100644 index cc8dd4a82..000000000 --- a/lib/features/email/domain/usecases/get_text_data_from_attachment_interactor.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'dart:async'; - -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:core/utils/app_logger.dart'; -import 'package:dartz/dartz.dart'; -import 'package:dio/dio.dart'; -import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package: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_text_data_from_attachment_state.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart'; - -class GetTextDataFromAttachmentInteractor { - const GetTextDataFromAttachmentInteractor(this._downloadAttachmentForWebInteractor); - - final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor; - - Stream> execute( - DownloadTaskId taskId, - Attachment attachment, - AccountId accountId, - String baseDownloadUrl, - {CancelToken? cancelToken,} - ) async* { - final onProgressStream = StreamController>(); - try { - yield Right(GettingTextDataFromAttachment(attachment: attachment)); - final downloadState = await _downloadAttachmentForWebInteractor.execute( - taskId, - attachment, - accountId, - baseDownloadUrl, - onProgressStream, - cancelToken: cancelToken, - ).last; - - yield downloadState.fold( - (failure) { - return Left(GetTextDataFromAttachmentFailure( - exception: failure is FeatureFailure ? failure.exception : null, - )); - }, - (success) { - if (success is! DownloadAttachmentForWebSuccess) { - return Left(GetTextDataFromAttachmentFailure()); - } - - return Right(GetTextDataFromAttachmentSuccess( - attachment: attachment, - data: success.bytes, - )); - }, - ); - } catch (e) { - logError('GetTextDataFromAttachmentInteractor::execute(): $e'); - yield Left(GetTextDataFromAttachmentFailure(exception: e)); - } - onProgressStream.close(); - } -} \ No newline at end of file diff --git a/lib/features/email/presentation/bindings/email_bindings.dart b/lib/features/email/presentation/bindings/email_bindings.dart index bf231f23d..d8d56de82 100644 --- a/lib/features/email/presentation/bindings/email_bindings.dart +++ b/lib/features/email/presentation/bindings/email_bindings.dart @@ -22,9 +22,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment 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_image_data_from_attachment_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/get_text_data_from_attachment_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'; @@ -86,8 +84,6 @@ class EmailBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), - Get.find(), )); } @@ -186,12 +182,6 @@ class EmailBindings extends BaseBindings { Get.find(), Get.find(), Get.find())); - Get.lazyPut(() => GetImageDataFromAttachmentInteractor( - Get.find(), - )); - Get.lazyPut(() => GetTextDataFromAttachmentInteractor( - Get.find(), - )); } @override diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index ff4e0856d..398fb13a2 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -17,6 +17,7 @@ import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_svg/flutter_svg.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/capability/capability_identifier.dart'; @@ -64,8 +65,6 @@ import 'package:tmail_ui_user/features/email/domain/state/export_all_attachments 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_html_content_from_attachment_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/get_image_data_from_attachment_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/get_text_data_from_attachment_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_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/move_to_mailbox_state.dart'; @@ -80,8 +79,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/download_all_attachments_for_web_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/get_image_data_from_attachment_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/get_text_data_from_attachment_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/maybe_calendar_event_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart'; @@ -146,6 +143,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_utils.dart'; import 'package:tmail_ui_user/main/utils/app_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'; @@ -176,8 +174,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { final GetHtmlContentFromAttachmentInteractor _getHtmlContentFromAttachmentInteractor; final DownloadAllAttachmentsForWebInteractor _downloadAllAttachmentsForWebInteractor; final ExportAllAttachmentsInteractor _exportAllAttachmentsInteractor; - final GetImageDataFromAttachmentInteractor _getImageDataFromAttachmentInteractor; - final GetTextDataFromAttachmentInteractor _getTextDataFromAttachmentInteractor; CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor; SendReceiptToSenderInteractor? _sendReceiptToSenderInteractor; @@ -236,8 +232,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { this._getHtmlContentFromAttachmentInteractor, this._downloadAllAttachmentsForWebInteractor, this._exportAllAttachmentsInteractor, - this._getImageDataFromAttachmentInteractor, - this._getTextDataFromAttachmentInteractor, ); @override @@ -315,32 +309,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { )); } else if (success is GettingHtmlContentFromAttachment) { _updateAttachmentsViewState(success.attachment.blobId, Right(success)); - } else if (success is GettingImageDataFromAttachment) { - _updateAttachmentsViewState(success.attachment.blobId, Right(success)); - } else if (success is GetImageDataFromAttachmentSuccess) { - _updateAttachmentsViewState(success.attachment.blobId, Right(success)); - Get.dialog(TwakeImagePreviewer( - bytes: success.data, - topBarOptions: TopBarOptions( - title: success.attachment.generateFileName(), - onClose: popBack, - ), - )); - } else if (success is GettingTextDataFromAttachment) { - _updateAttachmentsViewState(success.attachment.blobId, Right(success)); - } else if (success is GetTextDataFromAttachmentSuccess) { - _updateAttachmentsViewState(success.attachment.blobId, Right(success)); - Get.dialog(TwakePlainTextPreviewer( - supportedCharset: SupportedCharset.utf8, - bytes: success.data, - previewerOptions: PreviewerOptions( - width: currentContext == null ? 200 : currentContext!.width * 0.8, - ), - topBarOptions: TopBarOptions( - title: success.attachment.generateFileName(), - onClose: popBack, - ), - )); } } @@ -483,7 +451,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { state.fold( (failure) => null, (success) { - if (success is StartDownloadAttachmentForWeb) { + if (success is StartDownloadAttachmentForWeb && !success.previewerSupported) { emailSupervisorController.mailboxDashBoardController.addDownloadTask( DownloadTaskState( taskId: success.taskId, @@ -492,7 +460,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { ), ); - if (currentOverlayContext != null && currentContext != null) { + if (currentOverlayContext != null && currentContext != null && !success.previewerSupported) { appToast.showToastMessage( currentOverlayContext!, AppLocalizations.of(currentContext!).your_download_has_started, @@ -1034,7 +1002,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { await FlutterFileDialog.saveFile(params: params); } - void downloadAttachmentForWeb(Attachment attachment) { + void downloadAttachmentForWeb(Attachment attachment, {bool previewerSupported = false}) { if (accountId != null && session != null) { final generateTaskId = DownloadTaskId(uuid.v4()); try { @@ -1049,6 +1017,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { baseDownloadUrl, _downloadProgressStateController, cancelToken: cancelToken, + previewerSupported: previewerSupported, )); } catch (e) { logError('SingleEmailController::downloadAttachmentForWeb(): $e'); @@ -1130,9 +1099,57 @@ class SingleEmailController extends BaseController with AppLoaderMixin { mailboxDashBoardController.deleteDownloadTask(success.taskId); - _downloadManager.createAnchorElementDownloadFileWeb( + if (!success.previewerSupported) { + _downloadManager.createAnchorElementDownloadFileWeb( success.bytes, success.attachment.generateFileName()); + return; + } + + if (success.attachment.isImage) { + _updateAttachmentsViewState(success.attachment.blobId, Right(success)); + Navigator.of(currentContext!).push(GetDialogRoute( + pageBuilder: (context, _, __) => PointerInterceptor(child: TwakeImagePreviewer( + bytes: success.bytes, + zoomable: true, + previewerOptions: const PreviewerOptions( + previewerState: PreviewerState.success, + ), + topBarOptions: TopBarOptions( + title: success.attachment.generateFileName(), + onClose: () => Navigator.maybePop(context), + onDownload: currentContext == null + ? null + : () => handleDownloadAttachmentAction( + currentContext!, + success.attachment), + ), + )), + barrierDismissible: false, + )); + } else if (success.attachment.isText || success.attachment.isJson) { + _updateAttachmentsViewState(success.attachment.blobId, Right(success)); + Navigator.of(currentContext!).push(GetDialogRoute( + pageBuilder: (context, _, __) => PointerInterceptor(child: TwakePlainTextPreviewer( + supportedCharset: SupportedCharset.utf8, + bytes: success.bytes, + previewerOptions: PreviewerOptions( + previewerState: PreviewerState.success, + width: currentContext == null ? 200 : currentContext!.width * 0.8, + ), + topBarOptions: TopBarOptions( + title: success.attachment.generateFileName(), + onClose: () => Navigator.maybePop(context), + onDownload: currentContext == null + ? null + : () => handleDownloadAttachmentAction( + currentContext!, + success.attachment), + ), + )), + barrierDismissible: false, + )); + } } void _downloadPDFFile(Uint8List bytes, String fileName) { @@ -2193,9 +2210,13 @@ class SingleEmailController extends BaseController with AppLoaderMixin { ); } - void handleDownloadAttachmentAction(BuildContext context, Attachment attachment) { + void handleDownloadAttachmentAction( + BuildContext context, + Attachment attachment, + {bool previewerSupported = false} + ) { if (PlatformInfo.isWeb) { - downloadAttachmentForWeb(attachment); + downloadAttachmentForWeb(attachment, previewerSupported: previewerSupported); } else if (PlatformInfo.isMobile) { exportAttachment(context, attachment); } else { @@ -2241,37 +2262,19 @@ class SingleEmailController extends BaseController with AppLoaderMixin { customTextTransformers: [const StandardizeHtmlSanitizingTransformers()], ), )); - } else if (attachment.isImage) { - final attachmentEvaluation = evaluateAttachment(attachment); - if (!attachmentEvaluation.canDownloadAttachment) { - consumeState(Stream.value(Left(GetImageDataFromAttachmentFailure()))); - return; - } - - consumeState(_getImageDataFromAttachmentInteractor.execute( - DownloadTaskId(uuid.v4()), - attachment, - attachmentEvaluation.accountId!, - attachmentEvaluation.downloadUrl!, - )); - } else if (attachment.isText) { - final attachmentEvaluation = evaluateAttachment(attachment); - if (!attachmentEvaluation.canDownloadAttachment) { - consumeState(Stream.value(Left(GetTextDataFromAttachmentFailure()))); - return; - } - - consumeState(_getTextDataFromAttachmentInteractor.execute( - DownloadTaskId(uuid.v4()), - attachment, - attachmentEvaluation.accountId!, - attachmentEvaluation.downloadUrl!, - )); } else { - handleDownloadAttachmentAction(context, attachment); + handleDownloadAttachmentAction( + context, + attachment, + previewerSupported: attachmentPreviewSupported(attachment), + ); } } + bool attachmentPreviewSupported(Attachment attachment) { + return attachment.isImage || attachment.isText || attachment.isJson; + } + ({ bool canDownloadAttachment, AccountId? accountId, diff --git a/lib/features/email/presentation/extensions/attachment_extension.dart b/lib/features/email/presentation/extensions/attachment_extension.dart index fcbc1821f..075bccc97 100644 --- a/lib/features/email/presentation/extensions/attachment_extension.dart +++ b/lib/features/email/presentation/extensions/attachment_extension.dart @@ -46,4 +46,7 @@ extension AttachmentExtension on Attachment { bool get isText => (type?.isTextFile() ?? false) || name?.endsWith('.txt') == true || name?.endsWith('.md') == true; + + bool get isJson => (type?.isJsonFile() ?? false) + || name?.endsWith('.json') == true; } \ No newline at end of file diff --git a/lib/features/email/presentation/utils/email_utils.dart b/lib/features/email/presentation/utils/email_utils.dart index ad79dbb80..c1209b97e 100644 --- a/lib/features/email/presentation/utils/email_utils.dart +++ b/lib/features/email/presentation/utils/email_utils.dart @@ -18,8 +18,6 @@ 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/email/domain/state/get_image_data_from_attachment_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/get_text_data_from_attachment_state.dart'; import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/attachment/attachment_item_widget_style.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/email_attachments_styles.dart'; @@ -78,8 +76,6 @@ class EmailUtils { (success) { return success is DownloadAttachmentForWebSuccess || success is GetHtmlContentFromAttachmentSuccess - || success is GetImageDataFromAttachmentSuccess - || success is GetTextDataFromAttachmentSuccess || success is IdleDownloadAttachmentForWeb; }) ?? false; } diff --git a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart index bc8579c38..7d1fd6357 100644 --- a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart +++ b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart @@ -154,8 +154,8 @@ class EmailViewAppBarWidget extends StatelessWidget { return PopScope( canPop: false, onPopInvokedWithResult: (_, __) { + if (!PlatformInfo.isAndroid) return; onBackAction(); - return; }, child: child, ); diff --git a/test/features/email/presentation/controller/single_email_controller_test.dart b/test/features/email/presentation/controller/single_email_controller_test.dart index d0bc99d1d..a6e38d6b7 100644 --- a/test/features/email/presentation/controller/single_email_controller_test.dart +++ b/test/features/email/presentation/controller/single_email_controller_test.dart @@ -31,8 +31,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_acce 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/export_all_attachments_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_image_data_from_attachment_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/get_text_data_from_attachment_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/maybe_calendar_event_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/download_attachment_for_web_interactor.dart'; @@ -118,8 +116,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -161,8 +157,6 @@ void main() { final downloadAllAttachmentsForWebInteractor = MockDownloadAllAttachmentsForWebInteractor(); final exportAllAttachmentsInteractor = MockExportAllAttachmentsInteractor(); - final getImageDataFromAttachmentInteractor = MockGetImageDataFromAttachmentInteractor(); - final getTextDataFromAttachmentInteractor = MockGetTextDataFromAttachmentInteractor(); late SingleEmailController singleEmailController; @@ -223,8 +217,6 @@ void main() { getHtmlContentFromAttachmentInteractor, downloadAllAttachmentsForWebInteractor, exportAllAttachmentsInteractor, - getImageDataFromAttachmentInteractor, - getTextDataFromAttachmentInteractor, ); });