From 85e54357ce83867fa0e47ddc344ccd601753e78a Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 1 Jun 2022 17:24:07 +0700 Subject: [PATCH] TF-599 Handle move mailbox action for mailbox --- .../destination_picker_controller.dart | 12 ++- .../presentation/destination_picker_view.dart | 61 ++++++++++++--- .../model/destination_picker_arguments.dart | 6 +- .../app_bar_destination_picker_builder.dart | 2 +- .../data/datasource/mailbox_datasource.dart | 3 + .../mailbox_cache_datasource_impl.dart | 6 ++ .../mailbox_datasource_impl.dart | 10 +++ .../mailbox/data/network/mailbox_api.dart | 29 +++++++ .../repository/mailbox_repository_impl.dart | 6 ++ .../domain/model/move_mailbox_request.dart | 32 ++++++++ .../domain/repository/mailbox_repository.dart | 3 + .../domain/state/move_mailbox_state.dart | 45 +++++++++++ .../usecases/move_mailbox_interactor.dart | 30 ++++++++ .../presentation/mailbox_bindings.dart | 3 + .../presentation/mailbox_controller.dart | 77 ++++++++++++++++++- .../presentation/model/mailbox_actions.dart | 2 + .../widgets/mailbox_folder_tile_builder.dart | 2 +- lib/l10n/intl_messages.arb | 8 +- lib/main/localizations/app_localizations.dart | 6 ++ 19 files changed, 325 insertions(+), 18 deletions(-) create mode 100644 lib/features/mailbox/domain/model/move_mailbox_request.dart create mode 100644 lib/features/mailbox/domain/state/move_mailbox_state.dart create mode 100644 lib/features/mailbox/domain/usecases/move_mailbox_interactor.dart diff --git a/lib/features/destination_picker/presentation/destination_picker_controller.dart b/lib/features/destination_picker/presentation/destination_picker_controller.dart index dc436bc9c..e71856b49 100644 --- a/lib/features/destination_picker/presentation/destination_picker_controller.dart +++ b/lib/features/destination_picker/presentation/destination_picker_controller.dart @@ -4,6 +4,7 @@ import 'package:dartz/dartz.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; @@ -30,6 +31,7 @@ class DestinationPickerController extends BaseMailboxController { final searchQuery = SearchQuery.initial().obs; final mailboxCategoriesExpandMode = MailboxCategoriesExpandMode.initial().obs; + MailboxId? mailboxIdSelected; AccountId? accountId; final searchInputController = TextEditingController(); final searchFocus = FocusNode(); @@ -46,6 +48,7 @@ class DestinationPickerController extends BaseMailboxController { final arguments = Get.arguments; if (arguments != null && arguments is DestinationPickerArguments) { mailboxAction.value = arguments.mailboxAction; + mailboxIdSelected = arguments.mailboxIdSelected; accountId = arguments.accountId; getAllMailboxAction(); } @@ -56,7 +59,14 @@ class DestinationPickerController extends BaseMailboxController { super.onData(newState); newState.map((success) { if (success is GetAllMailboxSuccess) { - buildTree(success.mailboxList); + if (mailboxAction.value == MailboxActions.move && mailboxIdSelected != null) { + final newMailboxList = success.mailboxList + .where((mailbox) => mailbox.id != mailboxIdSelected) + .toList(); + buildTree(newMailboxList); + } else { + buildTree(success.mailboxList); + } } }); } diff --git a/lib/features/destination_picker/presentation/destination_picker_view.dart b/lib/features/destination_picker/presentation/destination_picker_view.dart index dbc4bbc23..34ac5abc7 100644 --- a/lib/features/destination_picker/presentation/destination_picker_view.dart +++ b/lib/features/destination_picker/presentation/destination_picker_view.dart @@ -141,7 +141,7 @@ class DestinationPickerView extends GetWidget Widget _buildSearchBarWidget(BuildContext context) { return Padding( padding: EdgeInsets.only( - top: _responsiveUtils.isScreenWithShortestSide(context) || kIsWeb ? 12 : 0, + top: _responsiveUtils.isScreenWithShortestSide(context) || BuildUtils.isWeb ? 12 : 0, left: _responsiveUtils.isLandscapeMobile(context) ? 0 : 16, right: 16), child: (SearchBarView(_imagePaths) @@ -174,17 +174,19 @@ class DestinationPickerView extends GetWidget primary: false, shrinkWrap: true, children: [ - if (actions == MailboxActions.moveEmail) _buildSearchBarWidget(context), + if (actions == MailboxActions.moveEmail || actions == MailboxActions.move) + _buildSearchBarWidget(context), _buildLoadingView(), if (actions == MailboxActions.create && !BuildUtils.isWeb && _responsiveUtils.isScreenWithShortestSide(context)) const SizedBox(height: 12), - if (actions == MailboxActions.create) _buildUnifiedMailbox(context), + if (actions == MailboxActions.create || actions == MailboxActions.move) + _buildUnifiedMailbox(context, actions), const SizedBox(height: 12), Obx(() => controller.defaultMailboxHasChild ? _buildMailboxCategory(context, MailboxCategories.exchange, controller.defaultRootNode, actions) : const SizedBox.shrink()), if (actions == MailboxActions.create) const SizedBox(height: 12), - if (actions != MailboxActions.create && !kIsWeb) + if (actions != MailboxActions.create && !BuildUtils.isWeb) const Padding( padding: EdgeInsets.only(left: 60), child: Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)), @@ -197,7 +199,7 @@ class DestinationPickerView extends GetWidget } Widget _buildMailboxCategory(BuildContext context, MailboxCategories categories, MailboxNode mailboxNode, MailboxActions? actions) { - if (actions == MailboxActions.moveEmail) { + if (actions == MailboxActions.moveEmail || actions == MailboxActions.move) { return _buildBodyMailboxCategory(context, categories, mailboxNode, actions); } return Column(children: [ @@ -237,12 +239,18 @@ class DestinationPickerView extends GetWidget return Container( decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white), margin: EdgeInsets.only( - left: actions == MailboxActions.moveEmail ? 8 : _responsiveUtils.isLandscapeMobile(context) ? 0 : 16, - right: actions == MailboxActions.moveEmail ? 0 : 16), + left: actions == MailboxActions.moveEmail + || actions == MailboxActions.move + || _responsiveUtils.isLandscapeMobile(context) + ? 0 + : 16, + right: actions == MailboxActions.moveEmail || actions == MailboxActions.move + ? 0 + : 16), padding: EdgeInsets.only( top: _responsiveUtils.isDesktop(context) && actions == MailboxActions.create ? 8 : 0, bottom: _responsiveUtils.isDesktop(context) && actions == MailboxActions.create ? 8 : 0, - left: _responsiveUtils.isDesktop(context) ? 0 : 12, + left: _responsiveUtils.isDesktop(context) || actions != MailboxActions.create ? 0 : 12, right: actions == MailboxActions.create ? 8 : 16), child: TreeView( key: Key('${categories.keyValue}_mailbox_list'), @@ -297,12 +305,43 @@ class DestinationPickerView extends GetWidget )); } - Widget _buildUnifiedMailbox(BuildContext context) { + Widget _buildUnifiedMailbox(BuildContext context, MailboxActions? actions) { + if (actions == MailboxActions.move) { + return InkWell( + onTap: () => controller.selectMailboxAction(null), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(14)), + child: Container( + color: Colors.white, + padding: const EdgeInsets.only(left: 16, top: 16), + child: Row(children: [ + SvgPicture.asset( + _imagePaths.icFolderMailbox, + width: BuildUtils.isWeb ? 20 : 24, + height: BuildUtils.isWeb ? 20 : 24, + fit: BoxFit.fill), + const SizedBox(width: 8), + Expanded(child: Text( + AppLocalizations.of(context).default_mailbox, + maxLines: 1, + overflow: CommonTextStyle.defaultTextOverFlow, + style: const TextStyle( + fontSize: 15, + color: AppColor.colorNameEmail, + fontWeight: FontWeight.normal), + )), + const SizedBox(width: 8), + ]) + ), + ), + ); + } + return Container( alignment: Alignment.center, margin: EdgeInsets.only( left: !_responsiveUtils.isLandscapeMobile(context) ? 16 : 0, - top: kIsWeb ? 16 : 0, + top: BuildUtils.isWeb ? 16 : 0, right: 16), decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white), child: MediaQuery( @@ -323,7 +362,7 @@ class DestinationPickerView extends GetWidget Expanded(child: Text( AppLocalizations.of(context).default_mailbox, maxLines: 1, - overflow:TextOverflow.ellipsis, + overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 15, color: AppColor.colorNameEmail), )) ] diff --git a/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart b/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart index cfeb5aaf8..846b60de7 100644 --- a/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart +++ b/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart @@ -1,14 +1,16 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; class DestinationPickerArguments with EquatableMixin { final AccountId accountId; final MailboxActions mailboxAction; + final MailboxId? mailboxIdSelected; - DestinationPickerArguments(this.accountId, this.mailboxAction); + DestinationPickerArguments(this.accountId, this.mailboxAction, {this.mailboxIdSelected}); @override - List get props => [accountId, mailboxAction]; + List get props => [accountId, mailboxAction, mailboxIdSelected]; } \ No newline at end of file diff --git a/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart b/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart index 0224bde1d..a0a440121 100644 --- a/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart +++ b/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart @@ -47,7 +47,7 @@ class AppBarDestinationPickerBuilder { } Widget _buildCancelButton() { - if (_mailboxAction == MailboxActions.moveEmail) { + if (_mailboxAction == MailboxActions.moveEmail || _mailboxAction == MailboxActions.move) { return Padding( padding: const EdgeInsets.only(right: 12), child: Material( diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart index 5912dc2bc..805c0eff7 100644 --- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart +++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart @@ -6,6 +6,7 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; abstract class MailboxDataSource { @@ -22,4 +23,6 @@ abstract class MailboxDataSource { Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds); Future renameMailbox(AccountId accountId, RenameMailboxRequest request); + + Future moveMailbox(AccountId accountId, MoveMailboxRequest request); } \ No newline at end of file diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart index 958c165c2..05086467a 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart @@ -8,6 +8,7 @@ import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager. import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; class MailboxCacheDataSourceImpl extends MailboxDataSource { @@ -59,4 +60,9 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource { Future renameMailbox(AccountId accountId, RenameMailboxRequest request) { throw UnimplementedError(); } + + @override + Future moveMailbox(AccountId accountId, MoveMailboxRequest request) { + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart index 490c22a84..14748acd2 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart @@ -8,6 +8,7 @@ import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_respons import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; class MailboxDataSourceImpl extends MailboxDataSource { @@ -70,4 +71,13 @@ class MailboxDataSourceImpl extends MailboxDataSource { throw error; }); } + + @override + Future moveMailbox(AccountId accountId, MoveMailboxRequest request) { + return Future.sync(() async { + return await mailboxAPI.moveMailbox(accountId, request); + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart index 617bffd6b..e32f829c2 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -23,6 +23,7 @@ import 'package:model/model.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; @@ -201,4 +202,32 @@ class MailboxAPI { throw error; }); } + + Future moveMailbox(AccountId accountId, MoveMailboxRequest request) async { + final setMailboxMethod = SetMailboxMethod(accountId) + ..addUpdates({ + request.mailboxId.id : PatchObject({ + 'parentId': request.destinationMailboxId?.id.value + }) + }); + + final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + + final setMailboxInvocation = requestBuilder.invocation(setMailboxMethod); + + final response = await (requestBuilder + ..usings(setMailboxMethod.requiredCapabilities)) + .build() + .execute(); + + final setMailboxResponse = response.parse( + setMailboxInvocation.methodCallId, + SetMailboxResponse.deserialize); + + return Future.sync(() async { + return setMailboxResponse?.updated?.isNotEmpty == true; + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart index 76ba34b58..7f7247026 100644 --- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart +++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart @@ -20,6 +20,7 @@ import 'package:tmail_ui_user/features/mailbox/data/extensions/state_extension.d import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart'; @@ -220,4 +221,9 @@ class MailboxRepositoryImpl extends MailboxRepository { return true; } + + @override + Future moveMailbox(AccountId accountId, MoveMailboxRequest request) { + return mapDataSource[DataSourceType.network]!.moveMailbox(accountId, request); + } } \ No newline at end of file diff --git a/lib/features/mailbox/domain/model/move_mailbox_request.dart b/lib/features/mailbox/domain/model/move_mailbox_request.dart new file mode 100644 index 000000000..8b1f0130b --- /dev/null +++ b/lib/features/mailbox/domain/model/move_mailbox_request.dart @@ -0,0 +1,32 @@ + +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; + +class MoveMailboxRequest with EquatableMixin { + + final MailboxId? destinationMailboxId; + final MailboxName? destinationMailboxName; + final MailboxId? parentId; + final MailboxId mailboxId; + final MoveAction moveAction; + + MoveMailboxRequest( + this.mailboxId, + this.moveAction, + { + this.parentId, + this.destinationMailboxId, + this.destinationMailboxName + } + ); + + @override + List get props => [ + mailboxId, + moveAction, + parentId, + destinationMailboxId, + destinationMailboxName + ]; +} \ No newline at end of file diff --git a/lib/features/mailbox/domain/repository/mailbox_repository.dart b/lib/features/mailbox/domain/repository/mailbox_repository.dart index d6724e407..73520c42d 100644 --- a/lib/features/mailbox/domain/repository/mailbox_repository.dart +++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart @@ -5,6 +5,7 @@ import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; abstract class MailboxRepository { @@ -19,4 +20,6 @@ abstract class MailboxRepository { Future renameMailbox(AccountId accountId, RenameMailboxRequest request); Future markAsMailboxRead(AccountId accountId, MailboxId mailboxId, MailboxName mailboxName); + + Future moveMailbox(AccountId accountId, MoveMailboxRequest request); } \ No newline at end of file diff --git a/lib/features/mailbox/domain/state/move_mailbox_state.dart b/lib/features/mailbox/domain/state/move_mailbox_state.dart new file mode 100644 index 000000000..1a3c0fcfe --- /dev/null +++ b/lib/features/mailbox/domain/state/move_mailbox_state.dart @@ -0,0 +1,45 @@ +import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; + +class MoveMailboxLoading extends UIState { + + MoveMailboxLoading(); + + @override + List get props => []; +} + +class MoveMailboxSuccess extends UIState { + + final MailboxId mailboxIdSelected; + final MoveAction moveAction; + final MailboxId? parentId; + final MailboxId? destinationMailboxId; + final MailboxName? destinationMailboxName; + + MoveMailboxSuccess( + this.mailboxIdSelected, + this.moveAction, + { + this.parentId, + this.destinationMailboxId, + this.destinationMailboxName + } + ); + + @override + List get props => [ + mailboxIdSelected, + parentId, + destinationMailboxId]; +} + +class MoveMailboxFailure extends FeatureFailure { + final dynamic exception; + + MoveMailboxFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/mailbox/domain/usecases/move_mailbox_interactor.dart b/lib/features/mailbox/domain/usecases/move_mailbox_interactor.dart new file mode 100644 index 000000000..276dbccf4 --- /dev/null +++ b/lib/features/mailbox/domain/usecases/move_mailbox_interactor.dart @@ -0,0 +1,30 @@ +import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/state/move_mailbox_state.dart'; + +class MoveMailboxInteractor { + final MailboxRepository mailboxRepository; + + MoveMailboxInteractor(this.mailboxRepository); + + Stream> execute(AccountId accountId, MoveMailboxRequest request) async* { + try { + final result = await mailboxRepository.moveMailbox(accountId, request); + if (result) { + yield Right(MoveMailboxSuccess( + request.mailboxId, + request.moveAction, + parentId: request.parentId, + destinationMailboxId: request.destinationMailboxId, + destinationMailboxName: request.destinationMailboxName)); + } else { + yield Left(MoveMailboxFailure(null)); + } + } catch (e) { + yield Left(MoveMailboxFailure(e)); + } + } +} \ No newline at end of file diff --git a/lib/features/mailbox/presentation/mailbox_bindings.dart b/lib/features/mailbox/presentation/mailbox_bindings.dart index 50b10ba54..3a3cf5e2c 100644 --- a/lib/features/mailbox/presentation/mailbox_bindings.dart +++ b/lib/features/mailbox/presentation/mailbox_bindings.dart @@ -20,6 +20,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_reposit import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/usecases/move_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart'; @@ -54,6 +55,7 @@ class MailboxBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), Get.find(), Get.find(), )); @@ -85,6 +87,7 @@ class MailboxBindings extends BaseBindings { Get.lazyPut(() => DeleteMultipleMailboxInteractor(Get.find())); Get.lazyPut(() => VerifyNameInteractor()); Get.lazyPut(() => RenameMailboxInteractor(Get.find())); + Get.lazyPut(() => MoveMailboxInteractor(Get.find())); } @override diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 93587503d..f6590f585 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -17,21 +17,26 @@ import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart'; 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/destination_picker/presentation/model/destination_picker_arguments.dart'; +import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; import 'package:tmail_ui_user/features/email/domain/state/delete_email_permanently_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/delete_multiple_emails_permanently_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/state/move_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_mailboxes_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/rename_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/usecases/move_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart'; @@ -77,6 +82,7 @@ class MailboxController extends BaseMailboxController { final DeleteMultipleMailboxInteractor _deleteMultipleMailboxInteractor; final VerifyNameInteractor _verifyNameInteractor; final RenameMailboxInteractor _renameMailboxInteractor; + final MoveMailboxInteractor _moveMailboxInteractor; final Uuid _uuid; final listMailboxSearched = [].obs; @@ -103,6 +109,7 @@ class MailboxController extends BaseMailboxController { this._deleteMultipleMailboxInteractor, this._verifyNameInteractor, this._renameMailboxInteractor, + this._moveMailboxInteractor, this._uuid, treeBuilder, ) : super(treeBuilder); @@ -172,6 +179,8 @@ class MailboxController extends BaseMailboxController { _searchMailboxAction(allMailboxes, searchQuery.value); } else if (success is RenameMailboxSuccess) { refreshMailboxChanges(); + } else if (success is MoveMailboxSuccess) { + _moveMailboxSuccess(success); } } ); @@ -483,6 +492,9 @@ class MailboxController extends BaseMailboxController { case MailboxActions.markAsRead: _markAsReadMailboxAction(selectionMailbox.first); break; + case MailboxActions.move: + _moveMailboxAction(selectionMailbox.first); + break; default: break; } @@ -664,6 +676,69 @@ class MailboxController extends BaseMailboxController { } } + void _moveMailboxAction(PresentationMailbox mailboxSelected) async { + final accountId = mailboxDashBoardController.accountId.value; + if (accountId != null) { + final destinationMailbox = await push( + AppRoutes.DESTINATION_PICKER, + arguments: DestinationPickerArguments( + accountId, + MailboxActions.move, + mailboxIdSelected: mailboxSelected.id)); + + _handleMovingMailbox( + accountId, + MoveAction.moving, + mailboxSelected, + destinationMailbox: destinationMailbox); + } + + _cancelSelectMailbox(); + } + + void _handleMovingMailbox( + AccountId accountId, + MoveAction moveAction, + PresentationMailbox mailboxSelected, + {PresentationMailbox? destinationMailbox}) { + consumeState(_moveMailboxInteractor.execute(accountId, + MoveMailboxRequest( + mailboxSelected.id, + moveAction, + destinationMailboxId: destinationMailbox?.id, + destinationMailboxName: destinationMailbox?.name, + parentId: mailboxSelected.parentId))); + } + + void _moveMailboxSuccess(MoveMailboxSuccess success) { + if (success.moveAction == MoveAction.moving + && currentOverlayContext != null + && currentContext != null) { + _appToast.showToastWithAction( + currentOverlayContext!, + AppLocalizations.of(currentContext!).moved_to_mailbox( + success.destinationMailboxName?.name ?? AppLocalizations.of(currentContext!).default_mailbox), + AppLocalizations.of(currentContext!).undo_action, + () { + _undoMovingMailbox(MoveMailboxRequest( + success.mailboxIdSelected, + MoveAction.undo, + destinationMailboxId: success.parentId, + parentId: success.destinationMailboxId)); + }, + maxWidth: _responsiveUtils.getMaxWidthToast(currentContext!)); + } + + refreshMailboxChanges(); + } + + void _undoMovingMailbox(MoveMailboxRequest newMoveRequest) { + final accountId = mailboxDashBoardController.accountId.value; + if (accountId != null) { + consumeState(_moveMailboxInteractor.execute(accountId, newMoveRequest)); + } + } + void _createListMailboxNameAsStringInMailboxParent(PresentationMailbox mailboxRenamed) { if (mailboxRenamed.parentId == null) { final allChildrenAtMailboxLocation = (defaultMailboxTree.value.root.childrenItems ?? []) + (folderMailboxTree.value.root.childrenItems ?? []); @@ -715,7 +790,7 @@ class MailboxController extends BaseMailboxController { _openDialogRenameMailboxAction(context, mailbox); break; case MailboxActions.move: - _appToast.showToast(AppLocalizations.of(context).the_feature_is_under_development); + _moveMailboxAction(mailbox); break; case MailboxActions.markAsRead: _markAsReadMailboxAction(mailbox); diff --git a/lib/features/mailbox/presentation/model/mailbox_actions.dart b/lib/features/mailbox/presentation/model/mailbox_actions.dart index c78048cc9..b42c1503a 100644 --- a/lib/features/mailbox/presentation/model/mailbox_actions.dart +++ b/lib/features/mailbox/presentation/model/mailbox_actions.dart @@ -21,6 +21,8 @@ extension MailboxActionsExtension on MailboxActions { return AppLocalizations.of(context).mailbox_location; case MailboxActions.moveEmail: return AppLocalizations.of(context).move_message; + case MailboxActions.move: + return AppLocalizations.of(context).allMailboxes; default: return ''; } diff --git a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart index 1dab2a4db..68be20f11 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart @@ -100,7 +100,7 @@ class MailBoxFolderTileBuilder { borderRadius: const BorderRadius.all(Radius.circular(14)), child: Container( color: Colors.white, - padding: const EdgeInsets.only(left: 16, top: 8, bottom: 8), + padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10), child: Row(children: [ _buildLeadingMailboxItem(), const SizedBox(width: 8), diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 2495f2c66..82741c0e0 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-06-01T15:37:34.038431", + "@@last_modified": "2022-06-01T17:23:21.677245", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -1393,5 +1393,11 @@ "placeholders": { "mailboxName": {} } + }, + "allMailboxes": "All mailboxes", + "@allMailboxes": { + "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 3e55c7835..5ffc07691 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1425,4 +1425,10 @@ class AppLocalizations { name: 'toastMessageMarkAsMailboxReadSuccess', args: [mailboxName]); } + + String get allMailboxes { + return Intl.message( + 'All mailboxes', + name: 'allMailboxes'); + } } \ No newline at end of file