From 6f10eacbb3d74f0273aaa33b70bd2c084dc82ed8 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 8 Apr 2024 13:35:54 +0700 Subject: [PATCH] TF-2785 Fix print feature empty when clicked too early --- ...emove_lazy_loading_image_transformers.dart | 19 +++++ .../transform_configuration.dart | 2 + .../email/domain/model/email_print.dart | 30 ++++++++ .../usecases/print_email_interactor.dart | 1 - .../presentation/action/email_ui_action.dart | 20 ++++- .../controller/single_email_controller.dart | 76 ++++++++++++++----- .../mailbox_dashboard_controller.dart | 2 + 7 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 core/lib/presentation/utils/html_transformer/dom/remove_lazy_loading_image_transformers.dart diff --git a/core/lib/presentation/utils/html_transformer/dom/remove_lazy_loading_image_transformers.dart b/core/lib/presentation/utils/html_transformer/dom/remove_lazy_loading_image_transformers.dart new file mode 100644 index 000000000..857d04192 --- /dev/null +++ b/core/lib/presentation/utils/html_transformer/dom/remove_lazy_loading_image_transformers.dart @@ -0,0 +1,19 @@ +import 'package:core/data/network/dio_client.dart'; +import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart'; +import 'package:html/dom.dart'; + +class RemoveLazyLoadingImageTransformer extends DomTransformer { + const RemoveLazyLoadingImageTransformer(); + + @override + Future process({ + required Document document, + required DioClient dioClient, + Map? mapUrlDownloadCID, + }) async { + final elements = document.querySelectorAll('img[loading]'); + await Future.wait(elements.map((element) async { + element.attributes.remove('loading'); + })); + } +} diff --git a/core/lib/presentation/utils/html_transformer/transform_configuration.dart b/core/lib/presentation/utils/html_transformer/transform_configuration.dart index 9e1b03cd0..fecf928d1 100644 --- a/core/lib/presentation/utils/html_transformer/transform_configuration.dart +++ b/core/lib/presentation/utils/html_transformer/transform_configuration.dart @@ -9,6 +9,7 @@ import 'package:core/presentation/utils/html_transformer/dom/blockquoted_transfo import 'package:core/presentation/utils/html_transformer/dom/image_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_collapsed_signature_button_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_lazy_loading_for_background_image_transformers.dart'; +import 'package:core/presentation/utils/html_transformer/dom/remove_lazy_loading_image_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_max_width_in_image_style_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_style_tag_outside_transformers.dart'; import 'package:core/presentation/utils/html_transformer/dom/remove_tooltip_link_transformers.dart'; @@ -67,6 +68,7 @@ class TransformConfiguration { if (PlatformInfo.isWeb) const RemoveTooltipLinkTransformer(), const RemoveLazyLoadingForBackgroundImageTransformer(), + const RemoveLazyLoadingImageTransformer(), const RemoveCollapsedSignatureButtonTransformer(), const RemoveStyleTagOutsideTransformer(), const RemoveMaxWidthInImageStyleTransformer(), diff --git a/lib/features/email/domain/model/email_print.dart b/lib/features/email/domain/model/email_print.dart index 3c1f33063..d37dec519 100644 --- a/lib/features/email/domain/model/email_print.dart +++ b/lib/features/email/domain/model/email_print.dart @@ -1,6 +1,12 @@ import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/email/attachment.dart'; +import 'package:model/extensions/list_email_address_extension.dart'; +import 'package:model/extensions/presentation_email_extension.dart'; +import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class EmailPrint with EquatableMixin { final String appName; @@ -39,6 +45,30 @@ class EmailPrint with EquatableMixin { this.replyToAddress, }); + factory EmailPrint.generate({ + required PrintEmailAction printEmailAction, + required EmailLoaded emailLoaded + }) { + return EmailPrint( + appName: AppLocalizations.of(printEmailAction.context).app_name, + userName: printEmailAction.userEmail, + emailInformation: printEmailAction.email.toEmail(), + attachments: emailLoaded.attachments, + emailContent: emailLoaded.htmlContent, + locale: Localizations.localeOf(printEmailAction.context).toLanguageTag(), + fromPrefix: AppLocalizations.of(printEmailAction.context).from_email_address_prefix, + toPrefix: AppLocalizations.of(printEmailAction.context).to_email_address_prefix, + ccPrefix: AppLocalizations.of(printEmailAction.context).cc_email_address_prefix, + bccPrefix: AppLocalizations.of(printEmailAction.context).bcc_email_address_prefix, + replyToPrefix: AppLocalizations.of(printEmailAction.context).replyToEmailAddressPrefix, + titleAttachment: AppLocalizations.of(printEmailAction.context).attachments.toLowerCase(), + toAddress: printEmailAction.email.to?.listEmailAddressToString(isFullEmailAddress: true), + ccAddress: printEmailAction.email.cc?.listEmailAddressToString(isFullEmailAddress: true), + bccAddress: printEmailAction.email.bcc?.listEmailAddressToString(isFullEmailAddress: true), + replyToAddress: printEmailAction.email.replyTo?.listEmailAddressToString(isFullEmailAddress: true), + ); + } + @override List get props => [ appName, diff --git a/lib/features/email/domain/usecases/print_email_interactor.dart b/lib/features/email/domain/usecases/print_email_interactor.dart index 7fadbfbca..1014b3b5f 100644 --- a/lib/features/email/domain/usecases/print_email_interactor.dart +++ b/lib/features/email/domain/usecases/print_email_interactor.dart @@ -14,7 +14,6 @@ class PrintEmailInteractor { Stream> execute(EmailPrint emailPrint) async* { try { - yield Right(PrintEmailLoading()); final htmlContentTransformed = await _transformHtmlEmailContent(emailPrint.emailContent); final newEmailPrint = emailPrint.fromEmailContent(htmlContentTransformed); await emailRepository.printEmail(newEmailPrint); diff --git a/lib/features/email/presentation/action/email_ui_action.dart b/lib/features/email/presentation/action/email_ui_action.dart index 3a2ae4ae5..e7a544590 100644 --- a/lib/features/email/presentation/action/email_ui_action.dart +++ b/lib/features/email/presentation/action/email_ui_action.dart @@ -1,5 +1,7 @@ +import 'package:flutter/cupertino.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; +import 'package:model/email/presentation_email.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.dart'; class EmailUIAction extends UIAction { @@ -22,4 +24,20 @@ class RefreshChangeEmailAction extends EmailUIAction { class CloseEmailDetailedViewToRedirectToTheInboxAction extends EmailUIAction {} -class CloseEmailDetailedViewAction extends EmailUIAction {} \ No newline at end of file +class CloseEmailDetailedViewAction extends EmailUIAction {} + +class PrintEmailAction extends EmailUIAction { + + final BuildContext context; + final String userEmail; + final PresentationEmail email; + + PrintEmailAction({ + required this.context, + required this.userEmail, + required this.email + }); + + @override + List get props => [context, userEmail, email]; +} \ No newline at end of file diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index 13ab26c23..be310b4fd 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -131,6 +131,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { EmailId? _currentEmailId; Identity? _identitySelected; EmailLoaded? _currentEmailLoaded; + PrintEmailAction? _printEmailAction; final StreamController> _downloadProgressStateController = StreamController>.broadcast(); @@ -209,6 +210,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { _handleParseCalendarEventSuccess(success); } else if (success is PrintEmailLoading) { _showMessageWhenStartingEmailPrinting(); + } else if (success is PrintEmailSuccess) { + _handlePrintEmailSuccess(success); } } @@ -230,7 +233,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } else if (failure is GetEmailContentFailure) { emailLoadedViewState.value = Left(failure); } else if (failure is PrintEmailFailure) { - _showMessageWhenEmailPrintingFailed(); + _showMessageWhenEmailPrintingFailed(failure); } } @@ -527,6 +530,13 @@ class SingleEmailController extends BaseController with AppLoaderMixin { emailContents.value = success.htmlEmailContent; } + if (_printEmailAction != null) { + _handlePrintEmailWhenEmailContentLoaded( + action: _printEmailAction!, + emailLoaded: _currentEmailLoaded! + ); + } + if (PlatformInfo.isMobile) { final detailedEmail = DetailedEmail( emailId: currentEmail!.id!, @@ -586,6 +596,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { calendarEvent.value = null; eventActions.clear(); emailUnsubscribe.value = null; + _printEmailAction = null; if (isEmailClosing) { emailLoadedViewState.value = Right(UIState.idle); viewState.value = Right(UIState.idle); @@ -1597,25 +1608,27 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } void _printEmail(BuildContext context, PresentationEmail email) { - final emailPrint = EmailPrint( - appName: AppLocalizations.of(context).app_name, - userName: mailboxDashBoardController.userProfile.value?.email ?? '', - emailInformation: email.toEmail(), - attachments: _currentEmailLoaded?.attachments, - emailContent: _currentEmailLoaded?.htmlContent ?? '', - locale: Localizations.localeOf(context).toLanguageTag(), - fromPrefix: AppLocalizations.of(context).from_email_address_prefix, - toPrefix: AppLocalizations.of(context).to_email_address_prefix, - ccPrefix: AppLocalizations.of(context).cc_email_address_prefix, - bccPrefix: AppLocalizations.of(context).bcc_email_address_prefix, - replyToPrefix: AppLocalizations.of(context).replyToEmailAddressPrefix, - titleAttachment: AppLocalizations.of(context).attachments.toLowerCase(), - toAddress: email.to?.listEmailAddressToString(isFullEmailAddress: true), - ccAddress: email.cc?.listEmailAddressToString(isFullEmailAddress: true), - bccAddress: email.bcc?.listEmailAddressToString(isFullEmailAddress: true), - replyToAddress: email.replyTo?.listEmailAddressToString(isFullEmailAddress: true), + if (_printEmailAction != null) { + log('SingleEmailController::_printEmail: Print email started'); + return; + } + + _printEmailAction = PrintEmailAction( + context: context, + userEmail: mailboxDashBoardController.userEmail, + email: email + ); + consumeState(Stream.value(Right(PrintEmailLoading()))); + + if (_currentEmailLoaded == null) { + log('SingleEmailController::_printEmail: Email content loading'); + return; + } + + _handlePrintEmailWhenEmailContentLoaded( + action: _printEmailAction!, + emailLoaded: _currentEmailLoaded! ); - consumeState(_printEmailInteractor.execute(emailPrint)); } void _showMessageWhenStartingEmailPrinting() { @@ -1628,11 +1641,34 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } - void _showMessageWhenEmailPrintingFailed() { + void _handlePrintEmailSuccess(PrintEmailSuccess success) { + _printEmailAction = null; + } + + void _showMessageWhenEmailPrintingFailed(PrintEmailFailure failure) { + _printEmailAction = null; + if (currentOverlayContext != null && currentContext != null) { appToast.showToastErrorMessage( currentOverlayContext!, AppLocalizations.of(currentContext!).printingFailed); } } + + void _handlePrintEmailWhenEmailContentLoaded({ + required PrintEmailAction action, + required EmailLoaded emailLoaded + }) { + if (action.email.id != emailLoaded.emailCurrent?.id) { + log('SingleEmailController::_handlePrintEmailInQueue: Print email action NOT matched email id'); + _printEmailAction = null; + return; + } + + consumeState( + _printEmailInteractor.execute( + EmailPrint.generate(printEmailAction: action, emailLoaded: emailLoaded) + ) + ); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index 71e5fe08d..7b259b794 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -2485,6 +2485,8 @@ class MailboxDashBoardController extends ReloadableController { isRecoveringDeletedMessage.value = true; } + String get userEmail => userProfile.value?.email ?? ''; + @override void onClose() { _emailReceiveManager.closeEmailReceiveManagerStream();