diff --git a/core/lib/utils/file_utils.dart b/core/lib/utils/file_utils.dart index 90674bde6..32f5d3db0 100644 --- a/core/lib/utils/file_utils.dart +++ b/core/lib/utils/file_utils.dart @@ -55,6 +55,16 @@ class FileUtils { return await file.writeAsString(content, mode: FileMode.append); } + Future deleteFile(String filePath) async { + final file = File(filePath); + if (await file.exists()) { + await file.delete(); + log("FileUtils()::deleteFile: $file"); + } else { + log("FileUtils()::deleteFile: File does not exist"); + } + } + Future getContentFromFile({ required String nameFile, String? folderPath, diff --git a/lib/features/caching/utils/caching_constants.dart b/lib/features/caching/utils/caching_constants.dart index c717cddbd..2dcbe0bf5 100644 --- a/lib/features/caching/utils/caching_constants.dart +++ b/lib/features/caching/utils/caching_constants.dart @@ -20,7 +20,8 @@ class CachingConstants { static const String fcmCacheBoxName = 'fcm_cache_box'; static const String detailedEmailCacheBoxName = 'detailed_email_cache_box'; - static const String emailContentFolderName = 'email_content'; + static const String newEmailContentFolderName = 'new_email'; + static const String openedEmailContentFolderNamee = 'opened_email'; static const String openedEmailCacheBoxName = 'opened_email_cache_box'; static const int maxNumberNewEmailsForOffline = 10; diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 7654cd28c..0d73a8ce5 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -140,7 +140,7 @@ class ComposerController extends BaseController { List initialAttachments = []; String? _textEditorWeb; String? _initTextEditor; - List? _emailContents; + String? _emailContents; double? maxWithEditor; late Worker uploadInlineImageWorker; @@ -281,6 +281,8 @@ class ComposerController extends BaseController { _pickFileSuccess(success); } else if (success is GetEmailContentSuccess) { _getEmailContentSuccess(success); + } else if (success is GetEmailContentFromCacheSuccess) { + _getEmailContentOffLineSuccess(success); } else if (success is GetAllIdentitiesSuccess) { _handleGetAllIdentitiesSuccess(success); } else if (success is DownloadImageAsBase64Success) { @@ -595,7 +597,7 @@ class ComposerController extends BaseController { log('ComposerController::getEmailContentQuotedAsHtml(): headerEmailQuoted: $headerEmailQuoted'); final headerEmailQuotedAsHtml = headerEmailQuoted != null ? headerEmailQuoted.addBlockTag('cite') : ''; - final trustAsHtml = arguments.emailContents?.asHtmlString ?? ''; + final trustAsHtml = arguments.emailContents ?? ''; final emailQuotedHtml = '${HtmlExtension.editorStartTags}$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}'; return emailQuotedHtml; @@ -1108,8 +1110,7 @@ class ComposerController extends BaseController { } if(arguments.emailContents != null && arguments.emailContents!.isNotEmpty) { - _emailContents = arguments.emailContents; - emailContentsViewState.value = Right(GetEmailContentSuccess(_emailContents!, [], [], null)); + emailContentsViewState.value = Right(GetEmailContentFromCacheSuccess(arguments.emailContents!, [])); } else { final session = mailboxDashBoardController.sessionCurrent; final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: _dynamicUrlInterceptors.jmapUrl); @@ -1128,6 +1129,16 @@ class ComposerController extends BaseController { } } + void _getEmailContentOffLineSuccess(GetEmailContentFromCacheSuccess success) { + if (success.attachments.isNotEmpty) { + initialAttachments = success.attachments; + uploadController.initializeUploadAttachments( + success.attachments.listAttachmentsDisplayedOutSide); + } + emailContentsViewState.value = Right(success); + _emailContents = success.emailContentString; + } + void _getEmailContentSuccess(GetEmailContentSuccess success) { if (success.attachments.isNotEmpty) { initialAttachments = success.attachments; @@ -1135,10 +1146,10 @@ class ComposerController extends BaseController { success.attachments.listAttachmentsDisplayedOutSide); } emailContentsViewState.value = Right(success); - _emailContents = success.emailContents; + _emailContents = success.emailContents.asHtmlString; } - String? getEmailContentDraftsAsHtml() => _emailContents?.asHtmlString; + String? getEmailContentDraftsAsHtml() => _emailContents; String getEmailAddressSender() { final arguments = composerArguments.value; 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 6c0ec2132..c94a05b3d 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 @@ -124,7 +124,7 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { final fileSaved = await _fileUtils.saveToFile( nameFile: detailedEmail.emailId.asString, content: detailedEmail.htmlEmailContent ?? '', - folderPath: detailedEmail.folderPath + folderPath: detailedEmail.newEmailFolderPath ); log('EmailHiveCacheDataSourceImpl::storeDetailedEmailToCache():fileSavedPath: ${fileSaved.path}'); final detailedEmailSaved = detailedEmail.fromEmailContentPath(fileSaved.path); @@ -163,7 +163,7 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { final task = HiveTask( runnable: () async { - final detailedEmailExisted = await _openedEmailCacheManager.isOpenedDetailEmailCached(accountId, session.username, detailedEmail); + final detailedEmailExisted = await _openedEmailCacheManager.isOpenedDetailEmailCached(accountId, session.username, detailedEmail.emailId); log('EmailHiveCacheDataSourceImpl::storeOpenedEmail():detailedEmailExisted: $detailedEmailExisted'); if (detailedEmailExisted) { @@ -173,7 +173,7 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { final fileSaved = await _fileUtils.saveToFile( nameFile: detailedEmail.emailId.asString, content: detailedEmail.htmlEmailContent ?? '', - folderPath: detailedEmail.folderPath + folderPath: detailedEmail.openedEmailFolderPath ); log('EmailHiveCacheDataSourceImpl::storeOpenedEmail():fileSavedPath: ${fileSaved.path}'); @@ -196,7 +196,7 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { final emailContent = await _fileUtils.getContentFromFile( nameFile: emailId.asString, - folderPath: CachingConstants.emailContentFolderName + folderPath: CachingConstants.openedEmailContentFolderNamee ); return detailedEmailHiveCache?.toDetailedEmailWithContent(emailContent); diff --git a/lib/features/email/data/repository/email_repository_impl.dart b/lib/features/email/data/repository/email_repository_impl.dart index 5ddc6c0f2..f8f15ce93 100644 --- a/lib/features/email/data/repository/email_repository_impl.dart +++ b/lib/features/email/data/repository/email_repository_impl.dart @@ -205,7 +205,7 @@ class EmailRepositoryImpl extends EmailRepository { } @override - Future getOpenedEmail(Session session, AccountId accountId, EmailId emailId) { - throw UnimplementedError(); + Future getOpenedEmail(Session session, AccountId accountId, EmailId emailId) { + return emailDataSource[DataSourceType.hiveCache]!.getOpenedEmail(session, accountId, emailId); } } \ No newline at end of file diff --git a/lib/features/email/domain/extensions/attachment_hive_cache_extension.dart b/lib/features/email/domain/extensions/attachment_hive_cache_extension.dart index 8e684b5b7..7d52a1c87 100644 --- a/lib/features/email/domain/extensions/attachment_hive_cache_extension.dart +++ b/lib/features/email/domain/extensions/attachment_hive_cache_extension.dart @@ -8,13 +8,13 @@ import 'package:tmail_ui_user/features/offline_mode/model/attachment_hive_cache. extension AttachmentExtension on AttachmentHiveCache { Attachment toAttachment() { return Attachment( - partId: PartId(partId!), - blobId: Id(blobId!), - size: UnsignedInt(size!), - name: name, - type: MediaType.parse(type!), - cid: cid, - disposition: disposition?.toContentDisposition(), + partId: partId != null ? PartId(partId!) : null, + blobId: blobId != null ? Id(blobId!) : null, + size: size != null ? UnsignedInt(size!) : null, + name: name, + type: type != null ? MediaType.parse(type!) : null, + cid: cid, + disposition: disposition?.toContentDisposition(), ); } } \ No newline at end of file diff --git a/lib/features/email/domain/extensions/detailed_email_extension.dart b/lib/features/email/domain/extensions/detailed_email_extension.dart index 0af1d50ec..207fd5e5c 100644 --- a/lib/features/email/domain/extensions/detailed_email_extension.dart +++ b/lib/features/email/domain/extensions/detailed_email_extension.dart @@ -17,7 +17,9 @@ extension DetailedEmailExtension on DetailedEmail { ); } - String get folderPath => CachingConstants.emailContentFolderName; + String get newEmailFolderPath => CachingConstants.newEmailContentFolderName; + + String get openedEmailFolderPath => CachingConstants.openedEmailContentFolderNamee; DetailedEmail fromEmailContentPath(String path) { return DetailedEmail( diff --git a/lib/features/email/domain/repository/email_repository.dart b/lib/features/email/domain/repository/email_repository.dart index 45e51d5f3..dd575c799 100644 --- a/lib/features/email/domain/repository/email_repository.dart +++ b/lib/features/email/domain/repository/email_repository.dart @@ -96,5 +96,5 @@ abstract class EmailRepository { Future storeOpenedEmail(Session session, AccountId accountId, DetailedEmail detailedEmail); - Future getOpenedEmail(Session session, AccountId accountId, EmailId emailId); + Future getOpenedEmail(Session session, AccountId accountId, EmailId emailId); } \ 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 4420f311d..20b0fb41c 100644 --- a/lib/features/email/domain/state/get_email_content_state.dart +++ b/lib/features/email/domain/state/get_email_content_state.dart @@ -26,6 +26,22 @@ class GetEmailContentSuccess extends UIState { ]; } +class GetEmailContentFromCacheSuccess extends UIState { + final String emailContentString; + final List attachments; + + GetEmailContentFromCacheSuccess( + this.emailContentString, + this.attachments, + ); + + @override + List get props => [ + emailContentString, + attachments, + ]; +} + class GetEmailContentFailure extends FeatureFailure { final dynamic exception; diff --git a/lib/features/email/domain/state/get_opened_email_from_cache_state.dart b/lib/features/email/domain/state/get_opened_email_from_cache_state.dart deleted file mode 100644 index 1cf21af58..000000000 --- a/lib/features/email/domain/state/get_opened_email_from_cache_state.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; - -class GetOpenedEmailLoading extends UIState {} - -class GetOpenedEmailSuccess extends UIState { - final DetailedEmail detailedEmail; - - GetOpenedEmailSuccess(this.detailedEmail); - - @override - List get props => [detailedEmail]; -} - -class GetOpenedEmailFailure extends FeatureFailure { - - GetOpenedEmailFailure(dynamic exception) : super(exception: exception); - - @override - List get props => [exception]; -} \ No newline at end of file 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 d94ea6817..02392e1a4 100644 --- a/lib/features/email/domain/usecases/get_email_content_interactor.dart +++ b/lib/features/email/domain/usecases/get_email_content_interactor.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; @@ -28,37 +30,85 @@ class GetEmailContentInteractor { ) async* { try { yield Right(GetEmailContentLoading()); - final email = await emailRepository.getEmailContent(session, accountId, emailId); - if (email.emailContentList.isNotEmpty) { - final newEmailContents = await emailRepository.transformEmailContent( - email.emailContentList, - email.allAttachments.listAttachmentsDisplayedInContent, - baseDownloadUrl, - accountId, - draftsEmail: draftsEmail - ); - - final newEmailContentsDisplayed = BuildUtils.isWeb && !composeEmail - ? await emailRepository.addTooltipWhenHoverOnLink(newEmailContents) - : newEmailContents; - - yield Right(GetEmailContentSuccess( - newEmailContents, - newEmailContentsDisplayed, - email.allAttachments, - email - )); - } else if (email.allAttachments.isNotEmpty) { - yield Right(GetEmailContentSuccess([], [], email.allAttachments, email)); - } else if (email.headers?.isNotEmpty == true) { - yield Right(GetEmailContentSuccess([], [], [], email)); + if (!BuildUtils.isWeb) { + yield* _tryToGetOpenedEmailCache(session, accountId, emailId, baseDownloadUrl, composeEmail: composeEmail, draftsEmail: draftsEmail); } else { - yield Left(GetEmailContentFailure(null)); + yield* _getContentEmailFromServer(session, accountId, emailId, baseDownloadUrl, composeEmail: composeEmail, draftsEmail: draftsEmail); } } catch (e) { log('GetEmailContentInteractor::execute(): exception = $e'); yield Left(GetEmailContentFailure(e)); } } + + Stream> _getContentEmailFromServer( + Session session, + AccountId accountId, + EmailId emailId, + String? baseDownloadUrl, + { + bool composeEmail = false, + bool draftsEmail = false + } + ) async* { + final email = await emailRepository.getEmailContent(session, accountId, emailId); + + if (email.emailContentList.isNotEmpty) { + final newEmailContents = await emailRepository.transformEmailContent( + email.emailContentList, + email.allAttachments.listAttachmentsDisplayedInContent, + baseDownloadUrl, + accountId, + draftsEmail: draftsEmail + ); + + final newEmailContentsDisplayed = BuildUtils.isWeb && !composeEmail + ? await emailRepository.addTooltipWhenHoverOnLink(newEmailContents) + : newEmailContents; + + yield Right(GetEmailContentSuccess( + newEmailContents, + newEmailContentsDisplayed, + email.allAttachments, + email + )); + } else if (email.allAttachments.isNotEmpty) { + yield Right(GetEmailContentSuccess([], [], email.allAttachments, email)); + } else if (email.headers?.isNotEmpty == true) { + yield Right(GetEmailContentSuccess([], [], [], email)); + } else { + yield Left(GetEmailContentFailure(null)); + } + } + + Stream> _tryToGetOpenedEmailCache( + Session session, + AccountId accountId, + EmailId emailId, + String? baseDownloadUrl, + { + bool composeEmail = false, + bool draftsEmail = false + } + ) async* { + log('GetEmailContentInteractor::_getOpenedEmailCache():'); + try { + final detailedEmail = await emailRepository.getOpenedEmail(session, accountId, emailId); + if (detailedEmail != null) { + yield Right(GetEmailContentFromCacheSuccess( + detailedEmail.htmlEmailContent ?? "", + detailedEmail.attachments ?? [], + )); + } else { + yield* _getContentEmailFromServer(session, accountId, emailId, baseDownloadUrl, composeEmail: composeEmail, draftsEmail: draftsEmail); + } + } catch (e) { + if (e is PathNotFoundException) { + yield* _getContentEmailFromServer(session, accountId, emailId, baseDownloadUrl, composeEmail: composeEmail, draftsEmail: draftsEmail); + } else { + yield Left(GetEmailContentFailure(e)); + } + } + } } \ No newline at end of file diff --git a/lib/features/email/domain/usecases/get_opened_email_from_cache_interactor.dart b/lib/features/email/domain/usecases/get_opened_email_from_cache_interactor.dart deleted file mode 100644 index f3966c7af..000000000 --- a/lib/features/email/domain/usecases/get_opened_email_from_cache_interactor.dart +++ /dev/null @@ -1,25 +0,0 @@ - -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:dartz/dartz.dart'; -import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package:jmap_dart_client/jmap/core/session/session.dart'; -import 'package:jmap_dart_client/jmap/mail/email/email.dart'; -import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; -import 'package:tmail_ui_user/features/email/domain/state/get_opened_email_from_cache_state.dart'; - -class GetOpenedEmailFromCacheInteractor { - final EmailRepository _emailRepository; - - GetOpenedEmailFromCacheInteractor(this._emailRepository); - - Stream> execute(Session session, AccountId accountId, EmailId emailId) async* { - try { - yield Right(GetOpenedEmailLoading()); - final detailedEmail = await _emailRepository.getOpenedEmail(session, accountId, emailId); - yield Right(GetOpenedEmailSuccess(detailedEmail)); - } catch (e) { - yield Left(GetOpenedEmailFailure(e)); - } - } -} \ 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 5e00df918..67df14f29 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -100,11 +100,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin { final emailAddressExpandMode = ExpandMode.COLLAPSE.obs; final attachmentsExpandMode = ExpandMode.COLLAPSE.obs; - final emailContents = [].obs; + final emailContents = RxnString(); final attachments = [].obs; EmailId? _currentEmailId; Identity? _identitySelected; - List? initialEmailContents; + String? initialEmailContents; final ScrollController scrollControllerAttachment = ScrollController(); @@ -150,6 +150,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { super.handleSuccessViewState(success); if (success is GetEmailContentSuccess) { _getEmailContentSuccess(success); + } else if (success is GetEmailContentFromCacheSuccess) { + _getEmailContentOffLineSuccess(success); } else if (success is MarkAsEmailReadSuccess) { _markAsEmailReadSuccess(success); } else if (success is ExportAttachmentSuccess) { @@ -356,6 +358,12 @@ 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()) { emailSupervisorController.popFirstEmailQueue(); @@ -370,8 +378,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { )); if (success.emailCurrent?.id == currentEmail?.id) { - emailContents.value = success.emailContentsDisplayed; - initialEmailContents = success.emailContents; + emailContents.value = success.emailContentsDisplayed.asHtmlString; + initialEmailContents = success.emailContents.asHtmlString; attachments.value = success.attachments; if (!BuildUtils.isWeb) { @@ -379,7 +387,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { emailId: currentEmail!.id!, attachments: attachments, headers: currentEmail?.emailHeader, - htmlEmailContent: emailContents.asHtmlString + htmlEmailContent: emailContents.value ); _storeOpenedEmailToCache( @@ -414,8 +422,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void _resetToOriginalValue() { attachmentsExpandMode.value = ExpandMode.COLLAPSE; emailAddressExpandMode.value = ExpandMode.COLLAPSE; - emailContents.clear(); - initialEmailContents?.clear(); + emailContents.value = null; + initialEmailContents = null; attachments.clear(); } @@ -1133,7 +1141,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { presentationEmail: mailboxDashBoardController.selectedEmail.value!, emailContents: initialEmailContents, attachments: emailActionType == EmailActionType.forward ? attachments : null, - mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role); + mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role + ); mailboxDashBoardController.goToComposer(arguments); } diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index ca3e7e425..7f405c78d 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -18,7 +18,6 @@ import 'package:model/email/attachment.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/email/presentation_email.dart'; import 'package:model/extensions/list_attachment_extension.dart'; -import 'package:model/extensions/list_email_content_extension.dart'; import 'package:model/extensions/presentation_email_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/base/widget/custom_scroll_behavior.dart'; @@ -441,20 +440,20 @@ class EmailView extends GetWidget { return const SizedBox.shrink(); } return Obx(() { - if (controller.emailContents.isNotEmpty) { - final allEmailContents = controller.emailContents.asHtmlString; + if (controller.emailContents.value != null) { + final allEmailContents = controller.emailContents.value; if (BuildUtils.isWeb) { return HtmlContentViewerOnWeb( widthContent: constraints.maxWidth, heightContent: responsiveUtils.getSizeScreenHeight(context), - contentHtml: allEmailContents, + contentHtml: allEmailContents ?? "", controller: HtmlViewerControllerForWeb(), mailtoDelegate: (uri) => controller.openMailToLink(uri)); } else { return HtmlContentViewer( heightContent: responsiveUtils.getSizeScreenHeight(context), - contentHtml: allEmailContents, + contentHtml: allEmailContents ?? "", mailtoDelegate: (uri) async => controller.openMailToLink(uri), onScrollHorizontalEnd: controller.toggleScrollPhysicsPagerView, onWebViewLoaded: (isScrollPageViewActivated) { diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 4a0abfd99..6a6c0003e 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -7,7 +7,7 @@ import 'package:tmail_ui_user/main/routes/router_arguments.dart'; class ComposerArguments extends RouterArguments { final EmailActionType emailActionType; final PresentationEmail? presentationEmail; - final List? emailContents; + final String? emailContents; final List? listSharedMediaFile; final EmailAddress? emailAddress; final List? attachments; 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 8a28ae119..3d48aee14 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -240,7 +240,7 @@ class MailboxDashBoardController extends ReloadableController { cc: success.composerCache.cc, bcc: success.composerCache.bcc, ), - emailContents: success.composerCache.emailContentList, + emailContents: success.composerCache.emailContentList.asHtmlString, ); openComposerOverlay(composerArguments); } @@ -350,7 +350,7 @@ class MailboxDashBoardController extends ReloadableController { _emailReceiveManager.clearPendingEmailContent(); final arguments = ComposerArguments( emailActionType: EmailActionType.edit, - emailContents: [emailContent], + emailContents: [emailContent].asHtmlString, mailboxRole: selectedMailbox.value?.role); goToComposer(arguments); } diff --git a/lib/features/offline_mode/manager/detailed_email_cache_manager.dart b/lib/features/offline_mode/manager/detailed_email_cache_manager.dart index f80c15bd4..bb1e68353 100644 --- a/lib/features/offline_mode/manager/detailed_email_cache_manager.dart +++ b/lib/features/offline_mode/manager/detailed_email_cache_manager.dart @@ -1,5 +1,6 @@ import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/file_utils.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:model/extensions/account_id_extensions.dart'; @@ -12,8 +13,9 @@ import 'package:tmail_ui_user/features/offline_mode/model/detailed_email_hive_ca class DetailedEmailCacheManager { final DetailedEmailHiveCacheClient _cacheClient; + final FileUtils _fileUtils; - DetailedEmailCacheManager(this._cacheClient); + DetailedEmailCacheManager(this._cacheClient, this._fileUtils); Future handleStoreDetailedEmail( AccountId accountId, @@ -23,9 +25,14 @@ class DetailedEmailCacheManager { final listDetailedEmails = await getAllDetailedEmails(accountId, userName); if (listDetailedEmails.length >= CachingConstants.maxNumberNewEmailsForOffline) { - final latestEmail = listDetailedEmails.last; - log('DetailedEmailCacheManager::handleStoreDetailedEmail():latestEmail: $latestEmail'); - await removeDetailedEmail(accountId, userName, latestEmail.emailId); + final lastElementsListEmail = listDetailedEmails.sublist(CachingConstants.maxNumberNewEmailsForOffline, listDetailedEmails.length); + for (var email in lastElementsListEmail) { + log('DetailedEmailCacheManager::handleStoreDetailedEmail():latestEmail: $email'); + if (email.emailContentPath != null) { + await _deleteFileExisted(email.emailContentPath!); + } + await removeDetailedEmail(accountId, userName, email.emailId); + } } await insertDetailedEmail(accountId, userName, detailedEmailCache); @@ -58,4 +65,8 @@ class DetailedEmailCacheManager { log('DetailedEmailCacheManager::getAllDetailedEmails():SIZE: ${detailedEmailCacheList.length}'); return detailedEmailCacheList; } + + Future _deleteFileExisted(String pathFile) async { + await _fileUtils.deleteFile(pathFile); + } } \ No newline at end of file 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 3c541146a..aba370962 100644 --- a/lib/features/offline_mode/manager/opened_email_cache_manager.dart +++ b/lib/features/offline_mode/manager/opened_email_cache_manager.dart @@ -21,9 +21,9 @@ class OpenedEmailCacheManager { OpenedEmailCacheManager(this._cacheClient, this._fileUtils); Future insertDetailedEmail( - AccountId accountId, - UserName userName, - DetailedEmailHiveCache detailedEmailCache + AccountId accountId, + UserName userName, + DetailedEmailHiveCache detailedEmailCache ) { final keyCache = TupleKey(detailedEmailCache.emailId, accountId.asString, userName.value).encodeKey; log('OpenedEmailCacheManager::insertDetailedEmail(): $keyCache'); @@ -31,9 +31,9 @@ class OpenedEmailCacheManager { } Future removeDetailedEmail( - AccountId accountId, - UserName userName, - String emailId + AccountId accountId, + UserName userName, + String emailId ) { final keyCache = TupleKey(emailId, accountId.asString, userName.value).encodeKey; log('OpenedEmailCacheManager::removeDetailedEmail(): $keyCache'); @@ -48,35 +48,40 @@ class OpenedEmailCacheManager { } Future storeOpenedEmail( - AccountId accountId, - UserName userName, - DetailedEmail detailedEmail + AccountId accountId, + UserName userName, + DetailedEmail detailedEmail ) async { final listDetailedEmails = await getAllDetailedEmails(accountId, userName); if (listDetailedEmails.length >= CachingConstants.maxNumberOpenedEmailsForOffline) { - final latestEmail = listDetailedEmails.last; - log('OpenedEmailCacheManager::handleStoreDetailedEmail():latestEmail: $latestEmail'); - await removeDetailedEmail(accountId, userName, latestEmail.emailId); + final lastElementsListEmail = listDetailedEmails.sublist(CachingConstants.maxNumberOpenedEmailsForOffline, listDetailedEmails.length); + for (var email in lastElementsListEmail) { + log('OpenedEmailCacheManager::handleStoreDetailedEmail():latestEmail: $email'); + if (email.emailContentPath != null) { + await _deleteFileExisted(email.emailContentPath!); + } + await removeDetailedEmail(accountId, userName, email.emailId); + } } await insertDetailedEmail(accountId, userName, detailedEmail.toHiveCache()); } Future isOpenedDetailEmailCached( - AccountId accountId, - UserName userName, - DetailedEmail detailedEmail + AccountId accountId, + UserName userName, + EmailId emailId ) async { - final emailContentPathExists = await _isFileExisted(detailedEmail); - final detailedEmailCacheExists = await getDetailEmailExistedInCache(accountId, userName, detailedEmail.emailId); + final emailContentPathExists = await _isFileExisted(emailId); + final detailedEmailCacheExists = await getDetailEmailExistedInCache(accountId, userName, emailId); return emailContentPathExists == true && detailedEmailCacheExists != null; } - Future _isFileExisted(DetailedEmail detailedEmail) async { + Future _isFileExisted(EmailId emailId) async { final fileSaved = await _fileUtils.isFileExisted( - nameFile: detailedEmail.emailId.asString, - folderPath: detailedEmail.folderPath, + nameFile: emailId.asString, + folderPath: CachingConstants.openedEmailContentFolderNamee, ); log('OpenedEmailCacheManager::_getDetailedEmailCache():_getEmailContentPath: $fileSaved'); return fileSaved; @@ -93,4 +98,7 @@ class OpenedEmailCacheManager { return detailedEmailCache; } + Future _deleteFileExisted(String pathFile) async { + await _fileUtils.deleteFile(pathFile); + } } \ No newline at end of file diff --git a/lib/main/bindings/local/local_bindings.dart b/lib/main/bindings/local/local_bindings.dart index a54636dca..62b804f58 100644 --- a/lib/main/bindings/local/local_bindings.dart +++ b/lib/main/bindings/local/local_bindings.dart @@ -73,7 +73,7 @@ class LocalBindings extends Bindings { Get.put(FCMCacheManager(Get.find(),Get.find())); Get.put(HiveCacheVersionClient(Get.find(), Get.find())); Get.put(DetailedEmailHiveCacheClient()); - Get.put(DetailedEmailCacheManager(Get.find())); + Get.put(DetailedEmailCacheManager(Get.find(), Get.find())); Get.put(OpenedEmailHiveCacheClient()); Get.put(OpenedEmailCacheManager(Get.find(), Get.find())); Get.put(CachingManager(