diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 57af033bf..b54cf9304 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -1135,8 +1135,8 @@ class ComposerController extends BaseController { _emailContents = arguments.emailContents; emailContentsViewState.value = Right( GetEmailContentSuccess( - emailContents: _emailContents!, - emailContentsDisplayed: [], + emailContent: _emailContents!, + emailContentDisplayed: '', attachments: [], emailCurrent: arguments.presentationEmail?.toEmail() ) @@ -1166,7 +1166,7 @@ class ComposerController extends BaseController { success.attachments.listAttachmentsDisplayedOutSide); } emailContentsViewState.value = Right(success); - _emailContents = success.emailContentString; + _emailContents = success.emailContent; } void _getEmailContentSuccess(GetEmailContentSuccess success) { @@ -1176,7 +1176,7 @@ class ComposerController extends BaseController { success.attachments.listAttachmentsDisplayedOutSide); } emailContentsViewState.value = Right(success); - _emailContents = success.emailContents; + _emailContents = success.emailContent; } String getEmailAddressSender() { diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index c513cace3..2c09da9de 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -282,7 +282,7 @@ class ComposerView extends BaseComposerView { child: loadingWidget, ); } else if (success is GetEmailContentSuccess) { - var contentHtml = success.emailContents; + var contentHtml = success.emailContent; if (contentHtml.isEmpty == true) { contentHtml = HtmlExtension.editorStartTags; } diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index d7b49ff32..b77e8d002 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -400,7 +400,7 @@ class ComposerView extends BaseComposerView { child: loadingWidget, ); } else if (success is GetEmailContentSuccess) { - var contentHtml = success.emailContents; + var contentHtml = success.emailContent; if (contentHtml.isEmpty == true) { contentHtml = HtmlExtension.editorStartTags; } diff --git a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart index f46beb033..ac7859fb1 100644 --- a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart @@ -173,12 +173,6 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { return Future.sync(() async { final task = HiveTask( runnable: () async { - final detailedEmailExisted = await _openedEmailCacheManager.isOpenedEmailAlreadyStored(accountId, session.username, detailedEmail.emailId); - - if (detailedEmailExisted) { - return Future.value(); - } - final fileSaved = await _fileUtils.saveToFile( nameFile: detailedEmail.emailId.asString, content: detailedEmail.htmlEmailContent ?? '', diff --git a/lib/features/email/domain/exceptions/email_cache_exceptions.dart b/lib/features/email/domain/exceptions/email_cache_exceptions.dart index a167cfa3e..5e2a9e9bd 100644 --- a/lib/features/email/domain/exceptions/email_cache_exceptions.dart +++ b/lib/features/email/domain/exceptions/email_cache_exceptions.dart @@ -3,4 +3,6 @@ class NotFoundStoredOpenedEmailException implements Exception {} class NotFoundStoredNewEmailException implements Exception {} -class NotFoundStoredEmailException implements Exception {} \ No newline at end of file +class NotFoundStoredEmailException implements Exception {} + +class OpenedEmailAlreadyStoredException implements Exception {} \ No newline at end of file diff --git a/lib/features/email/domain/state/get_email_content_state.dart b/lib/features/email/domain/state/get_email_content_state.dart index b9a55519b..2314bd0ae 100644 --- a/lib/features/email/domain/state/get_email_content_state.dart +++ b/lib/features/email/domain/state/get_email_content_state.dart @@ -2,46 +2,45 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/email/attachment.dart'; -import 'package:model/email/email_content.dart'; class GetEmailContentLoading extends LoadingState {} class GetEmailContentSuccess extends UIState { - final String emailContents; - final List emailContentsDisplayed; + final String emailContent; + final String emailContentDisplayed; final List attachments; final Email? emailCurrent; GetEmailContentSuccess({ - required this.emailContents, - required this.emailContentsDisplayed, + required this.emailContent, + required this.emailContentDisplayed, required this.attachments, required this.emailCurrent }); @override List get props => [ - emailContents, - emailContentsDisplayed, + emailContent, + emailContentDisplayed, attachments, emailCurrent ]; } class GetEmailContentFromCacheSuccess extends UIState { - final String emailContentString; + final String emailContent; final List attachments; final Email? emailCurrent; GetEmailContentFromCacheSuccess({ - required this.emailContentString, + required this.emailContent, required this.attachments, this.emailCurrent }); @override List get props => [ - emailContentString, + emailContent, attachments, emailCurrent, ]; diff --git a/lib/features/email/domain/usecases/get_email_content_interactor.dart b/lib/features/email/domain/usecases/get_email_content_interactor.dart index 95c6747a8..7de49cdf7 100644 --- a/lib/features/email/domain/usecases/get_email_content_interactor.dart +++ b/lib/features/email/domain/usecases/get_email_content_interactor.dart @@ -67,15 +67,15 @@ class GetEmailContentInteractor { : newEmailContents; yield Right(GetEmailContentSuccess( - emailContents: newEmailContents.asHtmlString, - emailContentsDisplayed: newEmailContentsDisplayed, + emailContent: newEmailContents.asHtmlString, + emailContentDisplayed: newEmailContentsDisplayed.asHtmlString, attachments: email.allAttachments, emailCurrent: email )); } else { yield Right(GetEmailContentSuccess( - emailContents: '', - emailContentsDisplayed: [], + emailContent: '', + emailContentDisplayed: '', attachments: email.allAttachments, emailCurrent: email )); @@ -99,7 +99,7 @@ class GetEmailContentInteractor { try { final detailedEmail = await emailRepository.getStoredOpenedEmail(session, accountId, emailId); yield Right(GetEmailContentFromCacheSuccess( - emailContentString: detailedEmail.htmlEmailContent ?? "", + emailContent: detailedEmail.htmlEmailContent ?? "", attachments: detailedEmail.attachments ?? [], emailCurrent: Email( id: emailId, @@ -132,7 +132,7 @@ class GetEmailContentInteractor { try { final detailedEmail = await emailRepository.getStoredNewEmail(session, accountId, emailId); yield Right(GetEmailContentFromCacheSuccess( - emailContentString: detailedEmail.htmlEmailContent ?? "", + emailContent: detailedEmail.htmlEmailContent ?? "", attachments: detailedEmail.attachments ?? [], emailCurrent: Email( id: emailId, diff --git a/lib/features/email/domain/usecases/store_opened_email_interactor.dart b/lib/features/email/domain/usecases/store_opened_email_interactor.dart index 9bd71da47..568f5f369 100644 --- a/lib/features/email/domain/usecases/store_opened_email_interactor.dart +++ b/lib/features/email/domain/usecases/store_opened_email_interactor.dart @@ -1,8 +1,10 @@ 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:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:tmail_ui_user/features/email/domain/exceptions/email_cache_exceptions.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/email/domain/state/store_opened_email_state.dart'; @@ -19,10 +21,27 @@ class StoreOpenedEmailInteractor { ) async* { try { yield Right(StoreOpenedEmailLoading()); - await _emailRepository.storeOpenedEmail(session, accountId, detailedEmail); - yield Right(StoreOpenedEmailSuccess()); + final isOpenedEmailExist = await _isOpenedEmailAlreadyStored(session, accountId, detailedEmail); + log('StoreOpenedEmailInteractor::execute():isOpenedEmailExist: $isOpenedEmailExist'); + if (!isOpenedEmailExist) { + await _emailRepository.storeOpenedEmail(session, accountId, detailedEmail); + yield Right(StoreOpenedEmailSuccess()); + } else { + yield Left(StoreOpenedEmailFailure(OpenedEmailAlreadyStoredException())); + } } catch (e) { yield Left(StoreOpenedEmailFailure(e)); } } + + Future _isOpenedEmailAlreadyStored(Session session, AccountId accountId, DetailedEmail detailedEmail) async { + try { + final storedOpenEmail = await _emailRepository.getStoredOpenedEmail(session, accountId, detailedEmail.emailId); + log('StoreOpenedEmailInteractor::isOpenedEmailAlreadyStored():storedOpenEmail: $storedOpenEmail'); + return true; + } catch (err) { + logError('StoreOpenedEmailInteractor::isOpenedEmailAlreadyStored():EXCEPTION: $err'); + return false; + } + } } \ 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 3c0c7abd1..fbbfd2a50 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -151,7 +151,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { if (success is GetEmailContentSuccess) { _getEmailContentSuccess(success); } else if (success is GetEmailContentFromCacheSuccess) { - _getEmailContentOffLineSuccess(success); + _getEmailContentOfflineSuccess(success); } else if (success is MarkAsEmailReadSuccess) { _markAsEmailReadSuccess(success); } else if (success is ExportAttachmentSuccess) { @@ -350,8 +350,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { await Future.delayed(const Duration(milliseconds: 300)); consumeState(Stream.value(Right( GetEmailContentSuccess( - emailContents: emailLoaded.emailContents, - emailContentsDisplayed: emailLoaded.emailContentsDisplayed, + emailContent: emailLoaded.emailContent, + emailContentDisplayed: emailLoaded.emailContentDisplayed, attachments: emailLoaded.attachments, emailCurrent: emailLoaded.emailCurrent ) @@ -361,28 +361,47 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } - void _getEmailContentOffLineSuccess(GetEmailContentFromCacheSuccess success) { - emailContents.value = success.emailContentString; - attachments.value = success.attachments; - initialEmailContents = success.emailContentString; - } - - void _getEmailContentSuccess(GetEmailContentSuccess success) { - if(emailSupervisorController.presentationEmailsLoaded.length > ThreadConstants.defaultLimit.value.toInt()) { + void _getEmailContentOfflineSuccess(GetEmailContentFromCacheSuccess success) { + if (emailSupervisorController.presentationEmailsLoaded.length > ThreadConstants.defaultLimit.value.toInt()) { emailSupervisorController.popFirstEmailQueue(); } emailSupervisorController.popEmailQueue(success.emailCurrent?.id); emailSupervisorController.pushEmailQueue(EmailLoaded( - success.emailContents, - success.emailContentsDisplayed.toList(), + success.emailContent, + success.emailContent, success.attachments.toList(), success.emailCurrent, )); if (success.emailCurrent?.id == currentEmail?.id) { - emailContents.value = success.emailContentsDisplayed.asHtmlString; - initialEmailContents = success.emailContents; + emailContents.value = success.emailContent; + initialEmailContents = success.emailContent; + attachments.value = success.attachments; + + final isShowMessageReadReceipt = success.emailCurrent?.hasReadReceipt(mailboxDashBoardController.mapMailboxById) == true; + if (isShowMessageReadReceipt) { + _handleReadReceipt(); + } + } + } + + void _getEmailContentSuccess(GetEmailContentSuccess success) { + if (emailSupervisorController.presentationEmailsLoaded.length > ThreadConstants.defaultLimit.value.toInt()) { + emailSupervisorController.popFirstEmailQueue(); + } + emailSupervisorController.popEmailQueue(success.emailCurrent?.id); + + emailSupervisorController.pushEmailQueue(EmailLoaded( + success.emailContent, + success.emailContentDisplayed, + success.attachments.toList(), + success.emailCurrent, + )); + + if (success.emailCurrent?.id == currentEmail?.id) { + emailContents.value = success.emailContentDisplayed; + initialEmailContents = success.emailContent; attachments.value = success.attachments; if (PlatformInfo.isMobile) { diff --git a/lib/features/email/presentation/model/email_loaded.dart b/lib/features/email/presentation/model/email_loaded.dart index 9dbdd7660..6fd774717 100644 --- a/lib/features/email/presentation/model/email_loaded.dart +++ b/lib/features/email/presentation/model/email_loaded.dart @@ -1,24 +1,24 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; -import 'package:model/model.dart'; +import 'package:model/email/attachment.dart'; class EmailLoaded with EquatableMixin { - final String emailContents; - final List emailContentsDisplayed; + final String emailContent; + final String emailContentDisplayed; final List attachments; final Email? emailCurrent; EmailLoaded( - this.emailContents, - this.emailContentsDisplayed, + this.emailContent, + this.emailContentDisplayed, this.attachments, this.emailCurrent, ); @override List get props => [ - emailContents, - emailContentsDisplayed, + emailContent, + emailContentDisplayed, attachments, emailCurrent ]; diff --git a/lib/features/offline_mode/manager/opened_email_cache_manager.dart b/lib/features/offline_mode/manager/opened_email_cache_manager.dart index 3b0cca63d..f24cf7eef 100644 --- a/lib/features/offline_mode/manager/opened_email_cache_manager.dart +++ b/lib/features/offline_mode/manager/opened_email_cache_manager.dart @@ -69,23 +69,6 @@ class OpenedEmailCacheManager { return detailedEmailCache; } - Future isOpenedEmailAlreadyStored( - AccountId accountId, - UserName userName, - EmailId emailId - ) async { - final listResult = await Future.wait([ - getStoredOpenedEmail(accountId, userName, emailId), - _fileUtils.isFileExisted( - nameFile: emailId.asString, - folderPath: CachingConstants.openedEmailContentFolderName) - ], eagerError: true); - - final emailContentPathExists = listResult.last as bool; - - return emailContentPathExists; - } - Future getStoredOpenedEmail( AccountId accountId, UserName userName,