From 5636625fa52421beeb50dc6d13005d9069c91681 Mon Sep 17 00:00:00 2001 From: Dat PHAM HOANG Date: Mon, 14 Mar 2022 12:16:26 +0700 Subject: [PATCH] TF-320 Delete mailbox with sub-mailbox --- .../data/datasource/mailbox_datasource.dart | 3 +- .../mailbox_cache_datasource_impl.dart | 7 ++- .../mailbox_datasource_impl.dart | 7 ++- .../mailbox/data/network/mailbox_api.dart | 58 +++++++++++++------ .../repository/mailbox_repository_impl.dart | 7 ++- .../domain/repository/mailbox_repository.dart | 3 +- .../delete_multiple_mailbox_interactor.dart | 5 +- .../presentation/mailbox_controller.dart | 19 +++--- 8 files changed, 70 insertions(+), 39 deletions(-) diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart index 660ffc274..5912dc2bc 100644 --- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart +++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart @@ -1,5 +1,6 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; 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/data/model/mailbox_change_response.dart'; @@ -18,7 +19,7 @@ abstract class MailboxDataSource { Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest); - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds); + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds); Future renameMailbox(AccountId accountId, RenameMailboxRequest 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 c0cc203ea..9f31744e5 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 @@ -1,11 +1,12 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; 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/data/datasource/mailbox_datasource.dart'; -import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; -import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/extensions/mailbox_extension.dart'; +import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.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/rename_mailbox_request.dart'; @@ -52,7 +53,7 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource { } @override - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) { + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds) { throw UnimplementedError(); } 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 90169a644..490c22a84 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart @@ -1,12 +1,13 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; 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/data/datasource/mailbox_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +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/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; class MailboxDataSourceImpl extends MailboxDataSource { @@ -53,9 +54,9 @@ class MailboxDataSourceImpl extends MailboxDataSource { } @override - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) { + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds) { return Future.sync(() async { - return await mailboxAPI.deleteMultipleMailbox(accountId, mailboxIds); + return await mailboxAPI.deleteMultipleMailbox(session, accountId, mailboxIds); }).catchError((error) { throw error; }); diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart index 758f8f493..a1b5cf567 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -1,10 +1,14 @@ import 'dart:async'; +import 'package:core/utils/app_logger.dart'; import 'package:jmap_dart_client/http/http_client.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; +import 'package:jmap_dart_client/jmap/core/capability/core_capability.dart'; import 'package:jmap_dart_client/jmap/core/patch_object.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/core/request/reference_path.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/jmap_request.dart'; @@ -20,6 +24,7 @@ import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_respons 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/rename_mailbox_request.dart'; +import 'package:tmail_ui_user/main/error/capability_validator.dart'; class MailboxAPI { @@ -131,29 +136,46 @@ class MailboxAPI { }); } - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) async { - final setMailboxMethod = SetMailboxMethod(accountId) - ..addDestroy(mailboxIds.map((mailboxId) => mailboxId.id).toSet()) - ..addOnDestroyRemoveEmails(true); + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds) async { + requireCapability(session, [CapabilityIdentifier.jmapCore, CapabilityIdentifier.jmapMail]); - final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + final coreCapability = (session.capabilities[CapabilityIdentifier.jmapCore] as CoreCapability); + final maxMethodCount = coreCapability.maxCallsInRequest.value.toInt(); - final setMailboxInvocation = requestBuilder.invocation(setMailboxMethod); + var finalResult = true; + var start = 0; + var end = 0; + while (end < mailboxIds.length) { + start = end; + if (mailboxIds.length - start >= maxMethodCount) { + end = maxMethodCount; + } else { + end = mailboxIds.length; + } + log('MailboxAPI::deleteMultipleMailbox(): delete from $start to $end / ${mailboxIds.length}'); + final currentExecuteList = mailboxIds.sublist(start, end); - final response = await (requestBuilder - ..usings(setMailboxMethod.requiredCapabilities)) - .build() - .execute(); + final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + final currentSetMailboxInvocations = currentExecuteList.map((mailboxId) { + return SetMailboxMethod(accountId) + ..addDestroy(Set.of([mailboxId.id])) + ..addOnDestroyRemoveEmails(true); + }) + .map(requestBuilder.invocation) + .toList(); - final setMailboxResponse = response.parse( - setMailboxInvocation.methodCallId, - SetMailboxResponse.deserialize); + final response = await (requestBuilder + ..usings(Set.of([CapabilityIdentifier.jmapCore, CapabilityIdentifier.jmapMail]))) + .build() + .execute(); - return Future.sync(() async { - return setMailboxResponse?.destroyed?.isNotEmpty == true; - }).catchError((error) { - throw error; - }); + finalResult = currentSetMailboxInvocations + .map((currentInvocation) => response.parse(currentInvocation.methodCallId, SetMailboxResponse.deserialize)) + .map((response) => response?.destroyed?.isNotEmpty ?? false) + .every((element) => element == true); + } + + return finalResult; } Future renameMailbox(AccountId accountId, RenameMailboxRequest request) async { diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart index 2c6318475..624d86e8e 100644 --- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart +++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart @@ -1,15 +1,16 @@ import 'package:core/core.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/extensions/state_extension.dart'; +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/data/model/state_type.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'; @@ -143,8 +144,8 @@ class MailboxRepositoryImpl extends MailboxRepository { } @override - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) { - return mapDataSource[DataSourceType.network]!.deleteMultipleMailbox(accountId, mailboxIds); + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds) { + return mapDataSource[DataSourceType.network]!.deleteMultipleMailbox(session, accountId, mailboxIds); } @override diff --git a/lib/features/mailbox/domain/repository/mailbox_repository.dart b/lib/features/mailbox/domain/repository/mailbox_repository.dart index 70bc98ad2..d4ac5e742 100644 --- a/lib/features/mailbox/domain/repository/mailbox_repository.dart +++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart @@ -1,5 +1,6 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; 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'; @@ -13,7 +14,7 @@ abstract class MailboxRepository { Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest); - Future deleteMultipleMailbox(AccountId accountId, List mailboxIds); + Future deleteMultipleMailbox(Session session, AccountId accountId, List mailboxIds); Future renameMailbox(AccountId accountId, RenameMailboxRequest request); } \ No newline at end of file diff --git a/lib/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart b/lib/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart index 4f8ab74ab..c5726241d 100644 --- a/lib/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart +++ b/lib/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart @@ -1,6 +1,7 @@ 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/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart'; @@ -10,9 +11,9 @@ class DeleteMultipleMailboxInteractor { DeleteMultipleMailboxInteractor(this.mailboxRepository); - Stream> execute(AccountId accountId, List mailboxIds) async* { + Stream> execute(Session session, AccountId accountId, List mailboxIds) async* { try { - final result = await mailboxRepository.deleteMultipleMailbox(accountId, mailboxIds); + final result = await mailboxRepository.deleteMultipleMailbox(session, accountId, mailboxIds); if (result) { yield Right(DeleteMultipleMailboxSuccess()); } else { diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 9629af39d..19b9a4853 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -464,16 +464,19 @@ class MailboxController extends BaseMailboxController { final matchedNode = findMailboxNodeById(presentationMailbox.id); final accountId = mailboxDashBoardController.accountId.value; + final session = mailboxDashBoardController.sessionCurrent; - if (matchedNode != null && accountId != null) { - final descendantIds = matchedNode.descendantsAsList() - .map((node) => node.item.id) - .toList(); + if (session != null) { + if (matchedNode != null && accountId != null) { + final descendantIds = matchedNode.descendantsAsList() + .map((node) => node.item.id) + .toList(); - final descendantIdsReversed = descendantIds.reversed.toList(); - consumeState(_deleteMultipleMailboxInteractor.execute(accountId, descendantIdsReversed)); - } else { - _deleteMailboxFailure(DeleteMultipleMailboxFailure(null)); + final descendantIdsReversed = descendantIds.reversed.toList(); + consumeState(_deleteMultipleMailboxInteractor.execute(session, accountId, descendantIdsReversed)); + } else { + _deleteMailboxFailure(DeleteMultipleMailboxFailure(null)); + } } _cancelSelectMailbox();