From 27454627b1aa344657ce3a63f24bd93b170d0da3 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 24 Mar 2025 01:56:45 +0700 Subject: [PATCH 01/10] TF-3358 Rename `ComposerCache` to `LocalEmailDraft` Signed-off-by: dab246 --- .../state/save_local_email_draft_state.dart | 9 ++++ ...estore_email_inline_images_interactor.dart | 8 +-- ...=> save_local_email_draft_interactor.dart} | 22 ++++---- .../presentation/composer_bindings.dart | 48 ++++++++--------- .../presentation/composer_controller.dart | 26 ++++----- .../model/composer_arguments.dart | 4 +- ...dart => local_email_draft_datasource.dart} | 14 ++--- ...=> local_email_draft_datasource_impl.dart} | 21 ++++---- ...oser_cache.dart => local_email_draft.dart} | 26 +++++---- .../composer_cache_repository_impl.dart | 54 ------------------- .../local_email_draft_repository_impl.dart | 54 +++++++++++++++++++ ...dart => local_email_draft_repository.dart} | 14 ++--- .../state/get_composer_cache_state.dart | 14 ++--- .../state/remove_composer_cache_state.dart | 8 +-- .../state/save_composer_cache_state.dart | 9 ---- ...get_all_local_email_draft_interactor.dart} | 14 ++--- ...ove_all_local_email_draft_interactor.dart} | 14 ++--- ... remove_local_email_draft_interactor.dart} | 14 ++--- .../bindings/mailbox_dashboard_bindings.dart | 34 ++++++------ .../mailbox_dashboard_controller.dart | 40 +++++++------- .../open_and_close_composer_extension.dart | 2 +- .../reopen_composer_cache_extension.dart | 10 ++-- .../composer_controller_test.dart | 20 +++---- .../mailbox_dashboard_controller_test.dart | 26 ++++----- .../mailbox_dashboard_view_widget_test.dart | 26 ++++----- ...fore_time_in_search_email_filter_test.dart | 28 +++++----- 26 files changed, 283 insertions(+), 276 deletions(-) create mode 100644 lib/features/composer/domain/state/save_local_email_draft_state.dart rename lib/features/composer/domain/usecases/{save_composer_cache_on_web_interactor.dart => save_local_email_draft_interactor.dart} (74%) rename lib/features/mailbox_dashboard/data/datasource/{session_storage_composer_datasource.dart => local_email_draft_datasource.dart} (69%) rename lib/features/mailbox_dashboard/data/datasource_impl/{session_storage_composer_datasoure_impl.dart => local_email_draft_datasource_impl.dart} (83%) rename lib/features/mailbox_dashboard/data/model/{composer_cache.dart => local_email_draft.dart} (70%) delete mode 100644 lib/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart create mode 100644 lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart rename lib/features/mailbox_dashboard/domain/repository/{composer_cache_repository.dart => local_email_draft_repository.dart} (70%) delete mode 100644 lib/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart rename lib/features/mailbox_dashboard/domain/usecases/{get_composer_cache_on_web_interactor.dart => get_all_local_email_draft_interactor.dart} (59%) rename lib/features/mailbox_dashboard/domain/usecases/{remove_all_composer_cache_on_web_interactor.dart => remove_all_local_email_draft_interactor.dart} (60%) rename lib/features/mailbox_dashboard/domain/usecases/{remove_composer_cache_by_id_on_web_interactor.dart => remove_local_email_draft_interactor.dart} (63%) diff --git a/lib/features/composer/domain/state/save_local_email_draft_state.dart b/lib/features/composer/domain/state/save_local_email_draft_state.dart new file mode 100644 index 0000000000..b39e917465 --- /dev/null +++ b/lib/features/composer/domain/state/save_local_email_draft_state.dart @@ -0,0 +1,9 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; + +class SaveLocalEmailDraftSuccess extends UIState {} + +class SaveLocalEmailDraftFailure extends FeatureFailure { + + SaveLocalEmailDraftFailure(dynamic exception) : super(exception: exception); +} \ No newline at end of file diff --git a/lib/features/composer/domain/usecases/restore_email_inline_images_interactor.dart b/lib/features/composer/domain/usecases/restore_email_inline_images_interactor.dart index 0d10be8191..5f34aad7e2 100644 --- a/lib/features/composer/domain/usecases/restore_email_inline_images_interactor.dart +++ b/lib/features/composer/domain/usecases/restore_email_inline_images_interactor.dart @@ -3,12 +3,12 @@ import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; import 'package:dartz/dartz.dart'; import 'package:tmail_ui_user/features/composer/domain/state/restore_email_inline_images_state.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; class RestoreEmailInlineImagesInteractor { - RestoreEmailInlineImagesInteractor(this._composerCacheRepository); + RestoreEmailInlineImagesInteractor(this._localEmailDraftRepository); - final ComposerCacheRepository _composerCacheRepository; + final LocalEmailDraftRepository _localEmailDraftRepository; Stream> execute({ required String htmlContent, @@ -18,7 +18,7 @@ class RestoreEmailInlineImagesInteractor { try { yield Right(RestoringEmailInlineImages()); - final emailContent = await _composerCacheRepository.restoreEmailInlineImages( + final emailContent = await _localEmailDraftRepository.restoreEmailInlineImages( htmlContent, transformConfiguration, mapUrlDownloadCID); diff --git a/lib/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart b/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart similarity index 74% rename from lib/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart rename to lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart index 27ea726c6a..e6b09bba93 100644 --- a/lib/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart +++ b/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart @@ -4,17 +4,17 @@ import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/save_local_email_draft_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; -class SaveComposerCacheOnWebInteractor { - final ComposerCacheRepository _composerCacheRepository; +class SaveLocalEmailDraftInteractor { + final LocalEmailDraftRepository _localEmailDraftRepository; final ComposerRepository _composerRepository; - SaveComposerCacheOnWebInteractor( - this._composerCacheRepository, + SaveLocalEmailDraftInteractor( + this._localEmailDraftRepository, this._composerRepository, ); @@ -29,10 +29,10 @@ class SaveComposerCacheOnWebInteractor { withIdentityHeader: true, isDraft: true, ); - await _composerCacheRepository.saveComposerCacheOnWeb( + await _localEmailDraftRepository.saveLocalEmailDraft( accountId: accountId, userName: userName, - composerCache: ComposerCache( + composerCache: LocalEmailDraft( email: emailCreated, hasRequestReadReceipt: createEmailRequest.hasRequestReadReceipt, isMarkAsImportant: createEmailRequest.isMarkAsImportant, @@ -43,9 +43,9 @@ class SaveComposerCacheOnWebInteractor { actionType: createEmailRequest.savedActionType, draftEmailId: createEmailRequest.draftsEmailId, )); - return Right(SaveComposerCacheSuccess()); + return Right(SaveLocalEmailDraftSuccess()); } catch (exception) { - return Left(SaveComposerCacheFailure(exception)); + return Left(SaveLocalEmailDraftFailure(exception)); } } } diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart index 29727746a5..57719f9c9a 100644 --- a/lib/features/composer/presentation/composer_bindings.dart +++ b/lib/features/composer/presentation/composer_bindings.dart @@ -15,7 +15,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_s import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/restore_email_inline_images_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/save_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/upload_attachment_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; @@ -48,11 +48,11 @@ import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart'; import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/session_storage_composer_datasoure_impl.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/preferences/bindings/preferences_interactors_bindings.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identity_interactors_bindings.dart'; @@ -143,7 +143,7 @@ class ComposerBindings extends BaseBindings { Get.find(), Get.find(), ), tag: composerId); - Get.lazyPut(() => SessionStorageComposerDatasourceImpl( + Get.lazyPut(() => LocalEmailDraftDataSourceImpl( Get.find(), Get.find(), ), tag: composerId); @@ -183,8 +183,8 @@ class ComposerBindings extends BaseBindings { () => Get.find(tag: composerId), tag: composerId, ); - Get.lazyPut( - () => Get.find(tag: composerId), + Get.lazyPut( + () => Get.find(tag: composerId), tag: composerId, ); } @@ -199,7 +199,7 @@ class ComposerBindings extends BaseBindings { Get.find(), ), tag: composerId); Get.lazyPut( - () => ComposerCacheRepositoryImpl(Get.find(tag: composerId)), + () => LocalEmailDraftRepositoryImpl(Get.find(tag: composerId)), tag: composerId, ); Get.lazyPut( @@ -232,8 +232,8 @@ class ComposerBindings extends BaseBindings { () => Get.find(tag: composerId), tag: composerId, ); - Get.lazyPut( - () => Get.find(tag: composerId), + Get.lazyPut( + () => Get.find(tag: composerId), tag: composerId, ); Get.lazyPut( @@ -269,11 +269,11 @@ class ComposerBindings extends BaseBindings { tag: composerId, ); Get.lazyPut( - () => RemoveComposerCacheByIdOnWebInteractor(Get.find(tag: composerId)), + () => RemoveLocalEmailDraftInteractor(Get.find(tag: composerId)), tag: composerId, ); - Get.lazyPut(() => SaveComposerCacheOnWebInteractor( - Get.find(tag: composerId), + Get.lazyPut(() => SaveLocalEmailDraftInteractor( + Get.find(tag: composerId), Get.find(tag: composerId), ), tag: composerId); Get.lazyPut( @@ -293,7 +293,7 @@ class ComposerBindings extends BaseBindings { Get.find(tag: composerId), ), tag: composerId); Get.lazyPut( - () => RestoreEmailInlineImagesInteractor(Get.find(tag: composerId)), + () => RestoreEmailInlineImagesInteractor(Get.find(tag: composerId)), tag: composerId, ); Get.lazyPut( @@ -322,8 +322,8 @@ class ComposerBindings extends BaseBindings { Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), - Get.find(tag: composerId), - Get.find(tag: composerId), + Get.find(tag: composerId), + Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), @@ -357,7 +357,7 @@ class ComposerBindings extends BaseBindings { Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); - Get.delete(tag: composerId); + Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); @@ -367,16 +367,16 @@ class ComposerBindings extends BaseBindings { Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); - Get.delete(tag: composerId); + Get.delete(tag: composerId); Get.delete(tag: composerId); - Get.delete(tag: composerId); + Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); - Get.delete(tag: composerId); + Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); @@ -385,8 +385,8 @@ class ComposerBindings extends BaseBindings { Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); - Get.delete(tag: composerId); - Get.delete(tag: composerId); + Get.delete(tag: composerId); + Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); Get.delete(tag: composerId); diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 49b267f8c4..b78545b433 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -47,7 +47,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomp import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/restore_email_inline_images_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/save_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/auto_create_tag_for_recipients_extension.dart'; @@ -86,6 +86,8 @@ import 'package:tmail_ui_user/features/email/presentation/extensions/presentatio import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.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/open_and_close_composer_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; @@ -145,8 +147,8 @@ class ComposerController extends BaseController final GetEmailContentInteractor _getEmailContentInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final UploadController uploadController; - final RemoveComposerCacheByIdOnWebInteractor _removeComposerCacheByIdOnWebInteractor; - final SaveComposerCacheOnWebInteractor _saveComposerCacheOnWebInteractor; + final RemoveLocalEmailDraftInteractor _removeLocalEmailDraftInteractor; + final SaveLocalEmailDraftInteractor _saveLocalEmailDraftInteractor; final DownloadImageAsBase64Interactor _downloadImageAsBase64Interactor; final TransformHtmlEmailContentInteractor _transformHtmlEmailContentInteractor; final GetServerSettingInteractor _getServerSettingInteractor; @@ -230,7 +232,7 @@ class ComposerController extends BaseController int? get savedEmailDraftHash => _savedEmailDraftHash; GetEmailContentInteractor get getEmailContentInteractor => _getEmailContentInteractor; - + GetServerSettingInteractor get getServerSettingInteractor => _getServerSettingInteractor; GetAllIdentitiesInteractor get getAllIdentitiesInteractor => _getAllIdentitiesInteractor; @@ -247,8 +249,8 @@ class ComposerController extends BaseController this._getEmailContentInteractor, this._getAllIdentitiesInteractor, this.uploadController, - this._removeComposerCacheByIdOnWebInteractor, - this._saveComposerCacheOnWebInteractor, + this._removeLocalEmailDraftInteractor, + this._saveLocalEmailDraftInteractor, this._downloadImageAsBase64Interactor, this._transformHtmlEmailContentInteractor, this._getServerSettingInteractor, @@ -398,13 +400,13 @@ class ComposerController extends BaseController final username = mailboxDashBoardController.sessionCurrent?.username; final accountId = mailboxDashBoardController.accountId.value; if (composerId != null && username != null && accountId != null) { - await _removeComposerCacheByIdOnWebInteractor.execute( + await _removeLocalEmailDraftInteractor.execute( accountId, username, composerId!, ); } - await _saveComposerCacheOnWebAction(); + await _saveLocalEmailDraftAction(); } void _listenStreamEvent() { @@ -452,13 +454,13 @@ class ComposerController extends BaseController }); } - Future _saveComposerCacheOnWebAction() async { + Future _saveLocalEmailDraftAction() async { autoCreateEmailTag(); final createEmailRequest = await _generateCreateEmailRequestToSaveAsCache(); if (createEmailRequest == null) return; - await _saveComposerCacheOnWebInteractor.execute( + await _saveLocalEmailDraftInteractor.execute( createEmailRequest, mailboxDashBoardController.accountId.value!, mailboxDashBoardController.sessionCurrent!.username); @@ -607,7 +609,7 @@ class ComposerController extends BaseController mailboxDashBoardController.accountId.value, ); } - + Future setupComposer() async { _isEmailBodyLoaded = false; final arguments = PlatformInfo.isWeb ? composerArgs : Get.arguments; @@ -2040,7 +2042,7 @@ class ComposerController extends BaseController if (mailboxDashBoardController.accountId.value != null && mailboxDashBoardController.sessionCurrent?.username != null ) { - await _saveComposerCacheOnWebAction(); + await _saveLocalEmailDraftAction(); } } diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index de16c586db..858cdbee52 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -6,7 +6,7 @@ import 'package:model/model.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart'; import 'package:tmail_ui_user/main/routes/router_arguments.dart'; @@ -119,7 +119,7 @@ class ComposerArguments extends RouterArguments { presentationEmail: presentationEmail, ); - factory ComposerArguments.fromSessionStorageBrowser(ComposerCache composerCache) => + factory ComposerArguments.fromSessionStorageBrowser(LocalEmailDraft composerCache) => ComposerArguments( emailActionType: EmailActionType.reopenComposerBrowser, presentationEmail: composerCache.email?.toPresentationEmail(), diff --git a/lib/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart similarity index 69% rename from lib/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart rename to lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart index 008a47ee5f..5e58a24290 100644 --- a/lib/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart +++ b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart @@ -1,25 +1,25 @@ import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; -abstract class SessionStorageComposerDatasource { - Future saveComposerCacheOnWeb({ +abstract class LocalEmailDraftDatasource { + Future saveLocalEmailDraft({ required AccountId accountId, required UserName userName, - required ComposerCache composerCache, + required LocalEmailDraft composerCache, }); - Future> getComposerCacheOnWeb( + Future> getLocalEmailDraft( AccountId accountId, UserName userName); - Future removeAllComposerCacheOnWeb( + Future removeAllLocalEmailDraft( AccountId accountId, UserName userName, ); - Future removeComposerCacheByIdOnWeb( + Future removeLocalEmailDraft( AccountId accountId, UserName userName, String composerId, diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/session_storage_composer_datasoure_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart similarity index 83% rename from lib/features/mailbox_dashboard/data/datasource_impl/session_storage_composer_datasoure_impl.dart rename to lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart index 824140b429..e1f836fd87 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/session_storage_composer_datasoure_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart @@ -7,20 +7,19 @@ import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/extensions/account_id_extensions.dart'; import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; import 'package:universal_html/html.dart' as html; -class SessionStorageComposerDatasourceImpl - extends SessionStorageComposerDatasource { - SessionStorageComposerDatasourceImpl(this._htmlTransform, this._exceptionThrower); +class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { + LocalEmailDraftDataSourceImpl(this._htmlTransform, this._exceptionThrower); final HtmlTransform _htmlTransform; final ExceptionThrower _exceptionThrower; @override - Future> getComposerCacheOnWeb( + Future> getLocalEmailDraft( AccountId accountId, UserName userName ) async { @@ -36,7 +35,7 @@ class SessionStorageComposerDatasourceImpl if (listEntries.isNotEmpty) { return listEntries - .map((entry) => ComposerCache.fromJson(jsonDecode(entry.value))) + .map((entry) => LocalEmailDraft.fromJson(jsonDecode(entry.value))) .toList(); } else { throw NotFoundInWebSessionException(); @@ -45,10 +44,10 @@ class SessionStorageComposerDatasourceImpl } @override - Future saveComposerCacheOnWeb({ + Future saveLocalEmailDraft({ required AccountId accountId, required UserName userName, - required ComposerCache composerCache, + required LocalEmailDraft composerCache, }) async { return Future.sync(() { final composerCacheKey = TupleKey( @@ -78,7 +77,7 @@ class SessionStorageComposerDatasourceImpl } @override - Future removeAllComposerCacheOnWeb(AccountId accountId, UserName userName) { + Future removeAllLocalEmailDraft(AccountId accountId, UserName userName) { return Future.sync(() { final keyWithIdentity = TupleKey( EmailActionType.reopenComposerBrowser.name, @@ -91,7 +90,7 @@ class SessionStorageComposerDatasourceImpl } @override - Future removeComposerCacheByIdOnWeb(AccountId accountId, UserName userName, String composerId) { + Future removeLocalEmailDraft(AccountId accountId, UserName userName, String composerId) { return Future.sync(() { final keyWithIdentity = TupleKey( EmailActionType.reopenComposerBrowser.name, diff --git a/lib/features/mailbox_dashboard/data/model/composer_cache.dart b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart similarity index 70% rename from lib/features/mailbox_dashboard/data/model/composer_cache.dart rename to lib/features/mailbox_dashboard/data/model/local_email_draft.dart index 30f6b9ed2b..0c40cade81 100644 --- a/lib/features/mailbox_dashboard/data/model/composer_cache.dart +++ b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart @@ -5,17 +5,19 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:model/email/email_action_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; -part 'composer_cache.g.dart'; +part 'local_email_draft.g.dart'; @JsonSerializable( - explicitToJson: true, - includeIfNull: false, - converters: [ - EmailIdNullableConverter(), - ] + explicitToJson: true, + includeIfNull: false, + converters: [ + EmailIdNullableConverter(), + ] ) -class ComposerCache with EquatableMixin { +class LocalEmailDraft with EquatableMixin { + final String? id; + final DateTime? timeStamp; final Email? email; final bool? hasRequestReadReceipt; final bool? isMarkAsImportant; @@ -26,7 +28,9 @@ class ComposerCache with EquatableMixin { final EmailActionType? actionType; final EmailId? draftEmailId; - ComposerCache({ + LocalEmailDraft({ + this.id, + this.timeStamp, this.email, this.hasRequestReadReceipt, this.isMarkAsImportant, @@ -38,12 +42,14 @@ class ComposerCache with EquatableMixin { this.draftEmailId, }); - factory ComposerCache.fromJson(Map json) => _$ComposerCacheFromJson(json); + factory LocalEmailDraft.fromJson(Map json) => _$LocalEmailDraftFromJson(json); - Map toJson() => _$ComposerCacheToJson(this); + Map toJson() => _$LocalEmailDraftToJson(this); @override List get props => [ + id, + timeStamp, email, hasRequestReadReceipt, isMarkAsImportant, diff --git a/lib/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart deleted file mode 100644 index 80c2233b99..0000000000 --- a/lib/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; -import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package:jmap_dart_client/jmap/core/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; - -class ComposerCacheRepositoryImpl extends ComposerCacheRepository { - - final SessionStorageComposerDatasource composerCacheDataSource; - - ComposerCacheRepositoryImpl(this.composerCacheDataSource); - - @override - Future> getComposerCacheOnWeb( - AccountId accountId, - UserName userName - ) { - return composerCacheDataSource.getComposerCacheOnWeb(accountId, userName); - } - - @override - Future removeAllComposerCacheOnWeb(AccountId accountId, UserName userName) { - return composerCacheDataSource.removeAllComposerCacheOnWeb(accountId, userName); - } - - @override - Future removeComposerCacheByIdOnWeb(AccountId accountId, UserName userName, String composerId) { - return composerCacheDataSource.removeComposerCacheByIdOnWeb(accountId, userName, composerId); - } - - @override - Future saveComposerCacheOnWeb({ - required AccountId accountId, - required UserName userName, - required ComposerCache composerCache, - }) { - return composerCacheDataSource.saveComposerCacheOnWeb( - accountId: accountId, - userName: userName, - composerCache: composerCache); - } - - @override - Future restoreEmailInlineImages( - String htmlContent, - TransformConfiguration transformConfiguration, - Map mapUrlDownloadCID) { - return composerCacheDataSource.restoreEmailInlineImages( - htmlContent, - transformConfiguration, - mapUrlDownloadCID); - } -} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart new file mode 100644 index 0000000000..1d5660323f --- /dev/null +++ b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart @@ -0,0 +1,54 @@ +import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; + +class LocalEmailDraftRepositoryImpl extends LocalEmailDraftRepository { + + final LocalEmailDraftDatasource _localEmailDraftDatasource; + + LocalEmailDraftRepositoryImpl(this._localEmailDraftDatasource); + + @override + Future> getLocalEmailDraft( + AccountId accountId, + UserName userName + ) { + return _localEmailDraftDatasource.getLocalEmailDraft(accountId, userName); + } + + @override + Future removeAllLocalEmailDraft(AccountId accountId, UserName userName) { + return _localEmailDraftDatasource.removeAllLocalEmailDraft(accountId, userName); + } + + @override + Future removeLocalEmailDraft(AccountId accountId, UserName userName, String composerId) { + return _localEmailDraftDatasource.removeLocalEmailDraft(accountId, userName, composerId); + } + + @override + Future saveLocalEmailDraft({ + required AccountId accountId, + required UserName userName, + required LocalEmailDraft composerCache, + }) { + return _localEmailDraftDatasource.saveLocalEmailDraft( + accountId: accountId, + userName: userName, + composerCache: composerCache); + } + + @override + Future restoreEmailInlineImages( + String htmlContent, + TransformConfiguration transformConfiguration, + Map mapUrlDownloadCID) { + return _localEmailDraftDatasource.restoreEmailInlineImages( + htmlContent, + transformConfiguration, + mapUrlDownloadCID); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart similarity index 70% rename from lib/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart rename to lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart index 929e3e7bb4..81376c12f0 100644 --- a/lib/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart +++ b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart @@ -1,25 +1,25 @@ import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; -abstract class ComposerCacheRepository { - Future saveComposerCacheOnWeb({ +abstract class LocalEmailDraftRepository { + Future saveLocalEmailDraft({ required AccountId accountId, required UserName userName, - required ComposerCache composerCache, + required LocalEmailDraft composerCache, }); - Future> getComposerCacheOnWeb( + Future> getLocalEmailDraft( AccountId accountId, UserName userName); - Future removeAllComposerCacheOnWeb( + Future removeAllLocalEmailDraft( AccountId accountId, UserName userName, ); - Future removeComposerCacheByIdOnWeb( + Future removeLocalEmailDraft( AccountId accountId, UserName userName, String composerId, diff --git a/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart b/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart index d80a71abf6..32f560cfb1 100644 --- a/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart +++ b/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart @@ -1,18 +1,18 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; -class GetComposerCacheSuccess extends UIState { +class GetLocalEmailDraftSuccess extends UIState { - final List listComposerCache; + final List listLocalEmailDraft; - GetComposerCacheSuccess(this.listComposerCache); + GetLocalEmailDraftSuccess(this.listLocalEmailDraft); @override - List get props => [listComposerCache]; + List get props => [listLocalEmailDraft]; } -class GetComposerCacheFailure extends FeatureFailure { +class GetLocalEmailDraftFailure extends FeatureFailure { - GetComposerCacheFailure(dynamic exception) : super(exception: exception); + GetLocalEmailDraftFailure(dynamic exception) : super(exception: exception); } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart b/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart index 04460eda13..f12941d16d 100644 --- a/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart +++ b/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart @@ -1,15 +1,15 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -class RemoveComposerCacheSuccess extends UIState { +class RemoveLocalEmailDraftSuccess extends UIState { - RemoveComposerCacheSuccess(); + RemoveLocalEmailDraftSuccess(); @override List get props => []; } -class RemoveComposerCacheFailure extends FeatureFailure { +class RemoveLocalEmailDraftFailure extends FeatureFailure { - RemoveComposerCacheFailure(dynamic exception) : super(exception: exception); + RemoveLocalEmailDraftFailure(dynamic exception) : super(exception: exception); } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart b/lib/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart deleted file mode 100644 index c4119537bc..0000000000 --- a/lib/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; - -class SaveComposerCacheSuccess extends UIState {} - -class SaveComposerCacheFailure extends FeatureFailure { - - SaveComposerCacheFailure(dynamic exception) : super(exception: exception); -} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart similarity index 59% rename from lib/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart rename to lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart index 4a96959d70..59f5361fab 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart @@ -3,23 +3,23 @@ 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/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart'; -class GetComposerCacheOnWebInteractor { - final ComposerCacheRepository composerCacheRepository; +class GetAllLocalEmailDraftInteractor { + final LocalEmailDraftRepository _localEmailDraftRepository; - GetComposerCacheOnWebInteractor(this.composerCacheRepository); + GetAllLocalEmailDraftInteractor(this._localEmailDraftRepository); Stream> execute(AccountId accountId, UserName userName) async* { try { - final listComposerCache = await composerCacheRepository.getComposerCacheOnWeb( + final listLocalEmailDraft = await _localEmailDraftRepository.getLocalEmailDraft( accountId, userName, ); - yield Right(GetComposerCacheSuccess(listComposerCache)); + yield Right(GetLocalEmailDraftSuccess(listLocalEmailDraft)); } catch (exception) { - yield Left(GetComposerCacheFailure(exception)); + yield Left(GetLocalEmailDraftFailure(exception)); } } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart similarity index 60% rename from lib/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart rename to lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart index 31bc522897..bda2a36089 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart @@ -3,20 +3,20 @@ 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/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart'; -class RemoveAllComposerCacheOnWebInteractor { - final ComposerCacheRepository composerCacheRepository; +class RemoveAllLocalEmailDraftInteractor { + final LocalEmailDraftRepository _localEmailDraftRepository; - RemoveAllComposerCacheOnWebInteractor(this.composerCacheRepository); + RemoveAllLocalEmailDraftInteractor(this._localEmailDraftRepository); Future> execute(AccountId accountId, UserName userName) async { try { - composerCacheRepository.removeAllComposerCacheOnWeb(accountId, userName); - return Right(RemoveComposerCacheSuccess()); + _localEmailDraftRepository.removeAllLocalEmailDraft(accountId, userName); + return Right(RemoveLocalEmailDraftSuccess()); } catch (exception) { - return Left(RemoveComposerCacheFailure(exception)); + return Left(RemoveLocalEmailDraftFailure(exception)); } } } diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart similarity index 63% rename from lib/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart rename to lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart index 08bdc06e5a..1b7abfa042 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart @@ -3,13 +3,13 @@ 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/user_name.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart'; -class RemoveComposerCacheByIdOnWebInteractor { - final ComposerCacheRepository composerCacheRepository; +class RemoveLocalEmailDraftInteractor { + final LocalEmailDraftRepository _localEmailDraftRepository; - RemoveComposerCacheByIdOnWebInteractor(this.composerCacheRepository); + RemoveLocalEmailDraftInteractor(this._localEmailDraftRepository); Future> execute( AccountId accountId, @@ -17,14 +17,14 @@ class RemoveComposerCacheByIdOnWebInteractor { String composerId, ) async { try { - composerCacheRepository.removeComposerCacheByIdOnWeb( + _localEmailDraftRepository.removeLocalEmailDraft( accountId, userName, composerId, ); - return Right(RemoveComposerCacheSuccess()); + return Right(RemoveLocalEmailDraftSuccess()); } catch (exception) { - return Left(RemoveComposerCacheFailure(exception)); + return Left(RemoveLocalEmailDraftFailure(exception)); } } } diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart index c0ee572250..da911c5849 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -57,33 +57,33 @@ import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_reposit import 'package:tmail_ui_user/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/app_grid_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_datasource.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/app_grid_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/hive_spam_report_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_app_grid_datasource_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/session_storage_composer_datasoure_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_spam_report_manager.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/app_grid_repository_impl.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/composer_cache_repository_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/search_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/spam_report_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/app_grid_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/spam_report_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_app_dashboard_configuration_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_app_grid_linagra_ecosystem_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_mailbox_cached_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_report_state_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart'; @@ -176,7 +176,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), + Get.find(), Get.find(), Get.find(), Get.find(), @@ -196,8 +196,8 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), - Get.find(), + Get.find(), + Get.find(), Get.find(), )); Get.put(AdvancedFilterController()); @@ -212,7 +212,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); - Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut( @@ -256,7 +256,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => MailboxCacheDataSourceImpl( Get.find(), Get.find())); - Get.lazyPut(() => SessionStorageComposerDatasourceImpl( + Get.lazyPut(() => LocalEmailDraftDataSourceImpl( Get.find(), Get.find())); Get.lazyPut(() => LocalSpamReportDataSourceImpl( @@ -311,9 +311,9 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => RefreshChangesSearchEmailInteractor(Get.find())); Get.lazyPut(() => QuickSearchEmailInteractor(Get.find())); Get.lazyPut(() => MarkAsMailboxReadInteractor(Get.find())); - Get.lazyPut(() => GetComposerCacheOnWebInteractor(Get.find())); - Get.lazyPut(() => RemoveComposerCacheByIdOnWebInteractor(Get.find())); - Get.lazyPut(() => RemoveAllComposerCacheOnWebInteractor(Get.find())); + Get.lazyPut(() => GetAllLocalEmailDraftInteractor(Get.find())); + Get.lazyPut(() => RemoveLocalEmailDraftInteractor(Get.find())); + Get.lazyPut(() => RemoveAllLocalEmailDraftInteractor(Get.find())); Get.lazyPut(() => MarkAsEmailReadInteractor(Get.find())); Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find())); Get.lazyPut(() => MarkAsMultipleEmailReadInteractor( @@ -365,7 +365,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); - Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); @@ -401,7 +401,7 @@ class MailboxDashBoardBindings extends BaseBindings { }, Get.find(), )); - Get.lazyPut(() => ComposerCacheRepositoryImpl(Get.find())); + Get.lazyPut(() => LocalEmailDraftRepositoryImpl(Get.find())); Get.lazyPut(() => SpamReportRepositoryImpl( { DataSourceType.local: Get.find(), 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 546baa81d5..130195e8ae 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -91,10 +91,10 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_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'; @@ -195,7 +195,7 @@ class MailboxDashBoardController extends ReloadableController final MoveToMailboxInteractor _moveToMailboxInteractor; final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor; final MarkAsMailboxReadInteractor _markAsMailboxReadInteractor; - final GetComposerCacheOnWebInteractor _getEmailCacheOnWebInteractor; + final GetAllLocalEmailDraftInteractor _getAllLocalEmailDraftInteractor; final GetIdentityCacheOnWebInteractor _getIdentityCacheOnWebInteractor; final MarkAsEmailReadInteractor _markAsEmailReadInteractor; final MarkAsStarEmailInteractor _markAsStarEmailInteractor; @@ -215,8 +215,8 @@ class MailboxDashBoardController extends ReloadableController final UnsubscribeEmailInteractor _unsubscribeEmailInteractor; final RestoredDeletedMessageInteractor _restoreDeletedMessageInteractor; final GetRestoredDeletedMessageInterator _getRestoredDeletedMessageInteractor; - final RemoveComposerCacheByIdOnWebInteractor _removeComposerCacheByIdOnWebInteractor; - final RemoveAllComposerCacheOnWebInteractor _removeAllComposerCacheOnWebInteractor; + final RemoveLocalEmailDraftInteractor _removeLocalEmailDraftInteractor; + final RemoveAllLocalEmailDraftInteractor _removeAllLocalEmailDraftInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; GetAllVacationInteractor? _getAllVacationInteractor; @@ -287,7 +287,7 @@ class MailboxDashBoardController extends ReloadableController this._moveToMailboxInteractor, this._deleteEmailPermanentlyInteractor, this._markAsMailboxReadInteractor, - this._getEmailCacheOnWebInteractor, + this._getAllLocalEmailDraftInteractor, this._getIdentityCacheOnWebInteractor, this._markAsEmailReadInteractor, this._markAsStarEmailInteractor, @@ -307,8 +307,8 @@ class MailboxDashBoardController extends ReloadableController this._unsubscribeEmailInteractor, this._restoreDeletedMessageInteractor, this._getRestoredDeletedMessageInteractor, - this._removeAllComposerCacheOnWebInteractor, - this._removeComposerCacheByIdOnWebInteractor, + this._removeAllLocalEmailDraftInteractor, + this._removeLocalEmailDraftInteractor, this._getAllIdentitiesInteractor, ); @@ -339,11 +339,11 @@ class MailboxDashBoardController extends ReloadableController super.onReady(); } - void _handleComposerCache() async { + void _handleLocalEmailDraft() async { if (accountId.value == null || sessionCurrent == null) return; consumeState( - _getEmailCacheOnWebInteractor.execute( + _getAllLocalEmailDraftInteractor.execute( accountId.value!, sessionCurrent!.username)); } @@ -436,8 +436,8 @@ class MailboxDashBoardController extends ReloadableController _handleGetRestoredDeletedMessageSuccess(success); } else if (success is GetAllIdentitiesSuccess) { _handleGetAllIdentitiesSuccess(success); - } else if (success is GetComposerCacheSuccess) { - handleGetComposerCacheSuccess(success); + } else if (success is GetLocalEmailDraftSuccess) { + handleGetLocalEmailDraftSuccess(success); } else if (success is GetIdentityCacheOnWebSuccess) { goToSettings(); } else if (success is MarkAsStarEmailSuccess) { @@ -477,7 +477,7 @@ class MailboxDashBoardController extends ReloadableController _handleEmptyTrashFolderFailure(failure); } else if (failure is MoveMultipleEmailToMailboxFailure) { toastManager.showMessageFailure(failure); - } else if (failure is GetComposerCacheFailure) { + } else if (failure is GetLocalEmailDraftFailure) { _handleIdentityCache(); } else if (failure is GetServerSettingFailure) { isSenderImportantFlagEnabled.value = true; @@ -723,7 +723,7 @@ class MailboxDashBoardController extends ReloadableController _setUpComponentsFromSession(session); if (PlatformInfo.isWeb) { - _handleComposerCache(); + _handleLocalEmailDraft(); } if (PlatformInfo.isAndroid && !_notificationManager.isNotificationClickedOnTerminate) { @@ -1692,7 +1692,7 @@ class MailboxDashBoardController extends ReloadableController _getRouteParameters(); _setUpComponentsFromSession(session); if (PlatformInfo.isWeb) { - _handleComposerCache(); + _handleLocalEmailDraft(); } } @@ -3051,20 +3051,20 @@ class MailboxDashBoardController extends ReloadableController isRecoveringDeletedMessage.value = true; } - Future removeComposerCacheByIdOnWeb(String composerId) async { + Future removeLocalEmailDraft(String composerId) async { if (accountId.value == null || sessionCurrent == null) return; - await _removeComposerCacheByIdOnWebInteractor.execute( + await _removeLocalEmailDraftInteractor.execute( accountId.value!, sessionCurrent!.username, composerId, ); } - Future removeAllComposerCacheOnWeb() async { + Future removeAllLocalEmailDraft() async { if (accountId.value == null || sessionCurrent == null) return; - await _removeAllComposerCacheOnWebInteractor.execute( + await _removeAllLocalEmailDraftInteractor.execute( accountId.value!, sessionCurrent!.username, ); diff --git a/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart index 0bf967b5a0..3fd78493e4 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart @@ -114,7 +114,7 @@ extension OpenAndCloseComposerExtension on MailboxDashBoardController { _handleResultAfterCloseComposer(result); if (composerId != null) { - await removeComposerCacheByIdOnWeb(composerId); + await removeLocalEmailDraft(composerId); } } diff --git a/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart index c914b1abac..9a92658d99 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart @@ -4,15 +4,15 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_compos import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart'; -extension ReopenComposerCacheExtension on MailboxDashBoardController { +extension ReopenLocalEmailDraftExtension on MailboxDashBoardController { - void handleGetComposerCacheSuccess(GetComposerCacheSuccess success) { - removeAllComposerCacheOnWeb(); + void handleGetLocalEmailDraftSuccess(GetLocalEmailDraftSuccess success) { + removeAllLocalEmailDraft(); - final listComposerCacheSortByIndex = success.listComposerCache + final listLocalEmailDraftSortByIndex = success.listLocalEmailDraft ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); - final listArguments = listComposerCacheSortByIndex + final listArguments = listLocalEmailDraftSortByIndex .map((composerCache) => ComposerArguments.fromSessionStorageBrowser(composerCache)) .toList(); diff --git a/test/features/composer/presentation/composer_controller_test.dart b/test/features/composer/presentation/composer_controller_test.dart index bd1b7db0a2..baa3519599 100644 --- a/test/features/composer/presentation/composer_controller_test.dart +++ b/test/features/composer/presentation/composer_controller_test.dart @@ -32,7 +32,7 @@ import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/save_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; @@ -48,7 +48,7 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; 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/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; @@ -151,8 +151,8 @@ class MockMailboxDashBoardController extends Mock implements MailboxDashBoardCon MockSpec(), MockSpec(), MockSpec(fallbackGenerators: fallbackGenerators), - MockSpec(), - MockSpec(), + MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -195,8 +195,8 @@ void main() { late MockGetEmailContentInteractor mockGetEmailContentInteractor; late MockGetAllIdentitiesInteractor mockGetAllIdentitiesInteractor; late MockUploadController mockUploadController; - late MockRemoveComposerCacheByIdOnWebInteractor mockRemoveComposerCacheByIdOnWebInteractor; - late MockSaveComposerCacheOnWebInteractor mockSaveComposerCacheOnWebInteractor; + late MockRemoveLocalEmailDraftInteractor mockRemoveLocalEmailDraftInteractor; + late MockSaveLocalEmailDraftInteractor mockSaveLocalEmailDraftInteractor; late MockDownloadImageAsBase64Interactor mockDownloadImageAsBase64Interactor; late MockTransformHtmlEmailContentInteractor mockTransformHtmlEmailContentInteractor; late MockGetServerSettingInteractor mockGetServerSettingInteractor; @@ -264,8 +264,8 @@ void main() { mockGetEmailContentInteractor = MockGetEmailContentInteractor(); mockGetAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); mockUploadController = MockUploadController(); - mockRemoveComposerCacheByIdOnWebInteractor = MockRemoveComposerCacheByIdOnWebInteractor(); - mockSaveComposerCacheOnWebInteractor = MockSaveComposerCacheOnWebInteractor(); + mockRemoveLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); + mockSaveLocalEmailDraftInteractor = MockSaveLocalEmailDraftInteractor(); mockDownloadImageAsBase64Interactor = MockDownloadImageAsBase64Interactor(); mockTransformHtmlEmailContentInteractor = MockTransformHtmlEmailContentInteractor(); mockGetServerSettingInteractor = MockGetServerSettingInteractor(); @@ -280,8 +280,8 @@ void main() { mockGetEmailContentInteractor, mockGetAllIdentitiesInteractor, mockUploadController, - mockRemoveComposerCacheByIdOnWebInteractor, - mockSaveComposerCacheOnWebInteractor, + mockRemoveLocalEmailDraftInteractor, + mockSaveLocalEmailDraftInteractor, mockDownloadImageAsBase64Interactor, mockTransformHtmlEmailContentInteractor, mockGetServerSettingInteractor, diff --git a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart index a09c7c8f7d..856c8174a7 100644 --- a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart +++ b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart @@ -53,12 +53,12 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_multipl import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -116,7 +116,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -174,8 +174,8 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), + MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -189,7 +189,7 @@ void main() { final deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - final getEmailCacheOnWebInteractor = MockGetComposerCacheOnWebInteractor(); + final getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -265,8 +265,8 @@ void main() { final verifyNameInteractor = MockVerifyNameInteractor(); final getAllMailboxInteractor = MockGetAllMailboxInteractor(); final refreshAllMailboxInteractor = MockRefreshAllMailboxInteractor(); - final removeAllComposerCacheOnWebInteractor = MockRemoveAllComposerCacheOnWebInteractor(); - final removeComposerCacheByIdOnWebInteractor = MockRemoveComposerCacheByIdOnWebInteractor(); + final removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); + final removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); final composerManager = MockComposerManager(); late MailboxController mailboxController; @@ -319,8 +319,8 @@ void main() { Get.put(getAuthenticatedAccountInteractor); Get.put(updateAccountCacheInteractor); Get.put(getAllIdentitiesInteractor); - Get.put(removeAllComposerCacheOnWebInteractor); - Get.put(removeComposerCacheByIdOnWebInteractor); + Get.put(removeAllLocalEmailDraftInteractor); + Get.put(removeLocalEmailDraftInteractor); Get.put(composerManager); searchController = SearchController( @@ -355,8 +355,8 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllComposerCacheOnWebInteractor, - removeComposerCacheByIdOnWebInteractor, + removeAllLocalEmailDraftInteractor, + removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); }); diff --git a/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart b/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart index 67171beb18..a48774b26d 100644 --- a/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart +++ b/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart @@ -52,12 +52,12 @@ import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.d import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -118,7 +118,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -175,8 +175,8 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), + MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -189,7 +189,7 @@ void main() { final moveToMailboxInteractor = MockMoveToMailboxInteractor(); final deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - final getEmailCacheOnWebInteractor = MockGetComposerCacheOnWebInteractor(); + final getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -252,8 +252,8 @@ void main() { final verifyNameInteractor = MockVerifyNameInteractor(); final getAllMailboxInteractor = MockGetAllMailboxInteractor(); final refreshAllMailboxInteractor = MockRefreshAllMailboxInteractor(); - final removeAllComposerCacheOnWebInteractor = MockRemoveAllComposerCacheOnWebInteractor(); - final removeComposerCacheByIdOnWebInteractor = MockRemoveComposerCacheByIdOnWebInteractor(); + final removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); + final removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); final composerManager = MockComposerManager(); @@ -317,8 +317,8 @@ void main() { Get.put(getAuthenticatedAccountInteractor); Get.put(updateAccountCacheInteractor); Get.put(getAllIdentitiesInteractor); - Get.put(removeAllComposerCacheOnWebInteractor); - Get.put(removeComposerCacheByIdOnWebInteractor); + Get.put(removeAllLocalEmailDraftInteractor); + Get.put(removeLocalEmailDraftInteractor); Get.put(composerManager); when(emailReceiveManager.pendingSharedFileInfo).thenAnswer((_) => BehaviorSubject.seeded([])); @@ -354,8 +354,8 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllComposerCacheOnWebInteractor, - removeComposerCacheByIdOnWebInteractor, + removeAllLocalEmailDraftInteractor, + removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); Get.put(mailboxDashboardController); diff --git a/test/features/search/verify_before_time_in_search_email_filter_test.dart b/test/features/search/verify_before_time_in_search_email_filter_test.dart index 1d82e4a3dd..77bc0674bf 100644 --- a/test/features/search/verify_before_time_in_search_email_filter_test.dart +++ b/test/features/search/verify_before_time_in_search_email_filter_test.dart @@ -39,12 +39,12 @@ import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_i import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_composer_cache_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -136,7 +136,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -153,8 +153,8 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), + MockSpec(), + MockSpec(), MockSpec(), MockSpec(fallbackGenerators: fallbackGenerators), ]) @@ -192,7 +192,7 @@ void main() { late MockMoveToMailboxInteractor moveToMailboxInteractor; late MockDeleteEmailPermanentlyInteractor deleteEmailPermanentlyInteractor; late MockMarkAsMailboxReadInteractor markAsMailboxReadInteractor; - late MockGetComposerCacheOnWebInteractor getEmailCacheOnWebInteractor; + late MockGetAllLocalEmailDraftInteractor getEmailCacheOnWebInteractor; late MockGetIdentityCacheOnWebInteractor getIdentityCacheOnWebInteractor; late MockMarkAsEmailReadInteractor markAsEmailReadInteractor; late MockMarkAsStarEmailInteractor markAsStarEmailInteractor; @@ -211,8 +211,8 @@ void main() { late MockUnsubscribeEmailInteractor unsubscribeEmailInteractor; late MockRestoredDeletedMessageInteractor restoreDeletedMessageInteractor; late MockGetRestoredDeletedMessageInterator getRestoredDeletedMessageInteractor; - late MockRemoveAllComposerCacheOnWebInteractor removeAllComposerCacheOnWebInteractor; - late MockRemoveComposerCacheByIdOnWebInteractor removeComposerCacheByIdOnWebInteractor; + late MockRemoveAllLocalEmailDraftInteractor removeAllLocalEmailDraftInteractor; + late MockRemoveLocalEmailDraftInteractor removeLocalEmailDraftInteractor; late MockGetAllIdentitiesInteractor getAllIdentitiesInteractor; // Declaration base controller @@ -285,7 +285,7 @@ void main() { moveToMailboxInteractor = MockMoveToMailboxInteractor(); deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - getEmailCacheOnWebInteractor = MockGetComposerCacheOnWebInteractor(); + getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -304,8 +304,8 @@ void main() { unsubscribeEmailInteractor = MockUnsubscribeEmailInteractor(); restoreDeletedMessageInteractor = MockRestoredDeletedMessageInteractor(); getRestoredDeletedMessageInteractor = MockGetRestoredDeletedMessageInterator(); - removeAllComposerCacheOnWebInteractor = MockRemoveAllComposerCacheOnWebInteractor(); - removeComposerCacheByIdOnWebInteractor = MockRemoveComposerCacheByIdOnWebInteractor(); + removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); + removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); searchController = SearchController( @@ -350,8 +350,8 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllComposerCacheOnWebInteractor, - removeComposerCacheByIdOnWebInteractor, + removeAllLocalEmailDraftInteractor, + removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); From 52a8505320101a8677d1992f4d54f80ae3d77aba Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 25 Mar 2025 11:24:19 +0700 Subject: [PATCH 02/10] TF-3358 Save LocalEmailDraft to hive database Signed-off-by: dab246 --- .../clients/local_email_draft_client.dart | 9 +++ .../caching/config/hive_cache_config.dart | 5 ++ .../caching/utils/caching_constants.dart | 2 + .../save_local_email_draft_interactor.dart | 19 ++--- .../presentation/composer_bindings.dart | 6 +- .../presentation/composer_controller.dart | 35 +++----- .../create_email_request_extension.dart | 23 ++++++ .../handle_local_email_draft_extension.dart | 81 +++++++++++++++++++ .../local_email_draft_datasource.dart | 8 +- .../local_email_draft_datasource_impl.dart | 61 ++++++-------- .../data/local/local_email_draft_manager.dart | 35 ++++++++ .../local/local_email_draft_worker_queue.dart | 8 ++ .../data/model/local_email_draft.dart | 59 ++++++++------ .../local_email_draft_repository_impl.dart | 15 +--- .../local_email_draft_exception.dart | 1 + .../local_email_draft_repository.dart | 8 +- ...t => get_all_local_email_draft_state.dart} | 10 ++- .../get_all_local_email_draft_interactor.dart | 13 ++- .../bindings/mailbox_dashboard_bindings.dart | 4 + .../mailbox_dashboard_controller.dart | 10 +-- .../local_email_draft_extension.dart | 25 ++++++ .../reopen_composer_cache_extension.dart | 21 ----- .../reopen_local_email_draft_extension.dart | 17 ++++ .../model/presentation_local_email_draft.dart | 38 +++++++++ lib/main/bindings/local/local_bindings.dart | 6 ++ .../composer_controller_test.dart | 10 --- 26 files changed, 359 insertions(+), 170 deletions(-) create mode 100644 lib/features/caching/clients/local_email_draft_client.dart create mode 100644 lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart create mode 100644 lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart create mode 100644 lib/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart create mode 100644 lib/features/mailbox_dashboard/domain/exceptions/local_email_draft_exception.dart rename lib/features/mailbox_dashboard/domain/state/{get_composer_cache_state.dart => get_all_local_email_draft_state.dart} (51%) create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart delete mode 100644 lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart create mode 100644 lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart diff --git a/lib/features/caching/clients/local_email_draft_client.dart b/lib/features/caching/clients/local_email_draft_client.dart new file mode 100644 index 0000000000..cd0c828540 --- /dev/null +++ b/lib/features/caching/clients/local_email_draft_client.dart @@ -0,0 +1,9 @@ +import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart'; +import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; + +class LocalEmailDraftClient extends HiveCacheClient { + + @override + String get tableName => CachingConstants.localDraftEmailCacheBoxName; +} \ No newline at end of file diff --git a/lib/features/caching/config/hive_cache_config.dart b/lib/features/caching/config/hive_cache_config.dart index ea8df229ad..b5e00e1ab6 100644 --- a/lib/features/caching/config/hive_cache_config.dart +++ b/lib/features/caching/config/hive_cache_config.dart @@ -27,6 +27,7 @@ import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_cache.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_rights_cache.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_cache.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/recent_search_cache.dart'; import 'package:tmail_ui_user/features/offline_mode/model/attachment_hive_cache.dart'; import 'package:tmail_ui_user/features/offline_mode/model/detailed_email_hive_cache.dart'; @@ -192,6 +193,10 @@ class HiveCacheConfig { OidcConfigurationCacheAdapter(), CachingConstants.OIDC_CONFIGURATION_CACHE_ID, ); + registerCacheAdapter( + LocalEmailDraftAdapter(), + CachingConstants.LOCAL_EMAIL_DRAFT_CACHE_ID + ); } void registerCacheAdapter(TypeAdapter typeAdapter, int typeId) { diff --git a/lib/features/caching/utils/caching_constants.dart b/lib/features/caching/utils/caching_constants.dart index 4db4af99f5..96d1c2f934 100644 --- a/lib/features/caching/utils/caching_constants.dart +++ b/lib/features/caching/utils/caching_constants.dart @@ -20,6 +20,7 @@ class CachingConstants { static const int SENDING_EMAIL_HIVE_CACHE_ID = 18; static const int SESSION_HIVE_CACHE_ID = 19; static const int OIDC_CONFIGURATION_CACHE_ID = 20; + static const int LOCAL_EMAIL_DRAFT_CACHE_ID = 21; static const String fcmCacheBoxName = 'fcm_cache_box'; static const String newEmailCacheBoxName = 'new_email_cache_box'; @@ -28,6 +29,7 @@ class CachingConstants { static const String sessionCacheBoxName = 'session_cache_box'; static const String firebaseRegistrationCacheBoxName = 'firebase_registration_cache_box'; static const String oidcConfigurationCacheBoxName = 'oidc_configuration_cache_box'; + static const String localDraftEmailCacheBoxName = 'local_email_draft_cache_box'; static const String oidcConfigurationCacheKeyName = 'oidc_configuration_cache_key'; diff --git a/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart b/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart index e6b09bba93..0a4533e0d2 100644 --- a/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart +++ b/lib/features/composer/domain/usecases/save_local_email_draft_interactor.dart @@ -5,8 +5,8 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart'; import 'package:tmail_ui_user/features/composer/domain/state/save_local_email_draft_state.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/create_email_request_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; class SaveLocalEmailDraftInteractor { @@ -30,19 +30,12 @@ class SaveLocalEmailDraftInteractor { isDraft: true, ); await _localEmailDraftRepository.saveLocalEmailDraft( - accountId: accountId, - userName: userName, - composerCache: LocalEmailDraft( + createEmailRequest.generateLocalEmailDraftFromEmail( email: emailCreated, - hasRequestReadReceipt: createEmailRequest.hasRequestReadReceipt, - isMarkAsImportant: createEmailRequest.isMarkAsImportant, - displayMode: createEmailRequest.displayMode, - composerIndex: createEmailRequest.composerIndex, - composerId: createEmailRequest.composerId, - draftHash: createEmailRequest.savedDraftHash, - actionType: createEmailRequest.savedActionType, - draftEmailId: createEmailRequest.draftsEmailId, - )); + accountId: accountId, + userName: userName, + ), + ); return Right(SaveLocalEmailDraftSuccess()); } catch (exception) { return Left(SaveLocalEmailDraftFailure(exception)); diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart index 57719f9c9a..1dc89867ec 100644 --- a/lib/features/composer/presentation/composer_bindings.dart +++ b/lib/features/composer/presentation/composer_bindings.dart @@ -50,6 +50,8 @@ import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repositor import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_manager.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; @@ -145,6 +147,8 @@ class ComposerBindings extends BaseBindings { ), tag: composerId); Get.lazyPut(() => LocalEmailDraftDataSourceImpl( Get.find(), + Get.find(), + Get.find(), Get.find(), ), tag: composerId); } @@ -322,8 +326,6 @@ class ComposerBindings extends BaseBindings { Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), - Get.find(tag: composerId), - Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), Get.find(tag: composerId), diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index b78545b433..f955559f7a 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -54,6 +54,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/auto_cre import 'package:tmail_ui_user/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_message_failure_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_identities_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/sanitize_signature_in_email_content_extension.dart'; @@ -87,7 +88,6 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.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/open_and_close_composer_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; @@ -147,8 +147,6 @@ class ComposerController extends BaseController final GetEmailContentInteractor _getEmailContentInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final UploadController uploadController; - final RemoveLocalEmailDraftInteractor _removeLocalEmailDraftInteractor; - final SaveLocalEmailDraftInteractor _saveLocalEmailDraftInteractor; final DownloadImageAsBase64Interactor _downloadImageAsBase64Interactor; final TransformHtmlEmailContentInteractor _transformHtmlEmailContentInteractor; final GetServerSettingInteractor _getServerSettingInteractor; @@ -163,6 +161,7 @@ class ComposerController extends BaseController GetAutoCompleteInteractor? _getAutoCompleteInteractor; GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; RestoreEmailInlineImagesInteractor? restoreEmailInlineImagesInteractor; + SaveLocalEmailDraftInteractor? saveLocalEmailDraftInteractor; List listToEmailAddress = []; List listCcEmailAddress = []; @@ -249,8 +248,6 @@ class ComposerController extends BaseController this._getEmailContentInteractor, this._getAllIdentitiesInteractor, this.uploadController, - this._removeLocalEmailDraftInteractor, - this._saveLocalEmailDraftInteractor, this._downloadImageAsBase64Interactor, this._transformHtmlEmailContentInteractor, this._getServerSettingInteractor, @@ -272,6 +269,7 @@ class ComposerController extends BaseController richTextWebController = getBinding(tag: composerId); restoreEmailInlineImagesInteractor = getBinding(tag: composerId); menuMoreOptionController = CustomPopupMenuController(); + saveLocalEmailDraftInteractor = getBinding(tag: composerId); } else { richTextMobileTabletController = getBinding(tag: composerId); } @@ -397,16 +395,7 @@ class ComposerController extends BaseController @override Future onUnloadBrowserListener(html.Event event) async { - final username = mailboxDashBoardController.sessionCurrent?.username; - final accountId = mailboxDashBoardController.accountId.value; - if (composerId != null && username != null && accountId != null) { - await _removeLocalEmailDraftInteractor.execute( - accountId, - username, - composerId!, - ); - } - await _saveLocalEmailDraftAction(); + await saveLocalEmailDraftAction(); } void _listenStreamEvent() { @@ -484,7 +473,7 @@ class ComposerController extends BaseController log('ComposerController::_generateCreateEmailRequest: SESSION or ACCOUNT_ID or ARGUMENTS is NULL'); return null; } - + String emailContent = await getContentInEditor(); if (currentEmailActionType == EmailActionType.compose) { emailContent = await _composerRepository.removeCollapsedExpandedSignatureEffect( @@ -496,7 +485,7 @@ class ComposerController extends BaseController final composerIndex = composerId != null ? mailboxDashBoardController.composerManager.getComposerIndex(composerId!) : null; - + return CreateEmailRequest( session: session, accountId: accountId, @@ -866,7 +855,7 @@ class ComposerController extends BaseController } final emailContent = await getContentInEditor(); - final uploadUri = _getUploadUriFromSession(session, accountId); + final uploadUri = getUploadUriFromSession(session, accountId); final cancelToken = CancelToken(); final resultState = await _showSendingMessageDialog( session: session, @@ -1184,7 +1173,7 @@ class ComposerController extends BaseController } final emailContent = await getContentInEditor(); - final uploadUri = _getUploadUriFromSession(session, accountId); + final uploadUri = getUploadUriFromSession(session, accountId); final cancelToken = CancelToken(); final resultState = await _showSavingMessageToDraftsDialog( session: session, @@ -1897,7 +1886,7 @@ class ComposerController extends BaseController popBack(); final emailContent = await getContentInEditor(); - final uploadUri = _getUploadUriFromSession(session, accountId); + final uploadUri = getUploadUriFromSession(session, accountId); final draftEmailId = getDraftEmailId(); log('ComposerController::_handleSaveMessageToDraft: draftEmailId = $draftEmailId'); final cancelToken = CancelToken(); @@ -2039,11 +2028,7 @@ class ComposerController extends BaseController @override Future onBeforeReconnect() async { - if (mailboxDashBoardController.accountId.value != null && - mailboxDashBoardController.sessionCurrent?.username != null - ) { - await _saveLocalEmailDraftAction(); - } + await saveLocalEmailDraftAction(); } void _setUpMaxWidthInlineImage({ diff --git a/lib/features/composer/presentation/extensions/create_email_request_extension.dart b/lib/features/composer/presentation/extensions/create_email_request_extension.dart index cc5adc2617..b916998fea 100644 --- a/lib/features/composer/presentation/extensions/create_email_request_extension.dart +++ b/lib/features/composer/presentation/extensions/create_email_request_extension.dart @@ -1,5 +1,7 @@ import 'package:core/core.dart'; import 'package:http_parser/http_parser.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart'; @@ -9,14 +11,18 @@ import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/email/mail_priority_header.dart'; +import 'package:model/extensions/account_id_extensions.dart'; import 'package:model/extensions/email_address_extension.dart'; +import 'package:model/extensions/email_extension.dart'; import 'package:model/extensions/session_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/identity_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart'; import 'package:tmail_ui_user/main/localizations/localization_service.dart'; @@ -202,4 +208,21 @@ extension CreateEmailRequestExtension on CreateEmailRequest { createMailboxRequest() ); } + + LocalEmailDraft generateLocalEmailDraftFromEmail({ + required Email email, + required AccountId accountId, + required UserName userName, + }) { + return LocalEmailDraft( + id: TupleKey(composerId!, accountId.asString, userName.value).encodeKey, + composerId: composerId!, + savedTime: DateTime.now(), + email: email.asString(), + hasRequestReadReceipt: hasRequestReadReceipt, + isMarkAsImportant: isMarkAsImportant, + displayMode: displayMode.name, + composerIndex: composerIndex, + ); + } } \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart new file mode 100644 index 0000000000..9175da8aba --- /dev/null +++ b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart @@ -0,0 +1,81 @@ + +import 'package:core/utils/app_logger.dart'; +import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/auto_create_tag_for_recipients_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; + +extension HandleLocalEmailDraftExtension on ComposerController { + + Future generateCreateEmailRequest() async { + final arguments = composerArguments.value; + final session = mailboxDashBoardController.sessionCurrent; + final accountId = mailboxDashBoardController.accountId.value; + + if (arguments == null || session == null || accountId == null) { + log('HandleLocalEmailDraftExtension::generateCreateEmailRequest: SESSION or ACCOUNT_ID or ARGUMENTS is NULL'); + return null; + } + + final emailContent = await getContentInEditor(); + final uploadUri = getUploadUriFromSession(session, accountId); + + final composerIndex = composerId != null + ? mailboxDashBoardController.composerManager.getComposerIndex(composerId!) + : null; + + return CreateEmailRequest( + session: session, + accountId: accountId, + emailActionType: arguments.emailActionType, + subject: subjectEmail.value ?? '', + emailContent: emailContent, + fromSender: arguments.presentationEmail?.from ?? {}, + toRecipients: listToEmailAddress.toSet(), + ccRecipients: listCcEmailAddress.toSet(), + bccRecipients: listBccEmailAddress.toSet(), + replyToRecipients: listReplyToEmailAddress.toSet(), + hasRequestReadReceipt: hasRequestReadReceipt.value, + isMarkAsImportant: isMarkAsImportant.value, + identity: identitySelected.value, + attachments: uploadController.attachmentsUploaded, + inlineAttachments: uploadController.mapInlineAttachments, + outboxMailboxId: getOutboxMailboxIdForComposer(), + sentMailboxId: getSentMailboxIdForComposer(), + draftsMailboxId: getDraftMailboxIdForComposer(), + draftsEmailId: getDraftEmailId(), + answerForwardEmailId: arguments.presentationEmail?.id, + unsubscribeEmailId: arguments.previousEmailId, + messageId: arguments.messageId, + references: arguments.references, + emailSendingQueue: arguments.sendingEmail, + displayMode: screenDisplayMode.value, + uploadUri: uploadUri, + composerIndex: composerIndex, + composerId: composerId, + ); + } + + Future saveLocalEmailDraftAction() async { + final username = mailboxDashBoardController.sessionCurrent?.username; + final accountId = mailboxDashBoardController.accountId.value; + + if (username == null || + accountId == null || + saveLocalEmailDraftInteractor == null) return; + + autoCreateEmailTag(); + + final createEmailRequest = await generateCreateEmailRequest(); + if (createEmailRequest == null) return; + + await saveLocalEmailDraftInteractor!.execute( + createEmailRequest, + accountId, + username, + ); + } + +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart index 5e58a24290..caca42ab05 100644 --- a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart +++ b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart @@ -4,13 +4,9 @@ import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; abstract class LocalEmailDraftDatasource { - Future saveLocalEmailDraft({ - required AccountId accountId, - required UserName userName, - required LocalEmailDraft composerCache, - }); + Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft); - Future> getLocalEmailDraft( + Future> getAllLocalEmailDraft( AccountId accountId, UserName userName); diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart index e1f836fd87..6b1a200f79 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; -import 'package:core/domain/exceptions/web_session_exception.dart'; import 'package:core/presentation/utils/html_transformer/html_transform.dart'; import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; @@ -8,58 +6,47 @@ import 'package:model/email/email_action_type.dart'; import 'package:model/extensions/account_id_extensions.dart'; import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_manager.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/offline_mode/hive_worker/hive_task.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; import 'package:universal_html/html.dart' as html; class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { - LocalEmailDraftDataSourceImpl(this._htmlTransform, this._exceptionThrower); final HtmlTransform _htmlTransform; + final LocalEmailDraftManager _localEmailDraftManager; + final LocalEmailDraftWorkerQueue _localEmailDraftWorkerQueue; final ExceptionThrower _exceptionThrower; + LocalEmailDraftDataSourceImpl( + this._htmlTransform, + this._localEmailDraftManager, + this._localEmailDraftWorkerQueue, + this._exceptionThrower, + ); + @override - Future> getLocalEmailDraft( + Future> getAllLocalEmailDraft( AccountId accountId, UserName userName - ) async { + ) { return Future.sync(() async { - final keyWithIdentity = TupleKey( - EmailActionType.reopenComposerBrowser.name, - accountId.asString, - userName.value).toString(); - - final listEntries = html.window.sessionStorage.entries.where( - (entry) => entry.key.startsWith(keyWithIdentity), - ); - - if (listEntries.isNotEmpty) { - return listEntries - .map((entry) => LocalEmailDraft.fromJson(jsonDecode(entry.value))) - .toList(); - } else { - throw NotFoundInWebSessionException(); - } + return await _localEmailDraftManager.getAllLocalEmailDraft(accountId, userName); }).catchError(_exceptionThrower.throwException); } @override - Future saveLocalEmailDraft({ - required AccountId accountId, - required UserName userName, - required LocalEmailDraft composerCache, - }) async { - return Future.sync(() { - final composerCacheKey = TupleKey( - EmailActionType.reopenComposerBrowser.name, - accountId.asString, - userName.value, - composerCache.composerId, - ).toString(); - Map entries = { - composerCacheKey: jsonEncode(composerCache.toJson()) - }; - html.window.sessionStorage.addAll(entries); + Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft) { + return Future.sync(() async { + final task = HiveTask( + id: localEmailDraft.id, + runnable: () async { + return await _localEmailDraftManager.saveLocalEmailDraft(localEmailDraft); + }, + ); + return _localEmailDraftWorkerQueue.addTask(task); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart new file mode 100644 index 0000000000..2453e678bd --- /dev/null +++ b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart @@ -0,0 +1,35 @@ + +import 'package:core/utils/app_logger.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'; +import 'package:tmail_ui_user/features/caching/clients/local_email_draft_client.dart'; +import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/local_email_draft_exception.dart'; + +class LocalEmailDraftManager { + + final LocalEmailDraftClient _localEmailDraftClient; + + LocalEmailDraftManager(this._localEmailDraftClient); + + Future> getAllLocalEmailDraft(AccountId accountId, UserName userName) async { + final nestedKey = TupleKey(accountId.asString, userName.value).encodeKey; + final listLocalEmailDraft = await _localEmailDraftClient.getListByNestedKey(nestedKey); + + if (listLocalEmailDraft.isEmpty) { + throw NotFoundLocalEmailDraftException(); + } + + return listLocalEmailDraft; + } + + Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft) async { + log('LocalEmailDraftManager::saveLocalEmailDraft: ID = ${localEmailDraft.id}'); + await _localEmailDraftClient.insertItem( + localEmailDraft.id, + localEmailDraft, + ); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart b/lib/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart new file mode 100644 index 0000000000..4ea55c3896 --- /dev/null +++ b/lib/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart @@ -0,0 +1,8 @@ + +import 'package:tmail_ui_user/features/offline_mode/hive_worker/hive_worker_queue.dart'; + +class LocalEmailDraftWorkerQueue extends WorkerQueue { + + @override + String get workerName => 'LocalEmailDraft'; +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/model/local_email_draft.dart b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart index 0c40cade81..be52239b28 100644 --- a/lib/features/mailbox_dashboard/data/model/local_email_draft.dart +++ b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart @@ -1,4 +1,6 @@ import 'package:equatable/equatable.dart'; +import 'package:hive/hive.dart'; +import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart'; import 'package:jmap_dart_client/http/converter/email_id_nullable_converter.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -7,49 +9,60 @@ import 'package:tmail_ui_user/features/composer/presentation/model/screen_displa part 'local_email_draft.g.dart'; -@JsonSerializable( - explicitToJson: true, - includeIfNull: false, - converters: [ - EmailIdNullableConverter(), - ] -) +@HiveType(typeId: CachingConstants.LOCAL_EMAIL_DRAFT_CACHE_ID) class LocalEmailDraft with EquatableMixin { - final String? id; - final DateTime? timeStamp; - final Email? email; + @HiveField(0) + final String id; + + @HiveField(1) + final String composerId; + + @HiveField(2) + final DateTime savedTime; + + @HiveField(3) + final String? email; + + @HiveField(4) final bool? hasRequestReadReceipt; + + @HiveField(5) final bool? isMarkAsImportant; - final ScreenDisplayMode displayMode; + + @HiveField(6) + final String? displayMode; + + @HiveField(7) final int? composerIndex; - final String? composerId; + + @HiveField(8) final int? draftHash; - final EmailActionType? actionType; - final EmailId? draftEmailId; + + @HiveField(9) + final String? actionType; + + @HiveField(10) + final String? draftEmailId; LocalEmailDraft({ - this.id, - this.timeStamp, + required this.id, + required this.composerId, + required this.savedTime, this.email, this.hasRequestReadReceipt, this.isMarkAsImportant, - this.displayMode = ScreenDisplayMode.normal, + this.displayMode, this.composerIndex, - this.composerId, this.draftHash, this.actionType, this.draftEmailId, }); - factory LocalEmailDraft.fromJson(Map json) => _$LocalEmailDraftFromJson(json); - - Map toJson() => _$LocalEmailDraftToJson(this); - @override List get props => [ id, - timeStamp, + savedTime, email, hasRequestReadReceipt, isMarkAsImportant, diff --git a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart index 1d5660323f..ccf7f832df 100644 --- a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart +++ b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart @@ -12,11 +12,11 @@ class LocalEmailDraftRepositoryImpl extends LocalEmailDraftRepository { LocalEmailDraftRepositoryImpl(this._localEmailDraftDatasource); @override - Future> getLocalEmailDraft( + Future> getAllLocalEmailDraft( AccountId accountId, UserName userName ) { - return _localEmailDraftDatasource.getLocalEmailDraft(accountId, userName); + return _localEmailDraftDatasource.getAllLocalEmailDraft(accountId, userName); } @override @@ -30,15 +30,8 @@ class LocalEmailDraftRepositoryImpl extends LocalEmailDraftRepository { } @override - Future saveLocalEmailDraft({ - required AccountId accountId, - required UserName userName, - required LocalEmailDraft composerCache, - }) { - return _localEmailDraftDatasource.saveLocalEmailDraft( - accountId: accountId, - userName: userName, - composerCache: composerCache); + Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft) { + return _localEmailDraftDatasource.saveLocalEmailDraft(localEmailDraft); } @override diff --git a/lib/features/mailbox_dashboard/domain/exceptions/local_email_draft_exception.dart b/lib/features/mailbox_dashboard/domain/exceptions/local_email_draft_exception.dart new file mode 100644 index 0000000000..e39087cd60 --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/exceptions/local_email_draft_exception.dart @@ -0,0 +1 @@ +class NotFoundLocalEmailDraftException implements Exception {} diff --git a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart index 81376c12f0..698c584f0a 100644 --- a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart +++ b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart @@ -4,13 +4,9 @@ import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; abstract class LocalEmailDraftRepository { - Future saveLocalEmailDraft({ - required AccountId accountId, - required UserName userName, - required LocalEmailDraft composerCache, - }); + Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft); - Future> getLocalEmailDraft( + Future> getAllLocalEmailDraft( AccountId accountId, UserName userName); diff --git a/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart b/lib/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart similarity index 51% rename from lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart rename to lib/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart index 32f560cfb1..47f2e1672c 100644 --- a/lib/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart +++ b/lib/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart @@ -2,17 +2,19 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; -class GetLocalEmailDraftSuccess extends UIState { +class GetAllLocalEmailDraftLoading extends LoadingState {} + +class GetAllLocalEmailDraftSuccess extends UIState { final List listLocalEmailDraft; - GetLocalEmailDraftSuccess(this.listLocalEmailDraft); + GetAllLocalEmailDraftSuccess(this.listLocalEmailDraft); @override List get props => [listLocalEmailDraft]; } -class GetLocalEmailDraftFailure extends FeatureFailure { +class GetAllLocalEmailDraftFailure extends FeatureFailure { - GetLocalEmailDraftFailure(dynamic exception) : super(exception: exception); + GetAllLocalEmailDraftFailure(dynamic exception) : super(exception: exception); } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart index 59f5361fab..4ee4ae393c 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart @@ -4,7 +4,7 @@ import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart'; class GetAllLocalEmailDraftInteractor { final LocalEmailDraftRepository _localEmailDraftRepository; @@ -13,13 +13,12 @@ class GetAllLocalEmailDraftInteractor { Stream> execute(AccountId accountId, UserName userName) async* { try { - final listLocalEmailDraft = await _localEmailDraftRepository.getLocalEmailDraft( - accountId, - userName, - ); - yield Right(GetLocalEmailDraftSuccess(listLocalEmailDraft)); + yield Right(GetAllLocalEmailDraftLoading()); + final listLocalEmailDraft = await _localEmailDraftRepository + .getAllLocalEmailDraft(accountId, userName); + yield Right(GetAllLocalEmailDraftSuccess(listLocalEmailDraft)); } catch (exception) { - yield Left(GetLocalEmailDraftFailure(exception)); + yield Left(GetAllLocalEmailDraftFailure(exception)); } } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart index da911c5849..fd4a34a4a9 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -65,6 +65,8 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/lo import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_manager.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_spam_report_manager.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/app_grid_repository_impl.dart'; @@ -258,6 +260,8 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find())); Get.lazyPut(() => LocalEmailDraftDataSourceImpl( Get.find(), + Get.find(), + Get.find(), Get.find())); Get.lazyPut(() => LocalSpamReportDataSourceImpl( Get.find(), 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 130195e8ae..9d69c36fba 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -89,7 +89,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentat import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_report_exception.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; @@ -103,7 +103,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/delete_emails_in_mailbox_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/open_and_close_composer_extension.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/user_setting_popup_menu_mixin.dart'; @@ -436,8 +436,8 @@ class MailboxDashBoardController extends ReloadableController _handleGetRestoredDeletedMessageSuccess(success); } else if (success is GetAllIdentitiesSuccess) { _handleGetAllIdentitiesSuccess(success); - } else if (success is GetLocalEmailDraftSuccess) { - handleGetLocalEmailDraftSuccess(success); + } else if (success is GetAllLocalEmailDraftSuccess) { + handleGetAllLocalEmailDraftSuccess(success); } else if (success is GetIdentityCacheOnWebSuccess) { goToSettings(); } else if (success is MarkAsStarEmailSuccess) { @@ -477,7 +477,7 @@ class MailboxDashBoardController extends ReloadableController _handleEmptyTrashFolderFailure(failure); } else if (failure is MoveMultipleEmailToMailboxFailure) { toastManager.showMessageFailure(failure); - } else if (failure is GetLocalEmailDraftFailure) { + } else if (failure is GetAllLocalEmailDraftFailure) { _handleIdentityCache(); } else if (failure is GetServerSettingFailure) { isSenderImportantFlagEnabled.value = true; diff --git a/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart new file mode 100644 index 0000000000..6664eac54c --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart @@ -0,0 +1,25 @@ + +import 'dart:convert'; + +import 'package:collection/collection.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; + +extension LocalEmailDraftExtension on LocalEmailDraft { + PresentationLocalEmailDraft toPresentation() { + return PresentationLocalEmailDraft( + id: id, + composerId: composerId, + savedTime: savedTime, + email: email != null ? Email.fromJson(jsonDecode(email!)) : null, + hasRequestReadReceipt: hasRequestReadReceipt, + isMarkAsImportant: isMarkAsImportant, + displayMode: ScreenDisplayMode.values.firstWhereOrNull( + (type) => type.name == displayMode, + ), + composerIndex: composerIndex, + ); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart deleted file mode 100644 index 9a92658d99..0000000000 --- a/lib/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart +++ /dev/null @@ -1,21 +0,0 @@ - -import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.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/open_and_close_composer_extension.dart'; - -extension ReopenLocalEmailDraftExtension on MailboxDashBoardController { - - void handleGetLocalEmailDraftSuccess(GetLocalEmailDraftSuccess success) { - removeAllLocalEmailDraft(); - - final listLocalEmailDraftSortByIndex = success.listLocalEmailDraft - ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); - - final listArguments = listLocalEmailDraftSortByIndex - .map((composerCache) => ComposerArguments.fromSessionStorageBrowser(composerCache)) - .toList(); - - openListComposer(listArguments); - } -} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart new file mode 100644 index 0000000000..081926a843 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart @@ -0,0 +1,17 @@ + +import 'package:core/utils/app_logger.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.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/local_email_draft_extension.dart'; + +extension ReopenLocalEmailDraftExtension on MailboxDashBoardController { + + void handleGetAllLocalEmailDraftSuccess(GetAllLocalEmailDraftSuccess success) { + final listPresentationLocalEmailDraft = success.listLocalEmailDraft + .map((localEmailDraft) => localEmailDraft.toPresentation()) + .toList(); + final listLocalEmailDraftSortByIndex = listPresentationLocalEmailDraft + ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); + log('ReopenLocalEmailDraftExtension::handleGetAllLocalEmailDraftSuccess:listLocalEmailDraftSortByIndex_length = ${listLocalEmailDraftSortByIndex.length}'); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart new file mode 100644 index 0000000000..5300f22fcd --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart @@ -0,0 +1,38 @@ +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; + +class PresentationLocalEmailDraft with EquatableMixin { + + final String id; + final String composerId; + final DateTime savedTime; + final Email? email; + final bool? hasRequestReadReceipt; + final bool? isMarkAsImportant; + final ScreenDisplayMode? displayMode; + final int? composerIndex; + + PresentationLocalEmailDraft({ + required this.id, + required this.composerId, + required this.savedTime, + this.email, + this.hasRequestReadReceipt, + this.isMarkAsImportant, + this.displayMode, + this.composerIndex, + }); + + @override + List get props => [ + id, + savedTime, + email, + hasRequestReadReceipt, + isMarkAsImportant, + displayMode, + composerIndex, + composerId, + ]; +} diff --git a/lib/main/bindings/local/local_bindings.dart b/lib/main/bindings/local/local_bindings.dart index c44ecf98a7..c2f2333596 100644 --- a/lib/main/bindings/local/local_bindings.dart +++ b/lib/main/bindings/local/local_bindings.dart @@ -11,6 +11,7 @@ import 'package:tmail_ui_user/features/caching/clients/encryption_key_cache_clie import 'package:tmail_ui_user/features/caching/clients/fcm_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/hive_cache_version_client.dart'; +import 'package:tmail_ui_user/features/caching/clients/local_email_draft_client.dart'; import 'package:tmail_ui_user/features/caching/clients/mailbox_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/new_email_hive_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/oidc_configuration_cache_client.dart'; @@ -32,6 +33,8 @@ import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_manager.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_spam_report_manager.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/new_email_cache_manager.dart'; @@ -90,6 +93,8 @@ class LocalBindings extends Bindings { Get.put(SendingEmailCacheManager(Get.find())); Get.put(SessionHiveCacheClient()); Get.put(LocalSpamReportManager(Get.find())); + Get.put(LocalEmailDraftClient()); + Get.put(LocalEmailDraftManager(Get.find())); Get.put(CachingManager( Get.find(), Get.find(), @@ -118,6 +123,7 @@ class LocalBindings extends Bindings { void _bindingWorkerQueue() { Get.put(NewEmailCacheWorkerQueue()); Get.put(OpenedEmailCacheWorkerQueue()); + Get.put(LocalEmailDraftWorkerQueue()); } void _bindingKeychainSharing() { diff --git a/test/features/composer/presentation/composer_controller_test.dart b/test/features/composer/presentation/composer_controller_test.dart index baa3519599..6777162f3f 100644 --- a/test/features/composer/presentation/composer_controller_test.dart +++ b/test/features/composer/presentation/composer_controller_test.dart @@ -32,7 +32,6 @@ import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/save_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; @@ -48,7 +47,6 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; 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/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; @@ -151,8 +149,6 @@ class MockMailboxDashBoardController extends Mock implements MailboxDashBoardCon MockSpec(), MockSpec(), MockSpec(fallbackGenerators: fallbackGenerators), - MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -195,8 +191,6 @@ void main() { late MockGetEmailContentInteractor mockGetEmailContentInteractor; late MockGetAllIdentitiesInteractor mockGetAllIdentitiesInteractor; late MockUploadController mockUploadController; - late MockRemoveLocalEmailDraftInteractor mockRemoveLocalEmailDraftInteractor; - late MockSaveLocalEmailDraftInteractor mockSaveLocalEmailDraftInteractor; late MockDownloadImageAsBase64Interactor mockDownloadImageAsBase64Interactor; late MockTransformHtmlEmailContentInteractor mockTransformHtmlEmailContentInteractor; late MockGetServerSettingInteractor mockGetServerSettingInteractor; @@ -264,8 +258,6 @@ void main() { mockGetEmailContentInteractor = MockGetEmailContentInteractor(); mockGetAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); mockUploadController = MockUploadController(); - mockRemoveLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); - mockSaveLocalEmailDraftInteractor = MockSaveLocalEmailDraftInteractor(); mockDownloadImageAsBase64Interactor = MockDownloadImageAsBase64Interactor(); mockTransformHtmlEmailContentInteractor = MockTransformHtmlEmailContentInteractor(); mockGetServerSettingInteractor = MockGetServerSettingInteractor(); @@ -280,8 +272,6 @@ void main() { mockGetEmailContentInteractor, mockGetAllIdentitiesInteractor, mockUploadController, - mockRemoveLocalEmailDraftInteractor, - mockSaveLocalEmailDraftInteractor, mockDownloadImageAsBase64Interactor, mockTransformHtmlEmailContentInteractor, mockGetServerSettingInteractor, From afca9e78cc8b0a99b014bc6f6467cd6b1896860d Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 25 Mar 2025 17:43:10 +0700 Subject: [PATCH 03/10] TF-3358 Show list draft locally dialog Signed-off-by: dab246 --- .../base/widget/email_avatar_builder.dart | 12 +- .../presentation/composer_controller.dart | 2 +- ...formation_sender_and_receiver_builder.dart | 5 +- .../data/local/local_email_draft_manager.dart | 2 - .../mailbox_dashboard_controller.dart | 4 +- ...sentation_local_email_draft_extension.dart | 64 ++++++ .../reopen_local_email_draft_extension.dart | 17 -- .../restore_local_email_draft_extension.dart | 33 +++ .../local_email_draft_item_widget.dart | 183 ++++++++++++++++ ...local_email_draft_list_dialog_builder.dart | 203 ++++++++++++++++++ lib/l10n/intl_messages.arb | 18 ++ lib/main/localizations/app_localizations.dart | 21 ++ 12 files changed, 535 insertions(+), 29 deletions(-) create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/presentation_local_email_draft_extension.dart delete mode 100644 lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart create mode 100644 lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart create mode 100644 lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart diff --git a/lib/features/base/widget/email_avatar_builder.dart b/lib/features/base/widget/email_avatar_builder.dart index cddbfc6edd..9f847e7365 100644 --- a/lib/features/base/widget/email_avatar_builder.dart +++ b/lib/features/base/widget/email_avatar_builder.dart @@ -3,26 +3,26 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/views/image/avatar_builder.dart'; import 'package:flutter/material.dart'; -import 'package:model/email/presentation_email.dart'; -import 'package:model/extensions/presentation_email_extension.dart'; class EmailAvatarBuilder extends StatelessWidget { - final PresentationEmail emailSelected; + final String avatarText; + final List? avatarColors; const EmailAvatarBuilder({ Key? key, - required this.emailSelected + required this.avatarText, + this.avatarColors, }) : super(key: key); @override Widget build(BuildContext context) { return (AvatarBuilder() - ..text(emailSelected.getAvatarText()) + ..text(avatarText) ..size(50) ..addTextStyle(ThemeUtils.textStyleHeadingH4(color: Colors.white)) ..backgroundColor(AppColor.colorAvatar) - ..avatarColor(emailSelected.avatarColors)) + ..avatarColor(avatarColors)) .build(); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index f955559f7a..5325bb086f 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -394,7 +394,7 @@ class ComposerController extends BaseController } @override - Future onUnloadBrowserListener(html.Event event) async { + Future onBeforeUnloadBrowserListener(html.Event event) async { await saveLocalEmailDraftAction(); } diff --git a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart index 50777bea8e..609ad5d7dd 100644 --- a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart +++ b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart @@ -48,7 +48,10 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { ? CrossAxisAlignment.start : CrossAxisAlignment.center, children: [ - EmailAvatarBuilder(emailSelected: emailSelected), + EmailAvatarBuilder( + avatarText: emailSelected.getAvatarText(), + avatarColors: emailSelected.avatarColors, + ), const SizedBox(width: 16), Expanded(child: LayoutBuilder(builder: (context, constraints) { return Transform( diff --git a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart index 2453e678bd..9bd62e695d 100644 --- a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart +++ b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart @@ -1,5 +1,4 @@ -import 'package:core/utils/app_logger.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'; @@ -26,7 +25,6 @@ class LocalEmailDraftManager { } Future saveLocalEmailDraft(LocalEmailDraft localEmailDraft) async { - log('LocalEmailDraftManager::saveLocalEmailDraft: ID = ${localEmailDraft.id}'); await _localEmailDraftClient.insertItem( localEmailDraft.id, localEmailDraft, 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 9d69c36fba..a53ba8bb75 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -103,7 +103,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/delete_emails_in_mailbox_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/open_and_close_composer_extension.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/user_setting_popup_menu_mixin.dart'; @@ -437,7 +437,7 @@ class MailboxDashBoardController extends ReloadableController } else if (success is GetAllIdentitiesSuccess) { _handleGetAllIdentitiesSuccess(success); } else if (success is GetAllLocalEmailDraftSuccess) { - handleGetAllLocalEmailDraftSuccess(success); + restoreLocalEmailDraft(success.listLocalEmailDraft); } else if (success is GetIdentityCacheOnWebSuccess) { goToSettings(); } else if (success is MarkAsStarEmailSuccess) { diff --git a/lib/features/mailbox_dashboard/presentation/extensions/presentation_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/presentation_local_email_draft_extension.dart new file mode 100644 index 0000000000..8999f5d9d3 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/presentation_local_email_draft_extension.dart @@ -0,0 +1,64 @@ + +import 'dart:ui'; + +import 'package:core/domain/extensions/datetime_extension.dart'; +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/extensions/string_extension.dart'; +import 'package:flutter_date_range_picker/flutter_date_range_picker.dart'; +import 'package:model/extensions/email_address_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; + +extension PresentationLocalEmailDraftExtension on PresentationLocalEmailDraft { + + String get avatarText { + final recipientName = firstRecipientName; + if (recipientName.isNotEmpty) { + return recipientName.firstCharacterToUpperCase; + } + return '?'; + } + + List get avatarColors { + if (email?.from?.isNotEmpty == true) { + return email!.from!.first.avatarColors; + } else { + return AppColor.mapGradientColor.first; + } + } + + String get firstRecipientName { + if (email?.to?.isNotEmpty == true) { + return email!.to!.first.asString(); + } if (email?.cc?.isNotEmpty == true) { + return email!.cc!.first.asString(); + } if (email?.bcc?.isNotEmpty == true) { + return email!.bcc!.first.asString(); + } else { + return senderName; + } + } + + String get senderName { + if (email?.from?.isNotEmpty == true) { + return email!.from!.first.asString(); + } else { + return ''; + } + } + + String get emailSubject => email?.subject?.trim() ?? ''; + + String get emailContent { + if (email?.bodyValues?.isNotEmpty == true) { + return email?.bodyValues?.values.first.value ?? ''; + } else { + return ''; + } + } + + bool get hasAttachment => email?.attachments?.isNotEmpty == true; + + String getSavedTime(String locale) { + return DateFormat(savedTime.toPattern(), locale).format(savedTime); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart deleted file mode 100644 index 081926a843..0000000000 --- a/lib/features/mailbox_dashboard/presentation/extensions/reopen_local_email_draft_extension.dart +++ /dev/null @@ -1,17 +0,0 @@ - -import 'package:core/utils/app_logger.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.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/local_email_draft_extension.dart'; - -extension ReopenLocalEmailDraftExtension on MailboxDashBoardController { - - void handleGetAllLocalEmailDraftSuccess(GetAllLocalEmailDraftSuccess success) { - final listPresentationLocalEmailDraft = success.listLocalEmailDraft - .map((localEmailDraft) => localEmailDraft.toPresentation()) - .toList(); - final listLocalEmailDraftSortByIndex = listPresentationLocalEmailDraft - ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); - log('ReopenLocalEmailDraftExtension::handleGetAllLocalEmailDraftSuccess:listLocalEmailDraftSortByIndex_length = ${listLocalEmailDraftSortByIndex.length}'); - } -} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart new file mode 100644 index 0000000000..7d32559ba8 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -0,0 +1,33 @@ + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:get/get.dart'; +import 'package:pointer_interceptor/pointer_interceptor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.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/local_email_draft_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart'; + +extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { + + void restoreLocalEmailDraft(List localEmailDrafts) { + final listPresentationLocalEmailDraft = localEmailDrafts + .map((localEmailDraft) => localEmailDraft.toPresentation()) + .toList(); + final listLocalEmailDraftSortByIndex = listPresentationLocalEmailDraft + ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); + + showLocalEmailDraftListDialog(listLocalEmailDraftSortByIndex); + } + + void showLocalEmailDraftListDialog(List presentationLocalEmailDrafts) { + Get.dialog( + PointerInterceptor( + child: LocalEmailDraftListDialogBuilder( + presentationLocalEmailDrafts: presentationLocalEmailDrafts, + ), + ), + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + ); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart new file mode 100644 index 0000000000..6c03366234 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart @@ -0,0 +1,183 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:tmail_ui_user/features/base/widget/email_avatar_builder.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/presentation_local_email_draft_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnSelectLocalEmailDraftAction = void Function( + PresentationLocalEmailDraft); + +class LocalEmailDraftItemWidget extends StatelessWidget { + final PresentationLocalEmailDraft draftLocal; + final bool isOldest; + final ImagePaths imagePaths; + final OnSelectLocalEmailDraftAction? onSelectLocalEmailDraftAction; + + const LocalEmailDraftItemWidget({ + super.key, + required this.draftLocal, + required this.imagePaths, + required this.isOldest, + this.onSelectLocalEmailDraftAction, + }); + + @override + Widget build(BuildContext context) { + return Material( + type: MaterialType.transparency, + child: InkWell( + onTap: () => onSelectLocalEmailDraftAction?.call(draftLocal), + child: Padding( + padding: EdgeInsetsDirectional.only( + start: 12, + end: 12, + top: 12, + bottom: isOldest ? 12 : 0, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + EmailAvatarBuilder( + avatarText: draftLocal.avatarText, + avatarColors: draftLocal.avatarColors, + ), + const SizedBox(width: 12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Expanded( + child: Text( + draftLocal.firstRecipientName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.black), + ), + ), + if (draftLocal.isMarkAsImportant == true) + SvgPicture.asset( + imagePaths.icMarkAsImportant, + width: 20, + height: 20, + fit: BoxFit.fill, + colorFilter: AppColor.steelGray200.asFilter(), + ), + if (draftLocal.hasAttachment) + Padding( + padding: const EdgeInsetsDirectional.only(start: 8), + child: SvgPicture.asset( + imagePaths.icAttachment, + width: 16, + height: 16, + colorFilter: AppColor.steelGray200.asFilter(), + fit: BoxFit.fill, + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.only(end: 4, start: 8), + child: Text( + draftLocal.getSavedTime( + Localizations.localeOf(context).toLanguageTag()), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColor.steelGray400), + ), + ), + ]), + if (draftLocal.emailSubject.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 2), + child: Text( + draftLocal.emailSubject, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColor.steelGray400), + ), + ), + if (draftLocal.emailContent.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 2), + child: Text( + draftLocal.emailContent, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColor.steelGray400), + ), + ), + const SizedBox(height: 12), + Row( + children: [ + Flexible( + child: TMailButtonWidget( + text: AppLocalizations.of(context).edit, + textStyle: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColor.primaryColor, fontSize: 12), + maxLines: 1, + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), + margin: const EdgeInsetsDirectional.only(end: 8), + onTapActionCallback: () {}, + ), + ), + Flexible( + child: TMailButtonWidget( + text: AppLocalizations.of(context).saveAsDraft, + textStyle: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.black, fontSize: 12), + maxLines: 1, + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), + margin: const EdgeInsetsDirectional.only(end: 8), + onTapActionCallback: () {}, + ), + ), + Flexible( + child: TMailButtonWidget( + text: AppLocalizations.of(context).discard, + textStyle: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColor.colorActionDeleteConfirmDialog, fontSize: 12), + maxLines: 1, + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), + margin: const EdgeInsetsDirectional.only(end: 8), + onTapActionCallback: () {}, + ), + ), + ], + ), + if (!isOldest) + const Padding( + padding: EdgeInsets.only(top: 12), + child: Divider(color: AppColor.colorDivider, height: 0.5)), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart new file mode 100644 index 0000000000..a15e438363 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -0,0 +1,203 @@ +import 'dart:ui'; + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; + +class LocalEmailDraftListDialogBuilder extends StatefulWidget { + final List presentationLocalEmailDrafts; + + const LocalEmailDraftListDialogBuilder({ + super.key, + required this.presentationLocalEmailDrafts, + }); + + @override + State createState() => + _LocalEmailDraftListDialogBuilderState(); +} + +class _LocalEmailDraftListDialogBuilderState + extends State { + static const double _maxHeight = 656.0; + static const double _maxWidth = 556.0; + + late final ResponsiveUtils _responsiveUtils; + late final ImagePaths _imagePaths; + late final ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _responsiveUtils = Get.find(); + _imagePaths = Get.find(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: _getBorderRadius(context), + ), + insetPadding: _getMargin(context), + alignment: Alignment.center, + backgroundColor: Colors.white, + child: Container( + decoration: BoxDecoration( + borderRadius: _getBorderRadius(context), + ), + width: _getWidth(context), + height: _getHeight(context), + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + SizedBox( + height: 52, + child: Row( + children: [ + const SizedBox(width: 40), + Expanded( + child: Text( + AppLocalizations.of(context).localDraftList, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(color: Colors.black), + ), + ), + TMailButtonWidget.fromIcon( + icon: _imagePaths.icComposerClose, + backgroundColor: Colors.transparent, + margin: const EdgeInsetsDirectional.only(end: 12), + onTapActionCallback: popBack, + ) + ], + ), + ), + const Divider(color: AppColor.colorDivider, height: 1), + Expanded( + child: ScrollbarListView( + scrollBehavior: ScrollConfiguration.of(context).copyWith( + physics: const BouncingScrollPhysics(), + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad + }, + scrollbars: false, + ), + scrollController: _scrollController, + child: ListView.builder( + itemCount: widget.presentationLocalEmailDrafts.length, + shrinkWrap: true, + controller: _scrollController, + primary: false, + itemBuilder: (_, index) { + final draftLocal = + widget.presentationLocalEmailDrafts[index]; + return LocalEmailDraftItemWidget( + draftLocal: draftLocal, + isOldest: index == widget.presentationLocalEmailDrafts.length - 1, + imagePaths: _imagePaths, + onSelectLocalEmailDraftAction: (draftLocal) {}, + ); + }, + ), + ), + ), + const Divider(color: AppColor.colorDivider, height: 1), + Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + const Spacer(), + TMailButtonWidget( + text: AppLocalizations.of(context).discardAll, + backgroundColor: AppColor.grayBackgroundColor, + maxLines: 1, + textStyle: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(color: AppColor.steelGray600), + borderRadius: 10, + margin: const EdgeInsetsDirectional.only(end: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + onTapActionCallback: () {}, + ), + TMailButtonWidget( + text: AppLocalizations.of(context).openAll, + backgroundColor: AppColor.blue700, + textStyle: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(color: Colors.white), + maxLines: 1, + borderRadius: 10, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + onTapActionCallback: () {}, + ), + ], + ), + ) + ], + ), + ), + ); + } + + EdgeInsets _getMargin(BuildContext context) { + if (_responsiveUtils.isMobile(context)) { + return EdgeInsets.zero; + } else { + if (_responsiveUtils.getSizeScreenHeight(context) > _maxHeight) { + return const EdgeInsets.symmetric(vertical: 12); + } else { + return const EdgeInsets.symmetric(vertical: 50); + } + } + } + + BorderRadius _getBorderRadius(BuildContext context) { + if (_responsiveUtils.isMobile(context)) { + return const BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16), + ); + } else { + return const BorderRadius.all(Radius.circular(16)); + } + } + + double _getWidth(BuildContext context) { + if (_responsiveUtils.isMobile(context)) { + return double.infinity; + } else { + return _maxWidth; + } + } + + double _getHeight(BuildContext context) { + if (!_responsiveUtils.isMobile(context) && + _responsiveUtils.getSizeScreenHeight(context) > _maxHeight) { + return _maxHeight; + } else { + return double.infinity; + } + } +} diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index dfc59c1443..a38f5ebd34 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4393,5 +4393,23 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "localDraftList": "Local Draft List", + "@localDraftList": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "openAll": "Open all", + "@openAll": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "discardAll": "Discard all", + "@discardAll": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 12b91dfdf7..75746f21e8 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4618,4 +4618,25 @@ class AppLocalizations { name: 'viewEntireMessage', ); } + + String get localDraftList { + return Intl.message( + 'Local Draft List', + name: 'localDraftList', + ); + } + + String get openAll { + return Intl.message( + 'Open all', + name: 'openAll', + ); + } + + String get discardAll { + return Intl.message( + 'Discard all', + name: 'discardAll', + ); + } } From 75d821333f77b901bd149ce56fe8ab283ec49622 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 25 Mar 2025 21:38:00 +0700 Subject: [PATCH 04/10] TF-3358 Handle `Edit` & `Discard` each local email draft item Signed-off-by: dab246 --- .../email_action_type_extension.dart | 2 +- .../view/mobile/mobile_editor_view.dart | 2 +- .../view/web/web_editor_view.dart | 2 +- .../model/composer_arguments.dart | 35 ++++--- .../local_email_draft_datasource.dart | 6 +- .../local_email_draft_datasource_impl.dart | 15 +-- .../data/local/local_email_draft_manager.dart | 4 + .../local_email_draft_repository_impl.dart | 4 +- .../local_email_draft_repository.dart | 6 +- .../remove_local_email_draft_interactor.dart | 14 +-- .../bindings/mailbox_dashboard_bindings.dart | 3 - .../mailbox_dashboard_controller.dart | 37 ++------ .../local_email_draft_extension.dart | 2 +- .../open_and_close_composer_extension.dart | 4 - .../restore_local_email_draft_extension.dart | 32 ++++++- .../model/presentation_local_email_draft.dart | 24 ++++- .../local_email_draft_item_widget.dart | 20 +++- ...local_email_draft_list_dialog_builder.dart | 91 ++++++++++++++++--- lib/l10n/intl_messages.arb | 6 ++ lib/main/localizations/app_localizations.dart | 7 ++ model/lib/email/email_action_type.dart | 2 +- .../mailbox_dashboard_controller_test.dart | 14 --- .../mailbox_dashboard_view_widget_test.dart | 14 --- ...fore_time_in_search_email_filter_test.dart | 15 --- 24 files changed, 206 insertions(+), 155 deletions(-) diff --git a/lib/features/composer/presentation/extensions/email_action_type_extension.dart b/lib/features/composer/presentation/extensions/email_action_type_extension.dart index 0f1c0da0d1..e7d7198d40 100644 --- a/lib/features/composer/presentation/extensions/email_action_type_extension.dart +++ b/lib/features/composer/presentation/extensions/email_action_type_extension.dart @@ -31,7 +31,7 @@ extension EmailActionTypeExtension on EmailActionType { } case EmailActionType.editDraft: case EmailActionType.editSendingEmail: - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: case EmailActionType.editAsNewEmail: return subject; default: diff --git a/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart b/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart index fd516a70e2..dbabb5f9c9 100644 --- a/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart +++ b/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart @@ -49,7 +49,7 @@ class MobileEditorView extends StatelessWidget with EditorViewMixin { case EmailActionType.editDraft: case EmailActionType.editSendingEmail: case EmailActionType.composeFromContentShared: - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: case EmailActionType.composeFromMailtoUri: case EmailActionType.composeFromUnsubscribeMailtoLink: case EmailActionType.editAsNewEmail: diff --git a/lib/features/composer/presentation/view/web/web_editor_view.dart b/lib/features/composer/presentation/view/web/web_editor_view.dart index 68be4c95d5..c497eab181 100644 --- a/lib/features/composer/presentation/view/web/web_editor_view.dart +++ b/lib/features/composer/presentation/view/web/web_editor_view.dart @@ -86,7 +86,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin { case EmailActionType.editDraft: case EmailActionType.editSendingEmail: case EmailActionType.composeFromContentShared: - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: case EmailActionType.composeFromUnsubscribeMailtoLink: case EmailActionType.composeFromMailtoUri: case EmailActionType.editAsNewEmail: diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 858cdbee52..6692dbc8b2 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -7,6 +7,7 @@ import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart'; import 'package:tmail_ui_user/main/routes/router_arguments.dart'; @@ -119,22 +120,26 @@ class ComposerArguments extends RouterArguments { presentationEmail: presentationEmail, ); - factory ComposerArguments.fromSessionStorageBrowser(LocalEmailDraft composerCache) => - ComposerArguments( - emailActionType: EmailActionType.reopenComposerBrowser, - presentationEmail: composerCache.email?.toPresentationEmail(), - emailContents: composerCache.email?.emailContentList.asHtmlString, - attachments: composerCache.email?.allAttachments.getListAttachmentsDisplayedOutside(composerCache.email?.htmlBodyAttachments ?? []), - selectedIdentityId: composerCache.email?.identityIdFromHeader, - inlineImages: composerCache.email?.allAttachments.listAttachmentsDisplayedInContent, - hasRequestReadReceipt: composerCache.hasRequestReadReceipt, - displayMode: composerCache.displayMode, - isMarkAsImportant: composerCache.isMarkAsImportant, - composerId: composerCache.composerId, - savedDraftHash: composerCache.draftHash, - savedActionType: composerCache.actionType, - savedEmailDraftId: composerCache.draftEmailId, + factory ComposerArguments.fromLocalEmailDraft(PresentationLocalEmailDraft localDraft) { + final email = localDraft.email; + final allAttachments = email?.allAttachments; + + return ComposerArguments( + emailActionType: EmailActionType.composeFromLocalEmailDraft, + presentationEmail: email?.toPresentationEmail(), + emailContents: email?.emailContentList.asHtmlString, + attachments: allAttachments?.getListAttachmentsDisplayedOutside(email?.htmlBodyAttachments ?? []), + selectedIdentityId: email?.identityIdFromHeader, + inlineImages: email?.allAttachments.listAttachmentsDisplayedInContent, + hasRequestReadReceipt: localDraft.hasRequestReadReceipt, + displayMode: localDraft.displayMode, + isMarkAsImportant: localDraft.isMarkAsImportant, + composerId: localDraft.composerId, + savedDraftHash: localDraft.draftHash, + savedActionType: localDraft.actionType, + savedEmailDraftId: localDraft.draftEmailId, ); + } factory ComposerArguments.replyEmail({ required PresentationEmail presentationEmail, diff --git a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart index caca42ab05..6a7cf984f0 100644 --- a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart +++ b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart @@ -15,11 +15,7 @@ abstract class LocalEmailDraftDatasource { UserName userName, ); - Future removeLocalEmailDraft( - AccountId accountId, - UserName userName, - String composerId, - ); + Future removeLocalEmailDraft(String draftLocalId); Future restoreEmailInlineImages( String htmlContent, diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart index 6b1a200f79..9c984f29ef 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart @@ -67,7 +67,7 @@ class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { Future removeAllLocalEmailDraft(AccountId accountId, UserName userName) { return Future.sync(() { final keyWithIdentity = TupleKey( - EmailActionType.reopenComposerBrowser.name, + EmailActionType.composeFromLocalEmailDraft.name, accountId.asString, userName.value, ).toString(); @@ -77,16 +77,9 @@ class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { } @override - Future removeLocalEmailDraft(AccountId accountId, UserName userName, String composerId) { - return Future.sync(() { - final keyWithIdentity = TupleKey( - EmailActionType.reopenComposerBrowser.name, - accountId.asString, - userName.value, - composerId, - ).toString(); - - html.window.sessionStorage.removeWhere((key, value) => key == keyWithIdentity); + Future removeLocalEmailDraft(String draftLocalId) { + return Future.sync(() async { + return await _localEmailDraftManager.removeLocalEmailDraft(draftLocalId); }).catchError(_exceptionThrower.throwException); } } diff --git a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart index 9bd62e695d..0c3efa64c4 100644 --- a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart +++ b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart @@ -30,4 +30,8 @@ class LocalEmailDraftManager { localEmailDraft, ); } + + Future removeLocalEmailDraft(String id) async { + await _localEmailDraftClient.deleteItem(id); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart index ccf7f832df..002fb89d63 100644 --- a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart +++ b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart @@ -25,8 +25,8 @@ class LocalEmailDraftRepositoryImpl extends LocalEmailDraftRepository { } @override - Future removeLocalEmailDraft(AccountId accountId, UserName userName, String composerId) { - return _localEmailDraftDatasource.removeLocalEmailDraft(accountId, userName, composerId); + Future removeLocalEmailDraft(String draftLocalId) { + return _localEmailDraftDatasource.removeLocalEmailDraft(draftLocalId); } @override diff --git a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart index 698c584f0a..89eac52e75 100644 --- a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart +++ b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart @@ -15,11 +15,7 @@ abstract class LocalEmailDraftRepository { UserName userName, ); - Future removeLocalEmailDraft( - AccountId accountId, - UserName userName, - String composerId, - ); + Future removeLocalEmailDraft(String draftLocalId); Future restoreEmailInlineImages( String htmlContent, diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart index 1b7abfa042..ed4c569523 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart @@ -1,8 +1,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/account_id.dart'; -import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart'; @@ -11,17 +9,9 @@ class RemoveLocalEmailDraftInteractor { RemoveLocalEmailDraftInteractor(this._localEmailDraftRepository); - Future> execute( - AccountId accountId, - UserName userName, - String composerId, - ) async { + Future> execute(String draftLocalId) async { try { - _localEmailDraftRepository.removeLocalEmailDraft( - accountId, - userName, - composerId, - ); + _localEmailDraftRepository.removeLocalEmailDraft(draftLocalId); return Right(RemoveLocalEmailDraftSuccess()); } catch (exception) { return Left(RemoveLocalEmailDraftFailure(exception)); diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart index fd4a34a4a9..8db09a70bb 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -178,7 +178,6 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), Get.find(), Get.find(), @@ -198,8 +197,6 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), - Get.find(), Get.find(), )); Get.put(AdvancedFilterController()); 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 a53ba8bb75..03fbfecc7c 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -94,7 +94,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_ema import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_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'; @@ -195,7 +194,6 @@ class MailboxDashBoardController extends ReloadableController final MoveToMailboxInteractor _moveToMailboxInteractor; final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor; final MarkAsMailboxReadInteractor _markAsMailboxReadInteractor; - final GetAllLocalEmailDraftInteractor _getAllLocalEmailDraftInteractor; final GetIdentityCacheOnWebInteractor _getIdentityCacheOnWebInteractor; final MarkAsEmailReadInteractor _markAsEmailReadInteractor; final MarkAsStarEmailInteractor _markAsStarEmailInteractor; @@ -215,8 +213,6 @@ class MailboxDashBoardController extends ReloadableController final UnsubscribeEmailInteractor _unsubscribeEmailInteractor; final RestoredDeletedMessageInteractor _restoreDeletedMessageInteractor; final GetRestoredDeletedMessageInterator _getRestoredDeletedMessageInteractor; - final RemoveLocalEmailDraftInteractor _removeLocalEmailDraftInteractor; - final RemoveAllLocalEmailDraftInteractor _removeAllLocalEmailDraftInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; GetAllVacationInteractor? _getAllVacationInteractor; @@ -228,6 +224,8 @@ class MailboxDashBoardController extends ReloadableController GetAutoCompleteInteractor? _getAutoCompleteInteractor; IOSNotificationManager? _iosNotificationManager; GetServerSettingInteractor? getServerSettingInteractor; + GetAllLocalEmailDraftInteractor? getAllLocalEmailDraftInteractor; + RemoveAllLocalEmailDraftInteractor? removeAllLocalEmailDraftInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -287,7 +285,6 @@ class MailboxDashBoardController extends ReloadableController this._moveToMailboxInteractor, this._deleteEmailPermanentlyInteractor, this._markAsMailboxReadInteractor, - this._getAllLocalEmailDraftInteractor, this._getIdentityCacheOnWebInteractor, this._markAsEmailReadInteractor, this._markAsStarEmailInteractor, @@ -307,8 +304,6 @@ class MailboxDashBoardController extends ReloadableController this._unsubscribeEmailInteractor, this._restoreDeletedMessageInteractor, this._getRestoredDeletedMessageInteractor, - this._removeAllLocalEmailDraftInteractor, - this._removeLocalEmailDraftInteractor, this._getAllIdentitiesInteractor, ); @@ -330,6 +325,7 @@ class MailboxDashBoardController extends ReloadableController void onReady() { if (PlatformInfo.isWeb) { listSearchFilterScrollController = ScrollController(); + getAllLocalEmailDraftInteractor = getBinding(); } if (PlatformInfo.isIOS) { _registerPendingCurrentEmailIdInNotification(); @@ -339,15 +335,6 @@ class MailboxDashBoardController extends ReloadableController super.onReady(); } - void _handleLocalEmailDraft() async { - if (accountId.value == null || sessionCurrent == null) return; - - consumeState( - _getAllLocalEmailDraftInteractor.execute( - accountId.value!, - sessionCurrent!.username)); - } - void _handleIdentityCache() async { if (accountId.value == null || sessionCurrent == null) return; @@ -437,7 +424,7 @@ class MailboxDashBoardController extends ReloadableController } else if (success is GetAllIdentitiesSuccess) { _handleGetAllIdentitiesSuccess(success); } else if (success is GetAllLocalEmailDraftSuccess) { - restoreLocalEmailDraft(success.listLocalEmailDraft); + handlerGetAllLocalEmailDraft(success.listLocalEmailDraft); } else if (success is GetIdentityCacheOnWebSuccess) { goToSettings(); } else if (success is MarkAsStarEmailSuccess) { @@ -723,7 +710,7 @@ class MailboxDashBoardController extends ReloadableController _setUpComponentsFromSession(session); if (PlatformInfo.isWeb) { - _handleLocalEmailDraft(); + restoreLocalEmailDraft(); } if (PlatformInfo.isAndroid && !_notificationManager.isNotificationClickedOnTerminate) { @@ -1692,7 +1679,7 @@ class MailboxDashBoardController extends ReloadableController _getRouteParameters(); _setUpComponentsFromSession(session); if (PlatformInfo.isWeb) { - _handleLocalEmailDraft(); + restoreLocalEmailDraft(); } } @@ -3051,20 +3038,10 @@ class MailboxDashBoardController extends ReloadableController isRecoveringDeletedMessage.value = true; } - Future removeLocalEmailDraft(String composerId) async { - if (accountId.value == null || sessionCurrent == null) return; - - await _removeLocalEmailDraftInteractor.execute( - accountId.value!, - sessionCurrent!.username, - composerId, - ); - } - Future removeAllLocalEmailDraft() async { if (accountId.value == null || sessionCurrent == null) return; - await _removeAllLocalEmailDraftInteractor.execute( + await removeAllLocalEmailDraftInteractor?.execute( accountId.value!, sessionCurrent!.username, ); diff --git a/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart index 6664eac54c..328caff142 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart @@ -18,7 +18,7 @@ extension LocalEmailDraftExtension on LocalEmailDraft { isMarkAsImportant: isMarkAsImportant, displayMode: ScreenDisplayMode.values.firstWhereOrNull( (type) => type.name == displayMode, - ), + ) ?? ScreenDisplayMode.normal, composerIndex: composerIndex, ); } diff --git a/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart index 3fd78493e4..da3d717a3e 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart @@ -112,10 +112,6 @@ extension OpenAndCloseComposerExtension on MailboxDashBoardController { } _handleResultAfterCloseComposer(result); - - if (composerId != null) { - await removeLocalEmailDraft(composerId); - } } void _handleResultAfterCloseComposer(dynamic result) { diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index 7d32559ba8..f8807b54f0 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -2,15 +2,30 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:get/get.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.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/local_email_draft_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/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { - void restoreLocalEmailDraft(List localEmailDrafts) { + void restoreLocalEmailDraft() { + if (accountId.value == null || + sessionCurrent == null || + getAllLocalEmailDraftInteractor == null) return; + + consumeState(getAllLocalEmailDraftInteractor!.execute( + accountId.value!, + sessionCurrent!.username, + )); + } + + void handlerGetAllLocalEmailDraft(List localEmailDrafts) { final listPresentationLocalEmailDraft = localEmailDrafts .map((localEmailDraft) => localEmailDraft.toPresentation()) .toList(); @@ -24,10 +39,25 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { Get.dialog( PointerInterceptor( child: LocalEmailDraftListDialogBuilder( + accountId: accountId.value, + userName: sessionCurrent?.username, presentationLocalEmailDrafts: presentationLocalEmailDrafts, + onEditLocalEmailDraftAction: _editLocalEmailDraft, + onSaveAsDraftLocalEmailDraftAction: _saveAsDraftLocalEmailDraft, ), ), barrierColor: AppColor.colorDefaultCupertinoActionSheet, ); } + + void _editLocalEmailDraft(PresentationLocalEmailDraft draftLocal) { + popBack(); + openComposer(ComposerArguments.fromLocalEmailDraft( + draftLocal.copyWith(displayMode: ScreenDisplayMode.normal), + )); + } + + void _saveAsDraftLocalEmailDraft(PresentationLocalEmailDraft draftLocal) { + popBack(); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart index 5300f22fcd..b77c88f28c 100644 --- a/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart +++ b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart @@ -10,7 +10,7 @@ class PresentationLocalEmailDraft with EquatableMixin { final Email? email; final bool? hasRequestReadReceipt; final bool? isMarkAsImportant; - final ScreenDisplayMode? displayMode; + final ScreenDisplayMode displayMode; final int? composerIndex; PresentationLocalEmailDraft({ @@ -20,10 +20,30 @@ class PresentationLocalEmailDraft with EquatableMixin { this.email, this.hasRequestReadReceipt, this.isMarkAsImportant, - this.displayMode, + this.displayMode = ScreenDisplayMode.normal, this.composerIndex, }); + PresentationLocalEmailDraft copyWith({ + String? id, + String? composerId, + DateTime? savedTime, + Email? email, + bool? hasRequestReadReceipt, + bool? isMarkAsImportant, + ScreenDisplayMode? displayMode, + int? composerIndex, + }) => PresentationLocalEmailDraft( + id: id ?? this.id, + composerId: composerId ?? this.composerId, + savedTime: savedTime ?? this.savedTime, + email: email ?? this.email, + hasRequestReadReceipt: hasRequestReadReceipt ?? this.hasRequestReadReceipt, + isMarkAsImportant: isMarkAsImportant ?? this.isMarkAsImportant, + displayMode: displayMode ?? this.displayMode, + composerIndex: composerIndex ?? this.composerIndex, + ); + @override List get props => [ id, diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart index 6c03366234..11a75395da 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart @@ -10,12 +10,21 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; typedef OnSelectLocalEmailDraftAction = void Function( PresentationLocalEmailDraft); +typedef OnDiscardLocalEmailDraftAction = void Function( + PresentationLocalEmailDraft); +typedef OnEditLocalEmailDraftAction = void Function( + PresentationLocalEmailDraft); +typedef OnSaveAsDraftLocalEmailDraftAction = void Function( + PresentationLocalEmailDraft); class LocalEmailDraftItemWidget extends StatelessWidget { final PresentationLocalEmailDraft draftLocal; final bool isOldest; final ImagePaths imagePaths; final OnSelectLocalEmailDraftAction? onSelectLocalEmailDraftAction; + final OnEditLocalEmailDraftAction? onEditLocalEmailDraftAction; + final OnSaveAsDraftLocalEmailDraftAction? onSaveAsDraftLocalEmailDraftAction; + final OnDiscardLocalEmailDraftAction? onDiscardLocalEmailDraftAction; const LocalEmailDraftItemWidget({ super.key, @@ -23,6 +32,9 @@ class LocalEmailDraftItemWidget extends StatelessWidget { required this.imagePaths, required this.isOldest, this.onSelectLocalEmailDraftAction, + this.onEditLocalEmailDraftAction, + this.onSaveAsDraftLocalEmailDraftAction, + this.onDiscardLocalEmailDraftAction, }); @override @@ -136,7 +148,7 @@ class LocalEmailDraftItemWidget extends StatelessWidget { maxLines: 1, padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), margin: const EdgeInsetsDirectional.only(end: 8), - onTapActionCallback: () {}, + onTapActionCallback: () => onEditLocalEmailDraftAction?.call(draftLocal), ), ), Flexible( @@ -149,7 +161,7 @@ class LocalEmailDraftItemWidget extends StatelessWidget { maxLines: 1, padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), margin: const EdgeInsetsDirectional.only(end: 8), - onTapActionCallback: () {}, + onTapActionCallback: () => onSaveAsDraftLocalEmailDraftAction?.call(draftLocal), ), ), Flexible( @@ -162,7 +174,7 @@ class LocalEmailDraftItemWidget extends StatelessWidget { maxLines: 1, padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), margin: const EdgeInsetsDirectional.only(end: 8), - onTapActionCallback: () {}, + onTapActionCallback: () => onDiscardLocalEmailDraftAction?.call(draftLocal), ), ), ], @@ -170,7 +182,7 @@ class LocalEmailDraftItemWidget extends StatelessWidget { if (!isOldest) const Padding( padding: EdgeInsets.only(top: 12), - child: Divider(color: AppColor.colorDivider, height: 0.5)), + child: Divider(color: AppColor.colorDivider, height: 0.5,)), ], ), ), diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index a15e438363..7dd4df4a96 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -4,20 +4,34 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart'; +import 'package:core/utils/app_logger.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class LocalEmailDraftListDialogBuilder extends StatefulWidget { + final AccountId? accountId; + final UserName? userName; final List presentationLocalEmailDrafts; + final OnEditLocalEmailDraftAction? onEditLocalEmailDraftAction; + final OnSaveAsDraftLocalEmailDraftAction? onSaveAsDraftLocalEmailDraftAction; const LocalEmailDraftListDialogBuilder({ super.key, + required this.accountId, + required this.userName, required this.presentationLocalEmailDrafts, + this.onEditLocalEmailDraftAction, + this.onSaveAsDraftLocalEmailDraftAction, }); @override @@ -33,17 +47,23 @@ class _LocalEmailDraftListDialogBuilderState late final ResponsiveUtils _responsiveUtils; late final ImagePaths _imagePaths; late final ScrollController _scrollController; + late final RemoveLocalEmailDraftInteractor? _removeLocalEmailDraftInteractor; + + final ValueNotifier> _listLocalEmailDraftsNotifier = ValueNotifier([]); @override void initState() { super.initState(); _responsiveUtils = Get.find(); _imagePaths = Get.find(); + _removeLocalEmailDraftInteractor = getBinding(); _scrollController = ScrollController(); + _listLocalEmailDraftsNotifier.value = widget.presentationLocalEmailDrafts; } @override void dispose() { + _listLocalEmailDraftsNotifier.dispose(); _scrollController.dispose(); super.dispose(); } @@ -103,19 +123,31 @@ class _LocalEmailDraftListDialogBuilderState scrollbars: false, ), scrollController: _scrollController, - child: ListView.builder( - itemCount: widget.presentationLocalEmailDrafts.length, - shrinkWrap: true, - controller: _scrollController, - primary: false, - itemBuilder: (_, index) { - final draftLocal = - widget.presentationLocalEmailDrafts[index]; - return LocalEmailDraftItemWidget( - draftLocal: draftLocal, - isOldest: index == widget.presentationLocalEmailDrafts.length - 1, - imagePaths: _imagePaths, - onSelectLocalEmailDraftAction: (draftLocal) {}, + child: ValueListenableBuilder( + valueListenable: _listLocalEmailDraftsNotifier, + builder: (context, localDrafts, _) { + log('_LocalEmailDraftListDialogBuilderState::build:_listLocalEmailDraftsNotifier:localDrafts = ${localDrafts.length}'); + return ListView.builder( + itemCount: localDrafts.length, + shrinkWrap: true, + controller: _scrollController, + primary: false, + itemBuilder: (_, index) { + final draftLocal = localDrafts[index]; + return LocalEmailDraftItemWidget( + draftLocal: draftLocal, + isOldest: index == localDrafts.length - 1, + imagePaths: _imagePaths, + onSelectLocalEmailDraftAction: widget.onEditLocalEmailDraftAction, + onEditLocalEmailDraftAction: widget.onEditLocalEmailDraftAction, + onSaveAsDraftLocalEmailDraftAction: widget.onSaveAsDraftLocalEmailDraftAction, + onDiscardLocalEmailDraftAction: (draftLocal) => + _handleDiscardLocalEmailDraftAction( + draftLocal, + AppLocalizations.of(context), + ) + ); + }, ); }, ), @@ -200,4 +232,37 @@ class _LocalEmailDraftListDialogBuilderState return double.infinity; } } + + void _handleDiscardLocalEmailDraftAction( + PresentationLocalEmailDraft emailDraft, + AppLocalizations appLocalizations, + ) { + Get.dialog( + PointerInterceptor(child: ConfirmationDialogBuilder( + imagePath: _imagePaths, + useIconAsBasicLogo: true, + textContent: appLocalizations.messageWarningDialogDiscardLocalDraft, + confirmText: appLocalizations.yes, + cancelText: appLocalizations.no, + cancelBackgroundButtonColor: AppColor.blue700, + cancelLabelButtonColor: Colors.white, + confirmBackgroundButtonColor: AppColor.grayBackgroundColor, + confirmLabelButtonColor: AppColor.steelGray600, + onConfirmButtonAction: () => removeLocalEmailDraft(emailDraft.id), + onCancelButtonAction: popBack, + onCloseButtonAction: popBack, + )), + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + ); + } + + void removeLocalEmailDraft(String draftLocalId) { + log('_LocalEmailDraftListDialogBuilderState::removeLocalEmailDraft:draftLocalId = $draftLocalId'); + popBack(); + + _listLocalEmailDraftsNotifier.value = List.from(_listLocalEmailDraftsNotifier.value) + ..removeWhere((draftLocal) => draftLocal.id == draftLocalId); + + _removeLocalEmailDraftInteractor?.execute(draftLocalId); + } } diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index a38f5ebd34..f9c6f300d9 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4411,5 +4411,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "messageWarningDialogDiscardLocalDraft": "Are you sure you want to delete this local draft? You will not be able to restore it.", + "@messageWarningDialogDiscardLocalDraft": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 75746f21e8..3103557762 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4639,4 +4639,11 @@ class AppLocalizations { name: 'discardAll', ); } + + String get messageWarningDialogDiscardLocalDraft { + return Intl.message( + 'Are you sure you want to delete this local draft? You will not be able to restore it.', + name: 'messageWarningDialogDiscardLocalDraft', + ); + } } diff --git a/model/lib/email/email_action_type.dart b/model/lib/email/email_action_type.dart index ecbed93d38..ad525b12ea 100644 --- a/model/lib/email/email_action_type.dart +++ b/model/lib/email/email_action_type.dart @@ -17,7 +17,7 @@ enum EmailActionType { composeFromEmailAddress, composeFromMailtoUri, editAsNewEmail, - reopenComposerBrowser, + composeFromLocalEmailDraft, moveToTrash, deletePermanently, preview, diff --git a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart index 856c8174a7..985e28d205 100644 --- a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart +++ b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart @@ -53,12 +53,9 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_multipl import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -116,7 +113,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -174,8 +170,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -189,7 +183,6 @@ void main() { final deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - final getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -265,8 +258,6 @@ void main() { final verifyNameInteractor = MockVerifyNameInteractor(); final getAllMailboxInteractor = MockGetAllMailboxInteractor(); final refreshAllMailboxInteractor = MockRefreshAllMailboxInteractor(); - final removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); - final removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); final composerManager = MockComposerManager(); late MailboxController mailboxController; @@ -319,8 +310,6 @@ void main() { Get.put(getAuthenticatedAccountInteractor); Get.put(updateAccountCacheInteractor); Get.put(getAllIdentitiesInteractor); - Get.put(removeAllLocalEmailDraftInteractor); - Get.put(removeLocalEmailDraftInteractor); Get.put(composerManager); searchController = SearchController( @@ -335,7 +324,6 @@ void main() { moveToMailboxInteractor, deleteEmailPermanentlyInteractor, markAsMailboxReadInteractor, - getEmailCacheOnWebInteractor, getIdentityCacheOnWebInteractor, markAsEmailReadInteractor, markAsStarEmailInteractor, @@ -355,8 +343,6 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllLocalEmailDraftInteractor, - removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); }); diff --git a/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart b/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart index a48774b26d..df0a6dcb41 100644 --- a/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart +++ b/test/features/mailbox_dashboard/presentation/view/mailbox_dashboard_view_widget_test.dart @@ -52,12 +52,9 @@ import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.d import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -118,7 +115,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -175,8 +171,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -189,7 +183,6 @@ void main() { final moveToMailboxInteractor = MockMoveToMailboxInteractor(); final deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - final getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -252,8 +245,6 @@ void main() { final verifyNameInteractor = MockVerifyNameInteractor(); final getAllMailboxInteractor = MockGetAllMailboxInteractor(); final refreshAllMailboxInteractor = MockRefreshAllMailboxInteractor(); - final removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); - final removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); final composerManager = MockComposerManager(); @@ -317,8 +308,6 @@ void main() { Get.put(getAuthenticatedAccountInteractor); Get.put(updateAccountCacheInteractor); Get.put(getAllIdentitiesInteractor); - Get.put(removeAllLocalEmailDraftInteractor); - Get.put(removeLocalEmailDraftInteractor); Get.put(composerManager); when(emailReceiveManager.pendingSharedFileInfo).thenAnswer((_) => BehaviorSubject.seeded([])); @@ -334,7 +323,6 @@ void main() { moveToMailboxInteractor, deleteEmailPermanentlyInteractor, markAsMailboxReadInteractor, - getEmailCacheOnWebInteractor, getIdentityCacheOnWebInteractor, markAsEmailReadInteractor, markAsStarEmailInteractor, @@ -354,8 +342,6 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllLocalEmailDraftInteractor, - removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); Get.put(mailboxDashboardController); diff --git a/test/features/search/verify_before_time_in_search_email_filter_test.dart b/test/features/search/verify_before_time_in_search_email_filter_test.dart index 77bc0674bf..1850b18d02 100644 --- a/test/features/search/verify_before_time_in_search_email_filter_test.dart +++ b/test/features/search/verify_before_time_in_search_email_filter_test.dart @@ -39,12 +39,9 @@ import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_i import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.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'; @@ -136,7 +133,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -153,8 +149,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), - MockSpec(), MockSpec(), MockSpec(fallbackGenerators: fallbackGenerators), ]) @@ -192,7 +186,6 @@ void main() { late MockMoveToMailboxInteractor moveToMailboxInteractor; late MockDeleteEmailPermanentlyInteractor deleteEmailPermanentlyInteractor; late MockMarkAsMailboxReadInteractor markAsMailboxReadInteractor; - late MockGetAllLocalEmailDraftInteractor getEmailCacheOnWebInteractor; late MockGetIdentityCacheOnWebInteractor getIdentityCacheOnWebInteractor; late MockMarkAsEmailReadInteractor markAsEmailReadInteractor; late MockMarkAsStarEmailInteractor markAsStarEmailInteractor; @@ -211,8 +204,6 @@ void main() { late MockUnsubscribeEmailInteractor unsubscribeEmailInteractor; late MockRestoredDeletedMessageInteractor restoreDeletedMessageInteractor; late MockGetRestoredDeletedMessageInterator getRestoredDeletedMessageInteractor; - late MockRemoveAllLocalEmailDraftInteractor removeAllLocalEmailDraftInteractor; - late MockRemoveLocalEmailDraftInteractor removeLocalEmailDraftInteractor; late MockGetAllIdentitiesInteractor getAllIdentitiesInteractor; // Declaration base controller @@ -285,7 +276,6 @@ void main() { moveToMailboxInteractor = MockMoveToMailboxInteractor(); deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor(); markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor(); - getEmailCacheOnWebInteractor = MockGetAllLocalEmailDraftInteractor(); getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor(); markAsEmailReadInteractor = MockMarkAsEmailReadInteractor(); markAsStarEmailInteractor = MockMarkAsStarEmailInteractor(); @@ -304,8 +294,6 @@ void main() { unsubscribeEmailInteractor = MockUnsubscribeEmailInteractor(); restoreDeletedMessageInteractor = MockRestoredDeletedMessageInteractor(); getRestoredDeletedMessageInteractor = MockGetRestoredDeletedMessageInterator(); - removeAllLocalEmailDraftInteractor = MockRemoveAllLocalEmailDraftInteractor(); - removeLocalEmailDraftInteractor = MockRemoveLocalEmailDraftInteractor(); getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor(); searchController = SearchController( @@ -330,7 +318,6 @@ void main() { moveToMailboxInteractor, deleteEmailPermanentlyInteractor, markAsMailboxReadInteractor, - getEmailCacheOnWebInteractor, getIdentityCacheOnWebInteractor, markAsEmailReadInteractor, markAsStarEmailInteractor, @@ -350,8 +337,6 @@ void main() { unsubscribeEmailInteractor, restoreDeletedMessageInteractor, getRestoredDeletedMessageInteractor, - removeAllLocalEmailDraftInteractor, - removeLocalEmailDraftInteractor, getAllIdentitiesInteractor, ); From ff65f7df5f0d2185829043ae924f0acd4b94b32f Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 25 Mar 2025 23:01:44 +0700 Subject: [PATCH 05/10] TF-3358 Handle `Save as draft` each local email draft item Signed-off-by: dab246 --- ...w_and_save_email_to_drafts_interactor.dart | 3 +- .../presentation/composer_controller.dart | 7 +- .../handle_local_email_draft_extension.dart | 5 - .../handle_message_failure_mixin.dart} | 3 +- .../model/create_email_request.dart | 26 +++- .../bindings/mailbox_dashboard_bindings.dart | 34 +++++ .../mailbox_dashboard_controller.dart | 6 +- .../restore_local_email_draft_extension.dart | 7 +- ...local_email_draft_list_dialog_builder.dart | 131 +++++++++++++++--- lib/l10n/intl_messages.arb | 6 + lib/main/localizations/app_localizations.dart | 8 ++ 11 files changed, 199 insertions(+), 37 deletions(-) rename lib/features/composer/presentation/{extensions/handle_message_failure_extension.dart => mixin/handle_message_failure_mixin.dart} (90%) diff --git a/lib/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart b/lib/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart index 35d9bc56ab..b3706b9e9e 100644 --- a/lib/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart +++ b/lib/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart @@ -30,7 +30,8 @@ class CreateNewAndSaveEmailToDraftsInteractor { try { yield dartz.Right(GenerateEmailLoading()); - final emailCreated = await _createEmailObject(createEmailRequest); + final emailCreated = createEmailRequest.emailCreated + ?? await _createEmailObject(createEmailRequest); if (emailCreated != null) { if (createEmailRequest.draftsEmailId == null) { diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 5325bb086f..eadac6bf67 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -55,7 +55,6 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/get_draf import 'package:tmail_ui_user/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_local_email_draft_extension.dart'; -import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_message_failure_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_identities_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/sanitize_signature_in_email_content_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/setup_email_attachments_extension.dart'; @@ -69,6 +68,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/setup_li import 'package:tmail_ui_user/features/composer/presentation/extensions/setup_selected_identity_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/update_screen_display_mode_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart'; +import 'package:tmail_ui_user/features/composer/presentation/mixin/handle_message_failure_mixin.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/saved_email_draft.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart'; @@ -114,7 +114,10 @@ import 'package:tmail_ui_user/main/universal_import/html_stub.dart' as html; import 'package:tmail_ui_user/main/utils/app_config.dart'; class ComposerController extends BaseController - with DragDropFileMixin, AutoCompleteResultMixin, EditorViewMixin + with DragDropFileMixin, + AutoCompleteResultMixin, + EditorViewMixin, + HandleMessageFailureMixin implements BeforeReconnectHandler { final mailboxDashBoardController = Get.find(); diff --git a/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart index 9175da8aba..b09f5e681b 100644 --- a/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart +++ b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart @@ -3,8 +3,6 @@ import 'package:core/utils/app_logger.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/auto_create_tag_for_recipients_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart'; -import 'package:tmail_ui_user/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart'; -import 'package:tmail_ui_user/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; extension HandleLocalEmailDraftExtension on ComposerController { @@ -42,8 +40,6 @@ extension HandleLocalEmailDraftExtension on ComposerController { identity: identitySelected.value, attachments: uploadController.attachmentsUploaded, inlineAttachments: uploadController.mapInlineAttachments, - outboxMailboxId: getOutboxMailboxIdForComposer(), - sentMailboxId: getSentMailboxIdForComposer(), draftsMailboxId: getDraftMailboxIdForComposer(), draftsEmailId: getDraftEmailId(), answerForwardEmailId: arguments.presentationEmail?.id, @@ -77,5 +73,4 @@ extension HandleLocalEmailDraftExtension on ComposerController { username, ); } - } \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/handle_message_failure_extension.dart b/lib/features/composer/presentation/mixin/handle_message_failure_mixin.dart similarity index 90% rename from lib/features/composer/presentation/extensions/handle_message_failure_extension.dart rename to lib/features/composer/presentation/mixin/handle_message_failure_mixin.dart index 4cc86e53c1..0cb6b8a62d 100644 --- a/lib/features/composer/presentation/extensions/handle_message_failure_extension.dart +++ b/lib/features/composer/presentation/mixin/handle_message_failure_mixin.dart @@ -1,11 +1,10 @@ import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart'; -import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -extension HandleMessageFailureExtension on ComposerController { +mixin HandleMessageFailureMixin { String getMessageFailure({ required AppLocalizations appLocalizations, diff --git a/lib/features/composer/presentation/model/create_email_request.dart b/lib/features/composer/presentation/model/create_email_request.dart index 2ffb786d53..f88112a23c 100644 --- a/lib/features/composer/presentation/model/create_email_request.dart +++ b/lib/features/composer/presentation/model/create_email_request.dart @@ -9,6 +9,7 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/email/attachment.dart'; import 'package:model/email/email_action_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; class CreateEmailRequest with EquatableMixin { @@ -44,13 +45,14 @@ class CreateEmailRequest with EquatableMixin { final int? savedDraftHash; final EmailActionType? savedActionType; final EmailId? savedEmailDraftId; + final Email? emailCreated; CreateEmailRequest({ required this.session, required this.accountId, required this.emailActionType, - required this.subject, - required this.emailContent, + this.subject = '', + this.emailContent = '', this.fromSender, this.toRecipients, this.ccRecipients, @@ -77,8 +79,27 @@ class CreateEmailRequest with EquatableMixin { this.savedDraftHash, this.savedActionType, this.savedEmailDraftId, + this.emailCreated, }); + factory CreateEmailRequest.fromLocalEmailDraft({ + required Session session, + required AccountId accountId, + required PresentationLocalEmailDraft draftLocal, + }) { + return CreateEmailRequest( + session: session, + accountId: accountId, + emailActionType: EmailActionType.composeFromLocalEmailDraft, + emailCreated: draftLocal.email, + hasRequestReadReceipt: draftLocal.hasRequestReadReceipt ?? false, + isMarkAsImportant: draftLocal.isMarkAsImportant ?? false, + displayMode: draftLocal.displayMode, + composerId: draftLocal.composerId, + composerIndex: draftLocal.composerIndex, + ); + } + @override List get props => [ session, @@ -112,5 +133,6 @@ class CreateEmailRequest with EquatableMixin { savedDraftHash, savedActionType, savedEmailDraftId, + emailCreated, ]; } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart index 8db09a70bb..4b76a35b48 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -1,6 +1,8 @@ import 'package:core/data/model/source_type/data_source_type.dart'; +import 'package:core/data/network/download/download_client.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/html_transformer/html_transform.dart'; +import 'package:core/utils/application_manager.dart'; import 'package:core/utils/config/app_config_loader.dart'; import 'package:core/utils/file_utils.dart'; import 'package:core/utils/preview_eml_file_utils.dart'; @@ -10,8 +12,13 @@ import 'package:tmail_ui_user/features/base/base_bindings.dart'; import 'package:tmail_ui_user/features/caching/clients/recent_search_cache_client.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/composer/data/datasource/composer_datasource.dart'; +import 'package:tmail_ui_user/features/composer/data/datasource_impl/composer_datasource_impl.dart'; +import 'package:tmail_ui_user/features/composer/data/repository/composer_repository_impl.dart'; import 'package:tmail_ui_user/features/composer/data/repository/contact_repository_impl.dart'; +import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/contact_repository.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.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/email/data/datasource/email_datasource.dart'; @@ -136,9 +143,13 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_emai import 'package:tmail_ui_user/features/thread/domain/usecases/search_email_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/search_more_email_interactor.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_bindings.dart'; +import 'package:tmail_ui_user/features/upload/data/datasource/attachment_upload_datasource.dart'; +import 'package:tmail_ui_user/features/upload/data/datasource_impl/attachment_upload_datasource_impl.dart'; +import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart'; import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart'; import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; +import 'package:uuid/uuid.dart'; class MailboxDashBoardBindings extends BaseBindings { @@ -218,6 +229,8 @@ class MailboxDashBoardBindings extends BaseBindings { () => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); } @override @@ -298,6 +311,15 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find(), )); + Get.lazyPut(() => AttachmentUploadDataSourceImpl( + Get.find(), + Get.find(), + Get.find(), + )); + Get.lazyPut(() => ComposerDataSourceImpl( + Get.find(), + Get.find(), + )); } @override @@ -348,6 +370,10 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find() )); + Get.lazyPut(() => CreateNewAndSaveEmailToDraftsInteractor( + Get.find(), + Get.find(), + )); IdentityInteractorsBindings().dependencies(); Get.lazyPut(() => GetAllIdentitiesInteractor( @@ -372,6 +398,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); } @override @@ -424,5 +451,12 @@ class MailboxDashBoardBindings extends BaseBindings { DataSourceType.network: Get.find(), DataSourceType.local: Get.find() },)); + Get.lazyPut(() => ComposerRepositoryImpl( + Get.find(), + Get.find(), + Get.find(), + Get.find(), + Get.find(), + )); } } \ 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 03fbfecc7c..a1f1183dff 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -38,6 +38,7 @@ import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_st import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; @@ -226,6 +227,7 @@ class MailboxDashBoardController extends ReloadableController GetServerSettingInteractor? getServerSettingInteractor; GetAllLocalEmailDraftInteractor? getAllLocalEmailDraftInteractor; RemoveAllLocalEmailDraftInteractor? removeAllLocalEmailDraftInteractor; + CreateNewAndSaveEmailToDraftsInteractor? createNewAndSaveEmailToDraftsInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -326,6 +328,8 @@ class MailboxDashBoardController extends ReloadableController if (PlatformInfo.isWeb) { listSearchFilterScrollController = ScrollController(); getAllLocalEmailDraftInteractor = getBinding(); + removeAllLocalEmailDraftInteractor = getBinding(); + createNewAndSaveEmailToDraftsInteractor = getBinding(); } if (PlatformInfo.isIOS) { _registerPendingCurrentEmailIdInNotification(); @@ -3150,7 +3154,7 @@ class MailboxDashBoardController extends ReloadableController try { return sessionCurrent?.getOwnEmailAddress() ?? ''; } catch (e) { - logError('ManageAccountDashBoardController::getOwnEmailAddress:Exception: $e'); + logError('MailboxDashBoardController::getOwnEmailAddress:Exception: $e'); return ''; } } diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index f8807b54f0..976a09979d 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -40,10 +40,9 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { PointerInterceptor( child: LocalEmailDraftListDialogBuilder( accountId: accountId.value, - userName: sessionCurrent?.username, + session: sessionCurrent, presentationLocalEmailDrafts: presentationLocalEmailDrafts, onEditLocalEmailDraftAction: _editLocalEmailDraft, - onSaveAsDraftLocalEmailDraftAction: _saveAsDraftLocalEmailDraft, ), ), barrierColor: AppColor.colorDefaultCupertinoActionSheet, @@ -56,8 +55,4 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { draftLocal.copyWith(displayMode: ScreenDisplayMode.normal), )); } - - void _saveAsDraftLocalEmailDraft(PresentationLocalEmailDraft draftLocal) { - popBack(); - } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index 7dd4df4a96..1a05c3e23b 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -2,16 +2,24 @@ import 'dart:ui'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart'; import 'package:core/utils/app_logger.dart'; +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; +import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/composer/presentation/mixin/handle_message_failure_mixin.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/saving_message_dialog_view.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart'; @@ -20,18 +28,16 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class LocalEmailDraftListDialogBuilder extends StatefulWidget { final AccountId? accountId; - final UserName? userName; + final Session? session; final List presentationLocalEmailDrafts; final OnEditLocalEmailDraftAction? onEditLocalEmailDraftAction; - final OnSaveAsDraftLocalEmailDraftAction? onSaveAsDraftLocalEmailDraftAction; const LocalEmailDraftListDialogBuilder({ super.key, required this.accountId, - required this.userName, + required this.session, required this.presentationLocalEmailDrafts, this.onEditLocalEmailDraftAction, - this.onSaveAsDraftLocalEmailDraftAction, }); @override @@ -40,14 +46,17 @@ class LocalEmailDraftListDialogBuilder extends StatefulWidget { } class _LocalEmailDraftListDialogBuilderState - extends State { + extends State + with HandleMessageFailureMixin { static const double _maxHeight = 656.0; static const double _maxWidth = 556.0; late final ResponsiveUtils _responsiveUtils; late final ImagePaths _imagePaths; + late final AppToast _appToast; late final ScrollController _scrollController; late final RemoveLocalEmailDraftInteractor? _removeLocalEmailDraftInteractor; + late final CreateNewAndSaveEmailToDraftsInteractor? _createNewAndSaveEmailToDraftsInteractor; final ValueNotifier> _listLocalEmailDraftsNotifier = ValueNotifier([]); @@ -56,7 +65,9 @@ class _LocalEmailDraftListDialogBuilderState super.initState(); _responsiveUtils = Get.find(); _imagePaths = Get.find(); + _appToast = Get.find(); _removeLocalEmailDraftInteractor = getBinding(); + _createNewAndSaveEmailToDraftsInteractor = getBinding(); _scrollController = ScrollController(); _listLocalEmailDraftsNotifier.value = widget.presentationLocalEmailDrafts; } @@ -140,12 +151,10 @@ class _LocalEmailDraftListDialogBuilderState imagePaths: _imagePaths, onSelectLocalEmailDraftAction: widget.onEditLocalEmailDraftAction, onEditLocalEmailDraftAction: widget.onEditLocalEmailDraftAction, - onSaveAsDraftLocalEmailDraftAction: widget.onSaveAsDraftLocalEmailDraftAction, + onSaveAsDraftLocalEmailDraftAction: (draftLocal) => + _saveAsDraftLocalEmailDraft(draftLocal, context), onDiscardLocalEmailDraftAction: (draftLocal) => - _handleDiscardLocalEmailDraftAction( - draftLocal, - AppLocalizations.of(context), - ) + _handleDiscardLocalEmailDraftAction(draftLocal, context) ); }, ); @@ -235,8 +244,9 @@ class _LocalEmailDraftListDialogBuilderState void _handleDiscardLocalEmailDraftAction( PresentationLocalEmailDraft emailDraft, - AppLocalizations appLocalizations, + BuildContext context, ) { + final appLocalizations = AppLocalizations.of(context); Get.dialog( PointerInterceptor(child: ConfirmationDialogBuilder( imagePath: _imagePaths, @@ -248,7 +258,10 @@ class _LocalEmailDraftListDialogBuilderState cancelLabelButtonColor: Colors.white, confirmBackgroundButtonColor: AppColor.grayBackgroundColor, confirmLabelButtonColor: AppColor.steelGray600, - onConfirmButtonAction: () => removeLocalEmailDraft(emailDraft.id), + onConfirmButtonAction: () { + popBack(); + removeLocalEmailDraft(context, emailDraft.id); + }, onCancelButtonAction: popBack, onCloseButtonAction: popBack, )), @@ -256,13 +269,95 @@ class _LocalEmailDraftListDialogBuilderState ); } - void removeLocalEmailDraft(String draftLocalId) { - log('_LocalEmailDraftListDialogBuilderState::removeLocalEmailDraft:draftLocalId = $draftLocalId'); - popBack(); - + Future removeLocalEmailDraft(BuildContext context, String draftLocalId) async { _listLocalEmailDraftsNotifier.value = List.from(_listLocalEmailDraftsNotifier.value) ..removeWhere((draftLocal) => draftLocal.id == draftLocalId); - _removeLocalEmailDraftInteractor?.execute(draftLocalId); + await _removeLocalEmailDraftInteractor?.execute(draftLocalId); + + if (context.mounted) { + _appToast.showToastSuccessMessage( + context, + AppLocalizations.of(context).deleteLocalDraftSuccessfully, + ); + } + + if (_listLocalEmailDraftsNotifier.value.isEmpty) { + popBack(); + } + } + + Future _saveAsDraftLocalEmailDraft( + PresentationLocalEmailDraft draftLocal, + BuildContext context, + ) async { + if (widget.accountId == null || + widget.session == null || + _createNewAndSaveEmailToDraftsInteractor == null) return; + + final resultState = await _showSavingMessageToDraftsDialog( + session: widget.session!, + accountId: widget.accountId!, + draftLocal: draftLocal, + createNewAndSaveEmailToDraftsInteractor: _createNewAndSaveEmailToDraftsInteractor!, + cancelToken: CancelToken(), + ); + + if (!context.mounted) return; + + if (resultState is SaveEmailAsDraftsSuccess) { + _appToast.showToastSuccessMessage( + context, + AppLocalizations.of(context).drafts_saved, + leadingSVGIcon: _imagePaths.icMailboxDrafts, + leadingSVGIconColor: Colors.white, + ); + + removeLocalEmailDraft(context, draftLocal.id); + } else if (resultState is SaveEmailAsDraftsFailure) { + final errorMessage = getMessageFailure( + appLocalizations: AppLocalizations.of(context), + exception: resultState.exception, + isDraft: true, + ); + + _appToast.showToastErrorMessage( + context, + errorMessage, + leadingSVGIcon: _imagePaths.icMailboxDrafts, + leadingSVGIconColor: Colors.white, + ); + } + } + + Future _showSavingMessageToDraftsDialog({ + required Session session, + required AccountId accountId, + required PresentationLocalEmailDraft draftLocal, + required CreateNewAndSaveEmailToDraftsInteractor createNewAndSaveEmailToDraftsInteractor, + CancelToken? cancelToken, + }) { + final childWidget = PointerInterceptor( + child: SavingMessageDialogView( + createEmailRequest: CreateEmailRequest.fromLocalEmailDraft( + session: session, + accountId: accountId, + draftLocal: draftLocal, + ), + createNewAndSaveEmailToDraftsInteractor: createNewAndSaveEmailToDraftsInteractor, + onCancelSavingEmailToDraftsAction: _handleCancelSavingMessageToDrafts, + cancelToken: cancelToken, + ), + ); + + return Get.dialog( + childWidget, + barrierDismissible: false, + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + ); + } + + void _handleCancelSavingMessageToDrafts({CancelToken? cancelToken}) { + cancelToken?.cancel([SavingEmailToDraftsCanceledException()]); } } diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index f9c6f300d9..9d3a13faf8 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4417,5 +4417,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "deleteLocalDraftSuccessfully": "Delete local draft successfully", + "@deleteLocalDraftSuccessfully": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 3103557762..8bbab137c2 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4646,4 +4646,12 @@ class AppLocalizations { name: 'messageWarningDialogDiscardLocalDraft', ); } + + String get deleteLocalDraftSuccessfully { + return Intl.message( + 'Delete local draft successfully', + name: 'deleteLocalDraftSuccessfully', + ); + } + } From 53a3cce9e73177db2ee9b48545765a79ee57c7a5 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 25 Mar 2025 23:47:36 +0700 Subject: [PATCH 06/10] TF-3358 Handle `Discard all` local email draft list Signed-off-by: dab246 --- .../local_email_draft_datasource.dart | 2 +- .../local_email_draft_datasource_impl.dart | 16 +---- .../data/local/local_email_draft_manager.dart | 5 ++ .../local_email_draft_repository_impl.dart | 4 +- .../local_email_draft_repository.dart | 2 +- .../remove_all_local_email_draft_state.dart | 9 +++ ...rt => remove_local_email_draft_state.dart} | 8 +-- ...ve_all_local_email_drafts_interactor.dart} | 12 ++-- .../remove_local_email_draft_interactor.dart | 2 +- .../bindings/mailbox_dashboard_bindings.dart | 4 +- .../mailbox_dashboard_controller.dart | 18 ------ .../restore_local_email_draft_extension.dart | 5 +- ...local_email_draft_list_dialog_builder.dart | 58 +++++++++++++++++-- lib/l10n/intl_messages.arb | 16 ++++- lib/main/localizations/app_localizations.dart | 19 +++++- 15 files changed, 118 insertions(+), 62 deletions(-) create mode 100644 lib/features/mailbox_dashboard/domain/state/remove_all_local_email_draft_state.dart rename lib/features/mailbox_dashboard/domain/state/{remove_composer_cache_state.dart => remove_local_email_draft_state.dart} (65%) rename lib/features/mailbox_dashboard/domain/usecases/{remove_all_local_email_draft_interactor.dart => remove_all_local_email_drafts_interactor.dart} (63%) diff --git a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart index 6a7cf984f0..79afe5ced2 100644 --- a/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart +++ b/lib/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart @@ -10,7 +10,7 @@ abstract class LocalEmailDraftDatasource { AccountId accountId, UserName userName); - Future removeAllLocalEmailDraft( + Future removeAllLocalEmailDrafts( AccountId accountId, UserName userName, ); diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart index 9c984f29ef..03149b7333 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart @@ -2,16 +2,12 @@ import 'package:core/presentation/utils/html_transformer/html_transform.dart'; import 'package:core/presentation/utils/html_transformer/transform_configuration.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; -import 'package:model/email/email_action_type.dart'; -import 'package:model/extensions/account_id_extensions.dart'; -import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/local_email_draft_datasource.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_manager.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_email_draft_worker_queue.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/offline_mode/hive_worker/hive_task.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; -import 'package:universal_html/html.dart' as html; class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { @@ -64,15 +60,9 @@ class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { } @override - Future removeAllLocalEmailDraft(AccountId accountId, UserName userName) { - return Future.sync(() { - final keyWithIdentity = TupleKey( - EmailActionType.composeFromLocalEmailDraft.name, - accountId.asString, - userName.value, - ).toString(); - - html.window.sessionStorage.removeWhere((key, value) => key.startsWith(keyWithIdentity)); + Future removeAllLocalEmailDrafts(AccountId accountId, UserName userName) { + return Future.sync(() async { + return await _localEmailDraftManager.removeAllLocalEmailDrafts(accountId, userName); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart index 0c3efa64c4..05747ee95e 100644 --- a/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart +++ b/lib/features/mailbox_dashboard/data/local/local_email_draft_manager.dart @@ -34,4 +34,9 @@ class LocalEmailDraftManager { Future removeLocalEmailDraft(String id) async { await _localEmailDraftClient.deleteItem(id); } + + Future removeAllLocalEmailDrafts(AccountId accountId, UserName userName) async { + final nestedKey = TupleKey(accountId.asString, userName.value).encodeKey; + await _localEmailDraftClient.clearAllDataContainKey(nestedKey); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart index 002fb89d63..86a970d2ae 100644 --- a/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart +++ b/lib/features/mailbox_dashboard/data/repository/local_email_draft_repository_impl.dart @@ -20,8 +20,8 @@ class LocalEmailDraftRepositoryImpl extends LocalEmailDraftRepository { } @override - Future removeAllLocalEmailDraft(AccountId accountId, UserName userName) { - return _localEmailDraftDatasource.removeAllLocalEmailDraft(accountId, userName); + Future removeAllLocalEmailDrafts(AccountId accountId, UserName userName) { + return _localEmailDraftDatasource.removeAllLocalEmailDrafts(accountId, userName); } @override diff --git a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart index 89eac52e75..b11ddc5f1b 100644 --- a/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart +++ b/lib/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart @@ -10,7 +10,7 @@ abstract class LocalEmailDraftRepository { AccountId accountId, UserName userName); - Future removeAllLocalEmailDraft( + Future removeAllLocalEmailDrafts( AccountId accountId, UserName userName, ); diff --git a/lib/features/mailbox_dashboard/domain/state/remove_all_local_email_draft_state.dart b/lib/features/mailbox_dashboard/domain/state/remove_all_local_email_draft_state.dart new file mode 100644 index 0000000000..3b80b2ce00 --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/state/remove_all_local_email_draft_state.dart @@ -0,0 +1,9 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; + +class RemoveAllLocalEmailDraftsSuccess extends UIState {} + +class RemoveAllLocalEmailDraftsFailure extends FeatureFailure { + + RemoveAllLocalEmailDraftsFailure(dynamic exception) : super(exception: exception); +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart b/lib/features/mailbox_dashboard/domain/state/remove_local_email_draft_state.dart similarity index 65% rename from lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart rename to lib/features/mailbox_dashboard/domain/state/remove_local_email_draft_state.dart index f12941d16d..a80c261dc3 100644 --- a/lib/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart +++ b/lib/features/mailbox_dashboard/domain/state/remove_local_email_draft_state.dart @@ -1,13 +1,7 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -class RemoveLocalEmailDraftSuccess extends UIState { - - RemoveLocalEmailDraftSuccess(); - - @override - List get props => []; -} +class RemoveLocalEmailDraftSuccess extends UIState {} class RemoveLocalEmailDraftFailure extends FeatureFailure { diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_drafts_interactor.dart similarity index 63% rename from lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart rename to lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_drafts_interactor.dart index bda2a36089..c4677a702a 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_all_local_email_drafts_interactor.dart @@ -4,19 +4,19 @@ import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_all_local_email_draft_state.dart'; -class RemoveAllLocalEmailDraftInteractor { +class RemoveAllLocalEmailDraftsInteractor { final LocalEmailDraftRepository _localEmailDraftRepository; - RemoveAllLocalEmailDraftInteractor(this._localEmailDraftRepository); + RemoveAllLocalEmailDraftsInteractor(this._localEmailDraftRepository); Future> execute(AccountId accountId, UserName userName) async { try { - _localEmailDraftRepository.removeAllLocalEmailDraft(accountId, userName); - return Right(RemoveLocalEmailDraftSuccess()); + await _localEmailDraftRepository.removeAllLocalEmailDrafts(accountId, userName); + return Right(RemoveAllLocalEmailDraftsSuccess()); } catch (exception) { - return Left(RemoveLocalEmailDraftFailure(exception)); + return Left(RemoveAllLocalEmailDraftsFailure(exception)); } } } diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart index ed4c569523..a09fd5a3e3 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart @@ -2,7 +2,7 @@ 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/mailbox_dashboard/domain/repository/local_email_draft_repository.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_composer_cache_state.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_local_email_draft_state.dart'; class RemoveLocalEmailDraftInteractor { final LocalEmailDraftRepository _localEmailDraftRepository; diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart index 4b76a35b48..f7fe541605 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -91,7 +91,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_app import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_mailbox_cached_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_report_state_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart'; @@ -336,7 +336,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => MarkAsMailboxReadInteractor(Get.find())); Get.lazyPut(() => GetAllLocalEmailDraftInteractor(Get.find())); Get.lazyPut(() => RemoveLocalEmailDraftInteractor(Get.find())); - Get.lazyPut(() => RemoveAllLocalEmailDraftInteractor(Get.find())); + Get.lazyPut(() => RemoveAllLocalEmailDraftsInteractor(Get.find())); Get.lazyPut(() => MarkAsEmailReadInteractor(Get.find())); Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find())); Get.lazyPut(() => MarkAsMultipleEmailReadInteractor( 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 a1f1183dff..f88c18ff33 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -38,7 +38,6 @@ import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_st import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; @@ -92,8 +91,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart'; @@ -225,9 +222,6 @@ class MailboxDashBoardController extends ReloadableController GetAutoCompleteInteractor? _getAutoCompleteInteractor; IOSNotificationManager? _iosNotificationManager; GetServerSettingInteractor? getServerSettingInteractor; - GetAllLocalEmailDraftInteractor? getAllLocalEmailDraftInteractor; - RemoveAllLocalEmailDraftInteractor? removeAllLocalEmailDraftInteractor; - CreateNewAndSaveEmailToDraftsInteractor? createNewAndSaveEmailToDraftsInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -327,9 +321,6 @@ class MailboxDashBoardController extends ReloadableController void onReady() { if (PlatformInfo.isWeb) { listSearchFilterScrollController = ScrollController(); - getAllLocalEmailDraftInteractor = getBinding(); - removeAllLocalEmailDraftInteractor = getBinding(); - createNewAndSaveEmailToDraftsInteractor = getBinding(); } if (PlatformInfo.isIOS) { _registerPendingCurrentEmailIdInNotification(); @@ -3042,15 +3033,6 @@ class MailboxDashBoardController extends ReloadableController isRecoveringDeletedMessage.value = true; } - Future removeAllLocalEmailDraft() async { - if (accountId.value == null || sessionCurrent == null) return; - - await removeAllLocalEmailDraftInteractor?.execute( - accountId.value!, - sessionCurrent!.username, - ); - } - bool validateSendingEmailFailedWhenNetworkIsLostOnMobile(dynamic failure) { return failure is SendEmailFailure && failure.exception is NoNetworkError && diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index 976a09979d..aedf870157 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -5,6 +5,7 @@ import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_local_email_draft_interactor.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/local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart'; @@ -15,11 +16,13 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { void restoreLocalEmailDraft() { + final getAllLocalEmailDraftInteractor = getBinding(); + if (accountId.value == null || sessionCurrent == null || getAllLocalEmailDraftInteractor == null) return; - consumeState(getAllLocalEmailDraftInteractor!.execute( + consumeState(getAllLocalEmailDraftInteractor.execute( accountId.value!, sessionCurrent!.username, )); diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index 1a05c3e23b..85b8ed32e0 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -9,6 +9,7 @@ import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart' import 'package:core/utils/app_logger.dart'; import 'package:dio/dio.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/session/session.dart'; @@ -20,6 +21,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_s import 'package:tmail_ui_user/features/composer/presentation/mixin/handle_message_failure_mixin.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/saving_message_dialog_view.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_all_local_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_item_widget.dart'; @@ -57,6 +59,7 @@ class _LocalEmailDraftListDialogBuilderState late final ScrollController _scrollController; late final RemoveLocalEmailDraftInteractor? _removeLocalEmailDraftInteractor; late final CreateNewAndSaveEmailToDraftsInteractor? _createNewAndSaveEmailToDraftsInteractor; + late final RemoveAllLocalEmailDraftsInteractor? _removeAllLocalEmailDraftsInteractor; final ValueNotifier> _listLocalEmailDraftsNotifier = ValueNotifier([]); @@ -68,6 +71,7 @@ class _LocalEmailDraftListDialogBuilderState _appToast = Get.find(); _removeLocalEmailDraftInteractor = getBinding(); _createNewAndSaveEmailToDraftsInteractor = getBinding(); + _removeAllLocalEmailDraftsInteractor = getBinding(); _scrollController = ScrollController(); _listLocalEmailDraftsNotifier.value = widget.presentationLocalEmailDrafts; } @@ -76,6 +80,7 @@ class _LocalEmailDraftListDialogBuilderState void dispose() { _listLocalEmailDraftsNotifier.dispose(); _scrollController.dispose(); + if (SmartDialog.checkExist()) SmartDialog.dismiss(); super.dispose(); } @@ -179,10 +184,10 @@ class _LocalEmailDraftListDialogBuilderState borderRadius: 10, margin: const EdgeInsetsDirectional.only(end: 8), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - onTapActionCallback: () {}, + onTapActionCallback: () => _handleDiscardAllLocalEmailDraftAction(context), ), TMailButtonWidget( - text: AppLocalizations.of(context).openAll, + text: AppLocalizations.of(context).restoreAll, backgroundColor: AppColor.blue700, textStyle: Theme.of(context) .textTheme @@ -260,7 +265,7 @@ class _LocalEmailDraftListDialogBuilderState confirmLabelButtonColor: AppColor.steelGray600, onConfirmButtonAction: () { popBack(); - removeLocalEmailDraft(context, emailDraft.id); + _removeLocalEmailDraft(context, emailDraft.id); }, onCancelButtonAction: popBack, onCloseButtonAction: popBack, @@ -269,7 +274,7 @@ class _LocalEmailDraftListDialogBuilderState ); } - Future removeLocalEmailDraft(BuildContext context, String draftLocalId) async { + Future _removeLocalEmailDraft(BuildContext context, String draftLocalId) async { _listLocalEmailDraftsNotifier.value = List.from(_listLocalEmailDraftsNotifier.value) ..removeWhere((draftLocal) => draftLocal.id == draftLocalId); @@ -313,7 +318,7 @@ class _LocalEmailDraftListDialogBuilderState leadingSVGIconColor: Colors.white, ); - removeLocalEmailDraft(context, draftLocal.id); + _removeLocalEmailDraft(context, draftLocal.id); } else if (resultState is SaveEmailAsDraftsFailure) { final errorMessage = getMessageFailure( appLocalizations: AppLocalizations.of(context), @@ -360,4 +365,47 @@ class _LocalEmailDraftListDialogBuilderState void _handleCancelSavingMessageToDrafts({CancelToken? cancelToken}) { cancelToken?.cancel([SavingEmailToDraftsCanceledException()]); } + + void _handleDiscardAllLocalEmailDraftAction(BuildContext context) { + final appLocalizations = AppLocalizations.of(context); + Get.dialog( + PointerInterceptor(child: ConfirmationDialogBuilder( + imagePath: _imagePaths, + useIconAsBasicLogo: true, + textContent: appLocalizations.messageWarningDialogDiscardAllLocalDrafts, + confirmText: appLocalizations.yes, + cancelText: appLocalizations.no, + cancelBackgroundButtonColor: AppColor.blue700, + cancelLabelButtonColor: Colors.white, + confirmBackgroundButtonColor: AppColor.grayBackgroundColor, + confirmLabelButtonColor: AppColor.steelGray600, + onConfirmButtonAction: () { + popBack(); + _removeAllLocalEmailDrafts(context); + }, + onCancelButtonAction: popBack, + onCloseButtonAction: popBack, + )), + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + ); + } + + Future _removeAllLocalEmailDrafts(BuildContext context) async { + if (widget.accountId == null || + widget.session == null || + _removeAllLocalEmailDraftsInteractor == null) return; + + SmartDialog.showLoading( + msg: AppLocalizations.of(context).deletingLocalDraft, + ); + _listLocalEmailDraftsNotifier.value = []; + + await _removeAllLocalEmailDraftsInteractor!.execute( + widget.accountId!, + widget.session!.username, + ); + + SmartDialog.dismiss(); + popBack(); + } } diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 9d3a13faf8..22ae61f9e0 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4400,8 +4400,8 @@ "placeholders_order": [], "placeholders": {} }, - "openAll": "Open all", - "@openAll": { + "restoreAll": "Restore all", + "@restoreAll": { "type": "text", "placeholders_order": [], "placeholders": {} @@ -4423,5 +4423,17 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "messageWarningDialogDiscardAllLocalDrafts": "Are you sure you want to delete all local drafts? They cannot be restored.", + "@messageWarningDialogDiscardAllLocalDrafts": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "deletingLocalDraft": "Deleting local draft...", + "@deletingLocalDraft": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 8bbab137c2..260afda2e1 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4626,10 +4626,10 @@ class AppLocalizations { ); } - String get openAll { + String get restoreAll { return Intl.message( - 'Open all', - name: 'openAll', + 'Restore all', + name: 'restoreAll', ); } @@ -4654,4 +4654,17 @@ class AppLocalizations { ); } + String get messageWarningDialogDiscardAllLocalDrafts { + return Intl.message( + 'Are you sure you want to delete all local drafts? They cannot be restored.', + name: 'messageWarningDialogDiscardAllLocalDrafts', + ); + } + + String get deletingLocalDraft { + return Intl.message( + 'Deleting local draft...', + name: 'deletingLocalDraft', + ); + } } From a7311d871a350ba838db0bc7326e1be30b9da9f8 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 26 Mar 2025 00:02:41 +0700 Subject: [PATCH 07/10] TF-3358 Handle `Restore all` local email draft list Signed-off-by: dab246 --- .../restore_local_email_draft_extension.dart | 11 +++++++++++ .../local_email_draft_list_dialog_builder.dart | 11 ++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index aedf870157..a5cecbb973 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -46,6 +46,7 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { session: sessionCurrent, presentationLocalEmailDrafts: presentationLocalEmailDrafts, onEditLocalEmailDraftAction: _editLocalEmailDraft, + onRestoreAllLocalEmailDraftsAction: _restoreAllLocalEmailDrafts, ), ), barrierColor: AppColor.colorDefaultCupertinoActionSheet, @@ -58,4 +59,14 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { draftLocal.copyWith(displayMode: ScreenDisplayMode.normal), )); } + + void _restoreAllLocalEmailDrafts(List localDrafts) { + popBack(); + + final listComposerArguments = localDrafts + .map(ComposerArguments.fromLocalEmailDraft) + .toList(); + + openListComposer(listComposerArguments); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index 85b8ed32e0..b0e78ece0f 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -6,7 +6,6 @@ import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart'; -import 'package:core/utils/app_logger.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -28,11 +27,14 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/lo import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; +typedef OnRestoreAllLocalEmailDraftsAction = Function(List); + class LocalEmailDraftListDialogBuilder extends StatefulWidget { final AccountId? accountId; final Session? session; final List presentationLocalEmailDrafts; final OnEditLocalEmailDraftAction? onEditLocalEmailDraftAction; + final OnRestoreAllLocalEmailDraftsAction? onRestoreAllLocalEmailDraftsAction; const LocalEmailDraftListDialogBuilder({ super.key, @@ -40,6 +42,7 @@ class LocalEmailDraftListDialogBuilder extends StatefulWidget { required this.session, required this.presentationLocalEmailDrafts, this.onEditLocalEmailDraftAction, + this.onRestoreAllLocalEmailDraftsAction, }); @override @@ -142,7 +145,6 @@ class _LocalEmailDraftListDialogBuilderState child: ValueListenableBuilder( valueListenable: _listLocalEmailDraftsNotifier, builder: (context, localDrafts, _) { - log('_LocalEmailDraftListDialogBuilderState::build:_listLocalEmailDraftsNotifier:localDrafts = ${localDrafts.length}'); return ListView.builder( itemCount: localDrafts.length, shrinkWrap: true, @@ -196,7 +198,10 @@ class _LocalEmailDraftListDialogBuilderState maxLines: 1, borderRadius: 10, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - onTapActionCallback: () {}, + onTapActionCallback: () => + widget.onRestoreAllLocalEmailDraftsAction?.call( + _listLocalEmailDraftsNotifier.value, + ), ), ], ), From 7d94fbad40388e70dca232115e1b61c2e6863698 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 26 Mar 2025 02:05:20 +0700 Subject: [PATCH 08/10] TF-3358 Auto save draft locally periodically Signed-off-by: dab246 --- .../manager/composer_manager.dart | 35 +++++++++++++++++++ .../presentation/manager/composer_timer.dart | 29 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 lib/features/composer/presentation/manager/composer_timer.dart diff --git a/lib/features/composer/presentation/manager/composer_manager.dart b/lib/features/composer/presentation/manager/composer_manager.dart index ee2e276c78..18517af1cd 100644 --- a/lib/features/composer/presentation/manager/composer_manager.dart +++ b/lib/features/composer/presentation/manager/composer_manager.dart @@ -7,7 +7,9 @@ import 'package:get/get.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/update_screen_display_mode_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/manager/composer_timer.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; @@ -19,6 +21,8 @@ class ComposerManager extends GetxController { final ResponsiveUtils _responsiveUtils = Get.find(); + ComposerTimer? _composerTimer; + void addComposer(ComposerArguments composerArguments) { final id = DateTime.now().millisecondsSinceEpoch.toString(); log('ComposerManager::addComposer:Id = $id'); @@ -28,6 +32,8 @@ class ComposerManager extends GetxController { composerIdsQueue.add(id); _arrangeComposerIfNeeded(); + + _initializeTimerIfNeeded(); } void addListComposer(List listArguments) { @@ -49,6 +55,8 @@ class ComposerManager extends GetxController { } _arrangeComposerIfNeeded(); + + _initializeTimerIfNeeded(); } void removeComposer(String id) { @@ -60,6 +68,10 @@ class ComposerManager extends GetxController { ComposerBindings(composerId: id).dispose(); _arrangeComposerIfNeeded(); + + if (!hasComposer) { + _clearTimerIfNeeded(); + } } void _arrangeComposerIfNeeded() { @@ -293,8 +305,31 @@ class ComposerManager extends GetxController { ComposerView getComposerView(String id) => composers[id]!; + void _initializeTimerIfNeeded() { + _composerTimer ??= ComposerTimer(onTick: _handleOnTick); + + if (!_composerTimer!.isRunning) { + _composerTimer!.start(); + } + } + + void _clearTimerIfNeeded() { + _composerTimer?.stop(); + _composerTimer = null; + } + + void _handleOnTick() { + if (!hasComposer) return; + + for (var id in composerIdsQueue) { + final controller = getComposerView(id).controller; + controller.saveLocalEmailDraftAction(); + } + } + @override void onClose() { + _clearTimerIfNeeded(); composerIdsQueue.clear(); super.onClose(); } diff --git a/lib/features/composer/presentation/manager/composer_timer.dart b/lib/features/composer/presentation/manager/composer_timer.dart new file mode 100644 index 0000000000..6679def99f --- /dev/null +++ b/lib/features/composer/presentation/manager/composer_timer.dart @@ -0,0 +1,29 @@ +import 'dart:async'; +import 'dart:ui'; + +class ComposerTimer { + static const int _delaySecondTime = 15; + + Timer? _timer; + final Duration interval; + final VoidCallback onTick; + + ComposerTimer({ + required this.onTick, + this.interval = const Duration(seconds: _delaySecondTime), + }); + + void start() { + stop(); + _timer = Timer.periodic(interval, (timer) { + onTick(); + }); + } + + void stop() { + _timer?.cancel(); + _timer = null; + } + + bool get isRunning => _timer?.isActive ?? false; +} From 4a5c529e26014254c0437fe63daa829b027b1590 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 26 Mar 2025 03:14:40 +0700 Subject: [PATCH 09/10] TF-3358 Remove local email draft when `Delete, Save as draft or Send` successfully Signed-off-by: dab246 --- .../presentation/composer_controller.dart | 10 ++++++ .../local_email_draft_datasource_impl.dart | 8 ++++- .../mailbox_dashboard_controller.dart | 3 ++ .../remove_local_email_draft_extension.dart | 35 +++++++++++++++++++ .../restore_local_email_draft_extension.dart | 8 +++++ ...local_email_draft_list_dialog_builder.dart | 7 ++++ lib/l10n/intl_messages.arb | 12 +++++++ lib/main/localizations/app_localizations.dart | 14 ++++++++ 8 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index eadac6bf67..d3ca907e74 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -90,6 +90,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_ import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.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/open_and_close_composer_extension.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; @@ -871,6 +872,9 @@ class ComposerController extends BaseController log('ComposerController::_handleSendMessages: resultState = $resultState'); if (resultState is SendEmailSuccess || mailboxDashBoardController.validateSendingEmailFailedWhenNetworkIsLostOnMobile(resultState)) { _sendButtonState = ButtonState.enabled; + if (composerId != null) { + mailboxDashBoardController.removeLocalEmailDraft(composerId!); + } _closeComposerAction(result: resultState); } else if (resultState is SendEmailFailure && resultState.exception is SendingEmailCanceledException) { _sendButtonState = ButtonState.enabled; @@ -1519,6 +1523,9 @@ class ComposerController extends BaseController void handleClickDeleteComposer(BuildContext context) { clearFocus(context); + if (composerId != null) { + mailboxDashBoardController.removeLocalEmailDraft(composerId!); + } _closeComposerAction(); } @@ -1905,6 +1912,9 @@ class ComposerController extends BaseController if (resultState is SaveEmailAsDraftsSuccess || resultState is UpdateEmailDraftsSuccess) { _closeComposerButtonState = ButtonState.enabled; + if (composerId != null) { + mailboxDashBoardController.removeLocalEmailDraft(composerId!); + } _closeComposerAction(result: resultState); } else if ((resultState is SaveEmailAsDraftsFailure && resultState.exception is SavingEmailToDraftsCanceledException) || (resultState is UpdateEmailDraftsFailure && resultState.exception is SavingEmailToDraftsCanceledException)) { diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart index 03149b7333..51755c5b46 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_email_draft_datasource_impl.dart @@ -69,7 +69,13 @@ class LocalEmailDraftDataSourceImpl extends LocalEmailDraftDatasource { @override Future removeLocalEmailDraft(String draftLocalId) { return Future.sync(() async { - return await _localEmailDraftManager.removeLocalEmailDraft(draftLocalId); + final task = HiveTask( + id: draftLocalId, + runnable: () async { + return await _localEmailDraftManager.removeLocalEmailDraft(draftLocalId); + }, + ); + return _localEmailDraftWorkerQueue.addTask(task); }).catchError(_exceptionThrower.throwException); } } 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 f88c18ff33..8653caabba 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -92,6 +92,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_repor import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_local_email_draft_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_local_email_draft_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_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'; @@ -222,6 +223,7 @@ class MailboxDashBoardController extends ReloadableController GetAutoCompleteInteractor? _getAutoCompleteInteractor; IOSNotificationManager? _iosNotificationManager; GetServerSettingInteractor? getServerSettingInteractor; + RemoveLocalEmailDraftInteractor? removeLocalEmailDraftInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -321,6 +323,7 @@ class MailboxDashBoardController extends ReloadableController void onReady() { if (PlatformInfo.isWeb) { listSearchFilterScrollController = ScrollController(); + removeLocalEmailDraftInteractor = getBinding(); } if (PlatformInfo.isIOS) { _registerPendingCurrentEmailIdInNotification(); diff --git a/lib/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart new file mode 100644 index 0000000000..162db44d75 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart @@ -0,0 +1,35 @@ + +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'; +import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; + +extension RemoveLocalEmailDraftExtension on MailboxDashBoardController { + + Future removeLocalEmailDraft(String composerId) async { + if (accountId.value == null || + sessionCurrent == null || + removeLocalEmailDraftInteractor == null) return; + + final draftLocalId = _generateDraftLocalId( + composerId: composerId, + accountId: accountId.value!, + userName: sessionCurrent!.username, + ); + + await removeLocalEmailDraftInteractor!.execute(draftLocalId); + } + + String _generateDraftLocalId({ + required String composerId, + required AccountId accountId, + required UserName userName, + }) { + return TupleKey( + composerId, + accountId.asString, + userName.value, + ).encodeKey; + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index a5cecbb973..0712eacaed 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -11,6 +11,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions 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/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { @@ -68,5 +69,12 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { .toList(); openListComposer(listComposerArguments); + + if (currentOverlayContext != null && currentContext != null) { + appToast.showToastSuccessMessage( + currentOverlayContext!, + AppLocalizations.of(currentContext!).restoreAllLocalDraftsSuccessfully, + ); + } } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index b0e78ece0f..bcf96c4ea9 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -410,6 +410,13 @@ class _LocalEmailDraftListDialogBuilderState widget.session!.username, ); + if (context.mounted) { + _appToast.showToastSuccessMessage( + context, + AppLocalizations.of(context).deleteAllLocalDraftsSuccessfully, + ); + } + SmartDialog.dismiss(); popBack(); } diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 22ae61f9e0..0873efa57b 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4435,5 +4435,17 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "deleteAllLocalDraftsSuccessfully": "Delete all local drafts successfully", + "@deleteAllLocalDraftsSuccessfully": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "restoreAllLocalDraftsSuccessfully": "Restore all local drafts successfully", + "@restoreAllLocalDraftsSuccessfully": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 260afda2e1..8b26ce18a4 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4667,4 +4667,18 @@ class AppLocalizations { name: 'deletingLocalDraft', ); } + + String get deleteAllLocalDraftsSuccessfully { + return Intl.message( + 'Delete all local drafts successfully', + name: 'deleteAllLocalDraftsSuccessfully', + ); + } + + String get restoreAllLocalDraftsSuccessfully { + return Intl.message( + 'Restore all local drafts successfully', + name: 'restoreAllLocalDraftsSuccessfully', + ); + } } From 158210653a60baf80f9412b85697e51419ba28f0 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 4 Apr 2025 18:55:29 +0700 Subject: [PATCH 10/10] TF-3358 Sort list local email draft by time Signed-off-by: dab246 --- .../presentation/composer_controller.dart | 98 +++---------------- .../create_email_request_extension.dart | 4 + .../handle_local_email_draft_extension.dart | 3 + .../setup_email_attachments_extension.dart | 2 +- .../setup_email_content_extension.dart | 2 +- .../setup_email_important_flag_extension.dart | 2 +- ...etup_email_other_components_extension.dart | 2 +- .../setup_email_recipients_extension.dart | 2 +- ...l_request_read_receipt_flag_extension.dart | 2 +- .../setup_email_subject_extension.dart | 2 +- .../setup_selected_identity_extension.dart | 2 +- .../manager/composer_manager.dart | 33 +++---- .../model/composer_arguments.dart | 2 - .../data/model/local_email_draft.dart | 5 - .../local_email_draft_extension.dart | 7 ++ .../restore_local_email_draft_extension.dart | 13 ++- .../model/presentation_local_email_draft.dart | 16 +++ ...local_email_draft_list_dialog_builder.dart | 10 +- 18 files changed, 78 insertions(+), 129 deletions(-) diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index d3ca907e74..b25c76b174 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -86,8 +86,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_emai import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_by_id_on_web_interactor.dart'; -import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.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/open_and_close_composer_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/remove_local_email_draft_extension.dart'; @@ -223,7 +221,7 @@ class ComposerController extends BaseController ButtonState _saveToDraftButtonState = ButtonState.enabled; ButtonState _sendButtonState = ButtonState.enabled; ButtonState printDraftButtonState = ButtonState.enabled; - int? _savedEmailDraftHash; + int? savedEmailDraftHash; bool restoringSignatureButton = false; bool synchronizeInitDraftHash = false; GlobalKey? responsiveContainerKey; @@ -231,9 +229,6 @@ class ComposerController extends BaseController EmailActionType? savedActionType; int minInputLengthAutocomplete = AppConfig.defaultMinInputLengthAutocomplete; - @visibleForTesting - int? get savedEmailDraftHash => _savedEmailDraftHash; - GetEmailContentInteractor get getEmailContentInteractor => _getEmailContentInteractor; GetServerSettingInteractor get getServerSettingInteractor => _getServerSettingInteractor; @@ -300,7 +295,7 @@ class ComposerController extends BaseController void onClose() { _textEditorWeb = null; savedActionType = null; - _savedEmailDraftHash = null; + savedEmailDraftHash = null; currentEmailActionType = null; emailIdEditing = null; maxWithEditor = null; @@ -447,19 +442,7 @@ class ComposerController extends BaseController }); } - Future _saveLocalEmailDraftAction() async { - autoCreateEmailTag(); - - final createEmailRequest = await _generateCreateEmailRequestToSaveAsCache(); - if (createEmailRequest == null) return; - - await _saveLocalEmailDraftInteractor.execute( - createEmailRequest, - mailboxDashBoardController.accountId.value!, - mailboxDashBoardController.sessionCurrent!.username); - } - - Uri? _getUploadUriFromSession(Session session, AccountId accountId) { + Uri? getUploadUriFromSession(Session session, AccountId accountId) { try { return session.getUploadUri(accountId, jmapUrl: dynamicUrlInterceptors.jmapUrl); } catch (e) { @@ -468,63 +451,6 @@ class ComposerController extends BaseController } } - Future _generateCreateEmailRequestToSaveAsCache() async { - final arguments = composerArguments.value; - final session = mailboxDashBoardController.sessionCurrent; - final accountId = mailboxDashBoardController.accountId.value; - - if (arguments == null || session == null || accountId == null) { - log('ComposerController::_generateCreateEmailRequest: SESSION or ACCOUNT_ID or ARGUMENTS is NULL'); - return null; - } - - String emailContent = await getContentInEditor(); - if (currentEmailActionType == EmailActionType.compose) { - emailContent = await _composerRepository.removeCollapsedExpandedSignatureEffect( - emailContent: emailContent, - ); - } - final uploadUri = _getUploadUriFromSession(session, accountId); - - final composerIndex = composerId != null - ? mailboxDashBoardController.composerManager.getComposerIndex(composerId!) - : null; - - return CreateEmailRequest( - session: session, - accountId: accountId, - emailActionType: arguments.emailActionType, - subject: subjectEmail.value ?? '', - emailContent: emailContent, - fromSender: arguments.presentationEmail?.from ?? {}, - toRecipients: listToEmailAddress.toSet(), - ccRecipients: listCcEmailAddress.toSet(), - bccRecipients: listBccEmailAddress.toSet(), - replyToRecipients: listReplyToEmailAddress.toSet(), - hasRequestReadReceipt: hasRequestReadReceipt.value, - isMarkAsImportant: isMarkAsImportant.value, - identity: identitySelected.value, - attachments: uploadController.attachmentsUploaded, - inlineAttachments: uploadController.mapInlineAttachments, - outboxMailboxId: getOutboxMailboxIdForComposer(), - sentMailboxId: getSentMailboxIdForComposer(), - draftsMailboxId: getDraftMailboxIdForComposer(), - draftsEmailId: getDraftEmailId(), - answerForwardEmailId: arguments.presentationEmail?.id, - unsubscribeEmailId: arguments.previousEmailId, - messageId: arguments.messageId, - references: arguments.references, - emailSendingQueue: arguments.sendingEmail, - displayMode: screenDisplayMode.value, - uploadUri: uploadUri, - composerIndex: composerIndex, - composerId: composerId, - savedDraftHash: arguments.savedDraftHash ?? _savedEmailDraftHash, - savedActionType: savedActionType ?? currentEmailActionType, - savedEmailDraftId: emailIdEditing, - ); - } - void _scrollControllerEmailAddressListener() { if (toEmailAddressController.text.isNotEmpty) { keyToEmailTagEditor.currentState?.closeSuggestionBox(); @@ -1101,8 +1027,8 @@ class ComposerController extends BaseController Future _validateEmailChange() async { final newDraftHash = await _hashDraftEmail(); - log('ComposerController::_validateEmailChange:newDraftHash = $newDraftHash | _savedEmailDraftHash = $_savedEmailDraftHash'); - return _savedEmailDraftHash != newDraftHash; + log('ComposerController::_validateEmailChange:newDraftHash = $newDraftHash | savedEmailDraftHash = $savedEmailDraftHash'); + return savedEmailDraftHash != newDraftHash; } Future _hashDraftEmail() async { @@ -1113,7 +1039,7 @@ class ComposerController extends BaseController ); if (emailIdEditing != null && savedActionType == EmailActionType.compose && - currentEmailActionType == EmailActionType.reopenComposerBrowser) { + currentEmailActionType == EmailActionType.composeFromLocalEmailDraft) { emailContent = await _composerRepository.removeStyleLazyLoadDisplayInlineImages( emailContent: emailContent, ); @@ -1138,7 +1064,7 @@ class ComposerController extends BaseController } Future _updateSavedEmailDraftHash() async { - _savedEmailDraftHash = await _hashDraftEmail(); + savedEmailDraftHash = await _hashDraftEmail(); } Future initEmailDraftHash() async { @@ -1148,13 +1074,13 @@ class ComposerController extends BaseController if (currentEmailActionType == EmailActionType.compose || currentEmailActionType == EmailActionType.editDraft) { - _savedEmailDraftHash = currentDraftHash; - } else if (currentEmailActionType == EmailActionType.reopenComposerBrowser) { - _savedEmailDraftHash = oldSavedDraftHash; + savedEmailDraftHash = currentDraftHash; + } else if (currentEmailActionType == EmailActionType.composeFromLocalEmailDraft) { + savedEmailDraftHash = oldSavedDraftHash; } - log('ComposerController::initEmailDraftHash:oldSavedDraftHash = $oldSavedDraftHash | currentDraftHash = $currentDraftHash | _savedEmailDraftHash = $_savedEmailDraftHash'); + log('ComposerController::initEmailDraftHash:oldSavedDraftHash = $oldSavedDraftHash | currentDraftHash = $currentDraftHash | savedEmailDraftHash = $savedEmailDraftHash'); - isEmailChanged.value = currentDraftHash != _savedEmailDraftHash; + isEmailChanged.value = currentDraftHash != savedEmailDraftHash; } void handleClickSaveAsDraftsButton(BuildContext context) async { diff --git a/lib/features/composer/presentation/extensions/create_email_request_extension.dart b/lib/features/composer/presentation/extensions/create_email_request_extension.dart index b916998fea..3e63380976 100644 --- a/lib/features/composer/presentation/extensions/create_email_request_extension.dart +++ b/lib/features/composer/presentation/extensions/create_email_request_extension.dart @@ -14,6 +14,7 @@ import 'package:model/email/mail_priority_header.dart'; import 'package:model/extensions/account_id_extensions.dart'; import 'package:model/extensions/email_address_extension.dart'; import 'package:model/extensions/email_extension.dart'; +import 'package:model/extensions/email_id_extensions.dart'; import 'package:model/extensions/session_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; @@ -223,6 +224,9 @@ extension CreateEmailRequestExtension on CreateEmailRequest { isMarkAsImportant: isMarkAsImportant, displayMode: displayMode.name, composerIndex: composerIndex, + draftHash: savedDraftHash, + actionType: savedActionType?.name, + draftEmailId: savedEmailDraftId?.asString, ); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart index b09f5e681b..a12e8dbf9e 100644 --- a/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart +++ b/lib/features/composer/presentation/extensions/handle_local_email_draft_extension.dart @@ -51,6 +51,9 @@ extension HandleLocalEmailDraftExtension on ComposerController { uploadUri: uploadUri, composerIndex: composerIndex, composerId: composerId, + savedDraftHash: arguments.savedDraftHash ?? savedEmailDraftHash, + savedActionType: savedActionType ?? currentEmailActionType, + savedEmailDraftId: emailIdEditing, ); } diff --git a/lib/features/composer/presentation/extensions/setup_email_attachments_extension.dart b/lib/features/composer/presentation/extensions/setup_email_attachments_extension.dart index f75a3cf2f5..eb58758ca0 100644 --- a/lib/features/composer/presentation/extensions/setup_email_attachments_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_attachments_extension.dart @@ -35,7 +35,7 @@ extension SetupEmailAttachmentsExtension on ComposerController { attachments = arguments.attachments; inlineImages = arguments.inlineImages; break; - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: attachments = arguments.attachments; inlineImages = arguments.inlineImages; break; diff --git a/lib/features/composer/presentation/extensions/setup_email_content_extension.dart b/lib/features/composer/presentation/extensions/setup_email_content_extension.dart index e0cd6cc6ea..28c5feff12 100644 --- a/lib/features/composer/presentation/extensions/setup_email_content_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_content_extension.dart @@ -162,7 +162,7 @@ extension SetupEmailContentExtension on ComposerController { } } break; - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: final inlineImages = arguments.inlineImages ?? []; final content = arguments.emailContents ?? ''; final displayMode = arguments.displayMode; diff --git a/lib/features/composer/presentation/extensions/setup_email_important_flag_extension.dart b/lib/features/composer/presentation/extensions/setup_email_important_flag_extension.dart index c3921306bd..82c11d1ea0 100644 --- a/lib/features/composer/presentation/extensions/setup_email_important_flag_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_important_flag_extension.dart @@ -11,7 +11,7 @@ extension SetupEmailImportantFlagExtension on ComposerController { case EmailActionType.editDraft: isMarkAsImportant.value = arguments.presentationEmail?.isMarkAsImportant ?? false; break; - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: isMarkAsImportant.value = arguments.isMarkAsImportant ?? false; break; default: diff --git a/lib/features/composer/presentation/extensions/setup_email_other_components_extension.dart b/lib/features/composer/presentation/extensions/setup_email_other_components_extension.dart index ab321761b2..8eaf5af42d 100644 --- a/lib/features/composer/presentation/extensions/setup_email_other_components_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_other_components_extension.dart @@ -13,7 +13,7 @@ extension SetupEmailOtherComponentsExtension on ComposerController { case EmailActionType.editSendingEmail: emailIdEditing = arguments.sendingEmail?.presentationEmail.id; break; - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: screenDisplayMode.value = arguments.displayMode; break; default: diff --git a/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart b/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart index 03dc63bcaa..d7342a4bc3 100644 --- a/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_recipients_extension.dart @@ -11,7 +11,7 @@ extension SetupEmailRecipientsExtension on ComposerController { switch(currentEmailActionType) { case EmailActionType.editAsNewEmail: case EmailActionType.editDraft: - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: initEmailAddress( presentationEmail: arguments.presentationEmail!, actionType: currentEmailActionType!, diff --git a/lib/features/composer/presentation/extensions/setup_email_request_read_receipt_flag_extension.dart b/lib/features/composer/presentation/extensions/setup_email_request_read_receipt_flag_extension.dart index 44a62ea110..b98a46e32c 100644 --- a/lib/features/composer/presentation/extensions/setup_email_request_read_receipt_flag_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_request_read_receipt_flag_extension.dart @@ -8,7 +8,7 @@ import 'package:tmail_ui_user/features/server_settings/domain/state/get_server_s extension SetupEmailRequestReadReceiptFlagExtension on ComposerController { void setupEmailRequestReadReceiptFlag(ComposerArguments arguments) { - if (currentEmailActionType == EmailActionType.reopenComposerBrowser) { + if (currentEmailActionType == EmailActionType.composeFromLocalEmailDraft) { hasRequestReadReceipt.value = arguments.hasRequestReadReceipt ?? false; } else if (currentEmailActionType != EmailActionType.editDraft) { getServerSetting(); diff --git a/lib/features/composer/presentation/extensions/setup_email_subject_extension.dart b/lib/features/composer/presentation/extensions/setup_email_subject_extension.dart index ff5a8c505b..cd46052fca 100644 --- a/lib/features/composer/presentation/extensions/setup_email_subject_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_email_subject_extension.dart @@ -17,7 +17,7 @@ extension SetupEmailSubjectExtension on ComposerController { case EmailActionType.replyToList: case EmailActionType.replyAll: case EmailActionType.forward: - case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromLocalEmailDraft: subject = arguments.presentationEmail!.getEmailTitle().trim(); break; case EmailActionType.editSendingEmail: diff --git a/lib/features/composer/presentation/extensions/setup_selected_identity_extension.dart b/lib/features/composer/presentation/extensions/setup_selected_identity_extension.dart index 5203ec22ce..076812883f 100644 --- a/lib/features/composer/presentation/extensions/setup_selected_identity_extension.dart +++ b/lib/features/composer/presentation/extensions/setup_selected_identity_extension.dart @@ -30,7 +30,7 @@ extension SetupSelectedIdentityExtension on ComposerController { ) ?? listFromIdentities.first; if (currentEmailActionType == EmailActionType.editDraft || - currentEmailActionType == EmailActionType.reopenComposerBrowser && + currentEmailActionType == EmailActionType.composeFromLocalEmailDraft && savedActionType == EmailActionType.editDraft) { identitySelected.value = currentIdentity; } else if (currentEmailActionType == EmailActionType.editAsNewEmail) { diff --git a/lib/features/composer/presentation/manager/composer_manager.dart b/lib/features/composer/presentation/manager/composer_manager.dart index 18517af1cd..3e5c425d8a 100644 --- a/lib/features/composer/presentation/manager/composer_manager.dart +++ b/lib/features/composer/presentation/manager/composer_manager.dart @@ -23,39 +23,30 @@ class ComposerManager extends GetxController { ComposerTimer? _composerTimer; - void addComposer(ComposerArguments composerArguments) { - final id = DateTime.now().millisecondsSinceEpoch.toString(); + void addComposer(ComposerArguments composerArguments, {bool isSynchronous = true}) { + final id = composerArguments.composerId + ?? DateTime.now().millisecondsSinceEpoch.toString(); log('ComposerManager::addComposer:Id = $id'); - ComposerBindings(composerId: id, composerArguments: composerArguments).dependencies(); + ComposerBindings( + composerId: id, + composerArguments: composerArguments, + ).dependencies(); composers[id] = ComposerView(key: Key(id), composerId: id); composerIdsQueue.add(id); - _arrangeComposerIfNeeded(); - - _initializeTimerIfNeeded(); + if (isSynchronous) { + _arrangeComposerIfNeeded(); + _initializeTimerIfNeeded(); + } } void addListComposer(List listArguments) { for (var argument in listArguments) { - final composerId = argument.composerId; - - if (composerId == null) continue; - - ComposerBindings( - composerId: composerId, - composerArguments: argument, - ).dependencies(); - - composers[composerId] = ComposerView( - key: Key(composerId), - composerId: composerId, - ); - composerIdsQueue.add(composerId); + addComposer(argument, isSynchronous: false); } _arrangeComposerIfNeeded(); - _initializeTimerIfNeeded(); } diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 6692dbc8b2..9256774d73 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -4,9 +4,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; - import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart'; diff --git a/lib/features/mailbox_dashboard/data/model/local_email_draft.dart b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart index be52239b28..4c5ee6983e 100644 --- a/lib/features/mailbox_dashboard/data/model/local_email_draft.dart +++ b/lib/features/mailbox_dashboard/data/model/local_email_draft.dart @@ -1,11 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:hive/hive.dart'; import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart'; -import 'package:jmap_dart_client/http/converter/email_id_nullable_converter.dart'; -import 'package:jmap_dart_client/jmap/mail/email/email.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:model/email/email_action_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; part 'local_email_draft.g.dart'; diff --git a/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart index 328caff142..36aeefc0fa 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/local_email_draft_extension.dart @@ -2,7 +2,9 @@ import 'dart:convert'; import 'package:collection/collection.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:model/email/email_action_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/local_email_draft.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart'; @@ -20,6 +22,11 @@ extension LocalEmailDraftExtension on LocalEmailDraft { (type) => type.name == displayMode, ) ?? ScreenDisplayMode.normal, composerIndex: composerIndex, + draftHash: draftHash, + actionType: EmailActionType.values.firstWhereOrNull( + (type) => type.name == actionType, + ), + draftEmailId: draftEmailId != null ? EmailId(Id(draftEmailId!)) : null, ); } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart index 0712eacaed..10eaafb601 100644 --- a/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart +++ b/lib/features/mailbox_dashboard/presentation/extensions/restore_local_email_draft_extension.dart @@ -33,10 +33,11 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { final listPresentationLocalEmailDraft = localEmailDrafts .map((localEmailDraft) => localEmailDraft.toPresentation()) .toList(); - final listLocalEmailDraftSortByIndex = listPresentationLocalEmailDraft - ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); - showLocalEmailDraftListDialog(listLocalEmailDraftSortByIndex); + final listLocalEmailDraftSortByTime = listPresentationLocalEmailDraft + ..sort((a, b) => b.savedTime.compareTo(a.savedTime)); + + showLocalEmailDraftListDialog(listLocalEmailDraftSortByTime); } void showLocalEmailDraftListDialog(List presentationLocalEmailDrafts) { @@ -64,7 +65,11 @@ extension RestoreLocalEmailDraftExtension on MailboxDashBoardController { void _restoreAllLocalEmailDrafts(List localDrafts) { popBack(); - final listComposerArguments = localDrafts + + final listLocalEmailDraftSortByIndex = localDrafts + ..sort((a, b) => (a.composerIndex ?? 0).compareTo(b.composerIndex ?? 0)); + + final listComposerArguments = listLocalEmailDraftSortByIndex .map(ComposerArguments.fromLocalEmailDraft) .toList(); diff --git a/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart index b77c88f28c..1c8293c0de 100644 --- a/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart +++ b/lib/features/mailbox_dashboard/presentation/model/presentation_local_email_draft.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:model/email/email_action_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; class PresentationLocalEmailDraft with EquatableMixin { @@ -12,6 +13,9 @@ class PresentationLocalEmailDraft with EquatableMixin { final bool? isMarkAsImportant; final ScreenDisplayMode displayMode; final int? composerIndex; + final int? draftHash; + final EmailActionType? actionType; + final EmailId? draftEmailId; PresentationLocalEmailDraft({ required this.id, @@ -22,6 +26,9 @@ class PresentationLocalEmailDraft with EquatableMixin { this.isMarkAsImportant, this.displayMode = ScreenDisplayMode.normal, this.composerIndex, + this.draftHash, + this.actionType, + this.draftEmailId, }); PresentationLocalEmailDraft copyWith({ @@ -33,6 +40,9 @@ class PresentationLocalEmailDraft with EquatableMixin { bool? isMarkAsImportant, ScreenDisplayMode? displayMode, int? composerIndex, + int? draftHash, + EmailActionType? actionType, + EmailId? draftEmailId, }) => PresentationLocalEmailDraft( id: id ?? this.id, composerId: composerId ?? this.composerId, @@ -42,6 +52,9 @@ class PresentationLocalEmailDraft with EquatableMixin { isMarkAsImportant: isMarkAsImportant ?? this.isMarkAsImportant, displayMode: displayMode ?? this.displayMode, composerIndex: composerIndex ?? this.composerIndex, + draftHash: draftHash ?? this.draftHash, + actionType: actionType ?? this.actionType, + draftEmailId: draftEmailId ?? this.draftEmailId, ); @override @@ -54,5 +67,8 @@ class PresentationLocalEmailDraft with EquatableMixin { displayMode, composerIndex, composerId, + draftHash, + actionType, + draftEmailId, ]; } diff --git a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart index bcf96c4ea9..38c1258efb 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/local_email_draft/local_email_draft_list_dialog_builder.dart @@ -279,13 +279,17 @@ class _LocalEmailDraftListDialogBuilderState ); } - Future _removeLocalEmailDraft(BuildContext context, String draftLocalId) async { + Future _removeLocalEmailDraft( + BuildContext context, + String draftLocalId, + {bool showToast = true} + ) async { _listLocalEmailDraftsNotifier.value = List.from(_listLocalEmailDraftsNotifier.value) ..removeWhere((draftLocal) => draftLocal.id == draftLocalId); await _removeLocalEmailDraftInteractor?.execute(draftLocalId); - if (context.mounted) { + if (showToast && context.mounted) { _appToast.showToastSuccessMessage( context, AppLocalizations.of(context).deleteLocalDraftSuccessfully, @@ -323,7 +327,7 @@ class _LocalEmailDraftListDialogBuilderState leadingSVGIconColor: Colors.white, ); - _removeLocalEmailDraft(context, draftLocal.id); + _removeLocalEmailDraft(context, draftLocal.id, showToast: false); } else if (resultState is SaveEmailAsDraftsFailure) { final errorMessage = getMessageFailure( appLocalizations: AppLocalizations.of(context),