diff --git a/lib/features/composer/domain/usecases/save_email_as_drafts_interactor.dart b/lib/features/composer/domain/usecases/save_email_as_drafts_interactor.dart index cddb85c59..e20c53868 100644 --- a/lib/features/composer/domain/usecases/save_email_as_drafts_interactor.dart +++ b/lib/features/composer/domain/usecases/save_email_as_drafts_interactor.dart @@ -12,11 +12,11 @@ class SaveEmailAsDraftsInteractor { Stream> execute(AccountId accountId, Email email) async* { try { - final result = await emailRepository.saveEmailAsDrafts(accountId, email); - if (result) { - yield Right(SaveEmailAsDraftsSuccess(email)); + final emailAsDrafts = await emailRepository.saveEmailAsDrafts(accountId, email); + if (emailAsDrafts != null) { + yield Right(SaveEmailAsDraftsSuccess(emailAsDrafts)); } else { - yield Left(SaveEmailAsDraftsFailure(result)); + yield Left(SaveEmailAsDraftsFailure(null)); } } catch (e) { yield Left(SaveEmailAsDraftsFailure(e)); diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart index 12ab6c938..f06e43b37 100644 --- a/lib/features/composer/presentation/composer_bindings.dart +++ b/lib/features/composer/presentation/composer_bindings.dart @@ -58,6 +58,7 @@ class ComposerBindings extends BaseBindings { Get.lazyPut(() => AutoCompleteDataSourceImpl()); Get.lazyPut(() => LocalAutoCompleteDataSourceImpl(Get.find())); Get.lazyPut(() => ContactDataSourceImpl()); + Get.lazyPut(() => EmailDataSourceImpl(Get.find())); Get.lazyPut(() => HtmlDataSourceImpl( Get.find(), Get.find() @@ -84,7 +85,6 @@ class ComposerBindings extends BaseBindings { DataSourceType.local: Get.find(), })); Get.lazyPut(() => ContactRepositoryImpl(Get.find())); - Get.lazyPut(() => EmailDataSourceImpl(Get.find())); Get.lazyPut(() => EmailRepositoryImpl( Get.find(), Get.find() @@ -97,7 +97,6 @@ class ComposerBindings extends BaseBindings { Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); - } @override diff --git a/lib/features/email/data/datasource/email_datasource.dart b/lib/features/email/data/datasource/email_datasource.dart index 0c6ea0e5c..5ca62ccd2 100644 --- a/lib/features/email/data/datasource/email_datasource.dart +++ b/lib/features/email/data/datasource/email_datasource.dart @@ -35,5 +35,7 @@ abstract class EmailDataSource { MarkStarAction markStarAction ); - Future saveEmailAsDrafts(AccountId accountId, Email email); + Future saveEmailAsDrafts(AccountId accountId, Email email); + + Future removeEmailDrafts(AccountId accountId, EmailId emailId); } \ No newline at end of file diff --git a/lib/features/email/data/datasource_impl/email_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_datasource_impl.dart index 41847d7a0..7daed804c 100644 --- a/lib/features/email/data/datasource_impl/email_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_datasource_impl.dart @@ -88,11 +88,20 @@ class EmailDataSourceImpl extends EmailDataSource { } @override - Future saveEmailAsDrafts(AccountId accountId, Email email) { + Future saveEmailAsDrafts(AccountId accountId, Email email) { return Future.sync(() async { return await emailAPI.saveEmailAsDrafts(accountId, email); }).catchError((error) { throw error; }); } + + @override + Future removeEmailDrafts(AccountId accountId, EmailId emailId) { + return Future.sync(() async { + return await emailAPI.removeEmailDrafts(accountId, emailId); + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 1ea5f58b1..7b8806dd7 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -254,7 +254,7 @@ class EmailAPI { }); } - Future saveEmailAsDrafts(AccountId accountId, Email email) async { + Future saveEmailAsDrafts(AccountId accountId, Email email) async { final setEmailMethod = SetEmailMethod(accountId) ..addCreate(email.id.id, email); @@ -272,7 +272,31 @@ class EmailAPI { SetEmailResponse.deserialize); return Future.sync(() async { - return setEmailResponse?.created?[email.id.id] != null; + return setEmailResponse?.created?[email.id.id]; + }).catchError((error) { + throw error; + }); + } + + Future removeEmailDrafts(AccountId accountId, EmailId emailId) async { + final setEmailMethod = SetEmailMethod(accountId) + ..addDestroy({emailId.id}); + + final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); + + final setEmailInvocation = requestBuilder.invocation(setEmailMethod); + + final response = await (requestBuilder + ..usings(setEmailMethod.requiredCapabilities)) + .build() + .execute(); + + final setEmailResponse = response.parse( + setEmailInvocation.methodCallId, + SetEmailResponse.deserialize); + + return Future.sync(() async { + return setEmailResponse?.destroyed?.contains(emailId.id) == true; }).catchError((error) { throw error; }); diff --git a/lib/features/email/data/repository/email_repository_impl.dart b/lib/features/email/data/repository/email_repository_impl.dart index 677ad7c60..45ecfc1e7 100644 --- a/lib/features/email/data/repository/email_repository_impl.dart +++ b/lib/features/email/data/repository/email_repository_impl.dart @@ -90,7 +90,12 @@ class EmailRepositoryImpl extends EmailRepository { } @override - Future saveEmailAsDrafts(AccountId accountId, Email email) { + Future saveEmailAsDrafts(AccountId accountId, Email email) { return emailDataSource.saveEmailAsDrafts(accountId, email); } + + @override + Future removeEmailDrafts(AccountId accountId, EmailId emailId) { + return emailDataSource.removeEmailDrafts(accountId, emailId); + } } \ No newline at end of file diff --git a/lib/features/email/domain/repository/email_repository.dart b/lib/features/email/domain/repository/email_repository.dart index 2db16ed73..04cc13d53 100644 --- a/lib/features/email/domain/repository/email_repository.dart +++ b/lib/features/email/domain/repository/email_repository.dart @@ -42,5 +42,7 @@ abstract class EmailRepository { AccountId accountId ); - Future saveEmailAsDrafts(AccountId accountId, Email email); + Future saveEmailAsDrafts(AccountId accountId, Email email); + + Future removeEmailDrafts(AccountId accountId, EmailId emailId); } \ No newline at end of file diff --git a/lib/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart b/lib/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart index 1e2186c10..f4f7458c8 100644 --- a/lib/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart +++ b/lib/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart @@ -32,17 +32,18 @@ class BottomBarMailWidgetBuilder { color: Colors.white, child: MediaQuery( data: MediaQueryData(padding: EdgeInsets.zero), - child: _presentationEmail != null ? _buildListOptionButton() : SizedBox.shrink() + child: _presentationEmail != null ? _buildListOptionButton(_presentationEmail!) : SizedBox.shrink() ) ); } - Widget _buildListOptionButton() { + Widget _buildListOptionButton(PresentationEmail presentationEmail) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ - (ButtonBuilder(_imagePaths.icReplyAllV2) + if (presentationEmail.numberOfAllEmailAddress() > 1) + (ButtonBuilder(_imagePaths.icReplyAllV2) ..key(Key('button_reply_all_message')) ..size(20) ..paddingIcon(EdgeInsets.only( diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 214ed5f16..33d243fd1 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -9,6 +9,7 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; @@ -22,6 +23,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_b import 'package:tmail_ui_user/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/mailbox_creator_arguments.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart'; @@ -84,6 +86,10 @@ class MailboxController extends BaseController { || success is MoveMultipleEmailToMailboxHasSomeEmailFailure) { mailboxDashBoardController.clearState(); refreshMailboxChanges(); + } else if (success is SaveEmailAsDraftsSuccess) { + refreshMailboxChanges(); + } else if (success is RemoveEmailDraftsSuccess) { + refreshMailboxChanges(); } }); }); diff --git a/lib/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart b/lib/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart new file mode 100644 index 000000000..ce7adb567 --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart @@ -0,0 +1,18 @@ +import 'package:core/core.dart'; + +class RemoveEmailDraftsSuccess extends UIState { + + RemoveEmailDraftsSuccess(); + + @override + List get props => []; +} + +class RemoveEmailDraftsFailure extends FeatureFailure { + final exception; + + RemoveEmailDraftsFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart new file mode 100644 index 000000000..9f80c2900 --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart @@ -0,0 +1,25 @@ +import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; + +class RemoveEmailDraftsInteractor { + final EmailRepository emailRepository; + + RemoveEmailDraftsInteractor(this.emailRepository); + + Stream> execute(AccountId accountId, EmailId emailId) async* { + try { + final result = await emailRepository.removeEmailDrafts(accountId, emailId); + if (result) { + yield Right(RemoveEmailDraftsSuccess()); + } else { + yield Left(RemoveEmailDraftsFailure(result)); + } + } catch (e) { + yield Left(RemoveEmailDraftsFailure(e)); + } + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart index fbf0843db..cb8cb90fe 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart @@ -1,30 +1,77 @@ import 'package:core/core.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tmail_ui_user/features/base/base_bindings.dart'; +import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; +import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart'; +import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart'; +import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasource_impl.dart'; +import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart'; +import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; +import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart'; +import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/email/presentation/email_bindings.dart'; import 'package:tmail_ui_user/features/login/data/repository/credential_repository_impl.dart'; import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_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/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_bindings.dart'; -class MailboxDashBoardBindings extends Bindings { +class MailboxDashBoardBindings extends BaseBindings { @override void dependencies() { - Get.lazyPut(() => CredentialRepositoryImpl(Get.find())); - Get.lazyPut(() => Get.find()); - Get.lazyPut(() => GetUserProfileInteractor(Get.find())); - - Get.put(MailboxDashBoardController( - Get.find(), - Get.find(), - Get.find(), - )); - + super.dependencies(); MailboxBindings().dependencies(); ThreadBindings().dependencies(); EmailBindings().dependencies(); } + + @override + void bindingsController() { + Get.put(MailboxDashBoardController( + Get.find(), + Get.find(), + Get.find(), + Get.find(), + )); + } + + @override + void bindingsDataSource() { + Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); + } + + @override + void bindingsDataSourceImpl() { + Get.lazyPut(() => EmailDataSourceImpl(Get.find())); + Get.lazyPut(() => HtmlDataSourceImpl( + Get.find(), + Get.find() + )); + } + + @override + void bindingsInteractor() { + Get.lazyPut(() => GetUserProfileInteractor(Get.find())); + Get.lazyPut(() => RemoveEmailDraftsInteractor(Get.find())); + } + + @override + void bindingsRepository() { + Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); + } + + @override + void bindingsRepositoryImpl() { + Get.lazyPut(() => CredentialRepositoryImpl(Get.find())); + Get.lazyPut(() => EmailRepositoryImpl( + Get.find(), + Get.find() + )); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart index 19ec74e36..8a36e46d7 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart @@ -4,6 +4,7 @@ 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/session/session.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; @@ -11,7 +12,9 @@ import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_draft import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/email/presentation/email_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_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_user_profile_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart'; import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart'; @@ -23,6 +26,7 @@ class MailboxDashBoardController extends BaseController { final GetUserProfileInteractor _getUserProfileInteractor; final AppToast _appToast; final ImagePaths _imagePaths; + final RemoveEmailDraftsInteractor _removeEmailDraftsInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -43,6 +47,7 @@ class MailboxDashBoardController extends BaseController { this._getUserProfileInteractor, this._appToast, this._imagePaths, + this._removeEmailDraftsInteractor, ); @override @@ -96,6 +101,9 @@ class MailboxDashBoardController extends BaseController { clearState(); } else if (success is SaveEmailAsDraftsSuccess) { _saveEmailAsDraftsSuccess(success); + clearState(); + } else if (success is RemoveEmailDraftsSuccess) { + clearState(); } } ); @@ -199,11 +207,18 @@ class MailboxDashBoardController extends BaseController { Get.overlayContext!, AppLocalizations.of(Get.context!).drafts_saved, AppLocalizations.of(Get.context!).discard, - () {} + () => _discardEmail(success.emailAsDrafts) ); } } + void _discardEmail(Email email) { + final currentAccountId = accountId.value; + if (currentAccountId != null) { + consumeState(_removeEmailDraftsInteractor.execute(currentAccountId, email.id)); + } + } + @override void onClose() { searchInputController.dispose(); diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 0febc8d79..f6bf4b0be 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -14,6 +14,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_request.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart'; @@ -22,6 +23,7 @@ import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state. import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; @@ -132,6 +134,10 @@ class ThreadController extends BaseController { mailboxDashBoardController.clearState(); } else if (success is SearchEmailNewQuery){ _searchEmail(); + } else if (success is SaveEmailAsDraftsSuccess + || success is RemoveEmailDraftsSuccess) { + cancelSelectEmail(); + _refreshEmailChanges(); } }); });