From c2797303095655446f1254d61a0a474af951dbd4 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 31 Oct 2023 01:30:11 +0700 Subject: [PATCH] TF-1705 Auto create default folder if missing on server CYRUS Signed-off-by: dab246 (cherry picked from commit 1a5bad168cddf07662f4c682189840bc8c4bdcef) --- .../base/mixin/handle_error_mixin.dart | 24 ++++ .../email/data/network/email_api.dart | 30 +--- .../data/datasource/mailbox_datasource.dart | 4 + .../mailbox_cache_datasource_impl.dart | 10 ++ .../mailbox_datasource_impl.dart | 14 ++ .../mailbox/data/network/mailbox_api.dart | 129 +++++++++++++++++- .../repository/mailbox_repository_impl.dart | 10 ++ .../domain/constants/mailbox_constants.dart | 3 - .../set_mailbox_method_exception.dart | 14 ++ .../domain/extensions/role_extension.dart | 24 ++++ .../domain/repository/mailbox_repository.dart | 4 + .../state/create_default_mailbox_state.dart | 33 +++++ ...create_new_default_mailbox_interactor.dart | 54 ++++++++ .../presentation/mailbox_bindings.dart | 3 + .../presentation/mailbox_controller.dart | 37 ++++- .../presentation/utils/mailbox_constants.dart | 12 ++ .../bindings/network/network_bindings.dart | 2 +- model/lib/extensions/mailbox_extension.dart | 4 +- 18 files changed, 375 insertions(+), 36 deletions(-) delete mode 100644 lib/features/mailbox/domain/constants/mailbox_constants.dart create mode 100644 lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart create mode 100644 lib/features/mailbox/domain/extensions/role_extension.dart create mode 100644 lib/features/mailbox/domain/state/create_default_mailbox_state.dart create mode 100644 lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart create mode 100644 lib/features/mailbox/presentation/utils/mailbox_constants.dart diff --git a/lib/features/base/mixin/handle_error_mixin.dart b/lib/features/base/mixin/handle_error_mixin.dart index 42948504a..6f128f3c1 100644 --- a/lib/features/base/mixin/handle_error_mixin.dart +++ b/lib/features/base/mixin/handle_error_mixin.dart @@ -1,7 +1,9 @@ +import 'package:collection/collection.dart'; import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/method/response/set_response.dart'; import 'package:model/error_type_handler/set_method_error_handler_mixin.dart'; mixin HandleSetErrorMixin { @@ -53,4 +55,26 @@ mixin HandleSetErrorMixin { unCatchErrorHandler?.call(remainedError); } } + + List> handleSetResponse(List listSetResponse) { + final listSetResponseNotNull = listSetResponse.whereNotNull().toList(); + if (listSetResponseNotNull.isEmpty) { + return []; + } + + final List> remainedErrors = []; + for (var response in listSetResponseNotNull) { + handleSetErrors( + notDestroyedError: response.notDestroyed, + notUpdatedError: response.notUpdated, + notCreatedError: response.notCreated, + unCatchErrorHandler: (setErrorEntry) { + remainedErrors.add(setErrorEntry); + return false; + } + ); + } + logError('HandleSetErrorMixin::handleSetResponse():remainedErrors: $remainedErrors'); + return remainedErrors; + } } diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 54912f730..682005bb8 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:io'; import 'dart:typed_data'; -import 'package:collection/collection.dart'; import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; @@ -12,10 +11,8 @@ 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/error/set_error.dart'; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; -import 'package:jmap_dart_client/jmap/core/method/response/set_response.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/reference_id.dart'; @@ -207,7 +204,7 @@ class EmailAPI with HandleSetErrorMixin { } final emailCreated = setEmailResponse?.created?[idCreateMethod]; - final listEntriesErrors = _handleSetEmailResponse([ + final listEntriesErrors = handleSetResponse([ setEmailResponse, setEmailSubmissionResponse, markAsAnsweredOrForwardedSetResponse @@ -221,27 +218,6 @@ class EmailAPI with HandleSetErrorMixin { } } - List> _handleSetEmailResponse(List listSetResponse) { - final listSetResponseNotNull = listSetResponse.whereNotNull().toList(); - if (listSetResponseNotNull.isEmpty) { - return []; - } - - final List> remainedErrors = []; - for (var response in listSetResponseNotNull) { - handleSetErrors( - notDestroyedError: response.notDestroyed, - notUpdatedError: response.notUpdated, - notCreatedError: response.notCreated, - unCatchErrorHandler: (setErrorEntry) { - remainedErrors.add(setErrorEntry); - return false; - } - ); - } - return remainedErrors; - } - Future> markAsRead( Session session, AccountId accountId, @@ -507,7 +483,7 @@ class EmailAPI with HandleSetErrorMixin { ); final emailCreated = setEmailResponse?.created?[idCreateMethod]; - final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]); + final listEntriesErrors = handleSetResponse([setEmailResponse]); final mapErrors = Map.fromEntries(listEntriesErrors); if (emailCreated != null && mapErrors.isEmpty) { @@ -574,7 +550,7 @@ class EmailAPI with HandleSetErrorMixin { final emailUpdated = setEmailResponse?.created?[idCreateMethod]; final isEmailDeleted = setEmailResponse?.destroyed?.contains(oldEmailId.id); - final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]); + final listEntriesErrors = handleSetResponse([setEmailResponse]); final mapErrors = Map.fromEntries(listEntriesErrors); if (emailUpdated != null && isEmailDeleted == true && mapErrors.isEmpty) { diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart index 5bff0a9c5..90c2161e5 100644 --- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart +++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart @@ -47,4 +47,8 @@ abstract class MailboxDataSource { Future subscribeMailbox(Session session, AccountId accountId, SubscribeMailboxRequest request); Future> subscribeMultipleMailbox(Session session, AccountId accountId, SubscribeMultipleMailboxRequest subscribeRequest); + + Future> createDefaultMailbox(Session session, AccountId accountId, List listRole); + + Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); } \ 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 8d831e1e9..6a99704c6 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 @@ -94,4 +94,14 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource { Future> subscribeMultipleMailbox(Session session, AccountId accountId, SubscribeMultipleMailboxRequest subscribeRequest) { throw UnimplementedError(); } + + @override + Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + throw UnimplementedError(); + } + + @override + Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { + 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 39077ab39..59814f610 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart @@ -118,4 +118,18 @@ class MailboxDataSourceImpl extends MailboxDataSource { return await mailboxAPI.subscribeMultipleMailbox(session, accountId, subscribeRequest); }).catchError(_exceptionThrower.throwException); } + + @override + Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + return Future.sync(() async { + return await mailboxAPI.createDefaultMailbox(session, accountId, listRole); + }).catchError(_exceptionThrower.throwException); + } + + @override + Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { + return Future.sync(() async { + return await mailboxAPI.setRoleDefaultMailbox(session, accountId, listMailbox); + }).catchError(_exceptionThrower.throwException); + } } \ 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 d2ad0d757..a88ee1901 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -27,7 +27,9 @@ import 'package:model/error_type_handler/set_method_error_handler_mixin.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/extensions/list_mailbox_id_extension.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/extensions/role_extension.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/mailbox_subscribe_state.dart'; @@ -36,12 +38,14 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_reque import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; +import 'package:uuid/uuid.dart'; class MailboxAPI with HandleSetErrorMixin { final HttpClient httpClient; + final Uuid _uuid; - MailboxAPI(this.httpClient); + MailboxAPI(this.httpClient, this._uuid); Future getAllMailbox(Session session, AccountId accountId, {Properties? properties}) async { final processingInvocation = ProcessingInvocation(); @@ -371,4 +375,127 @@ class MailboxAPI with HandleSetErrorMixin { log('MailboxAPI::subscribeMultipleMailbox():listMailboxIdSubscribe: $listMailboxIdSubscribe'); return listMailboxIdSubscribe ?? []; } + + Future> createDefaultMailbox( + Session session, + AccountId accountId, + List listRole + ) async { + final mapId = { + for (var role in listRole) + Id(_uuid.v1()) : role + }; + + final mapCreate = { + for (var id in mapId.keys) + id : Mailbox(name: MailboxName(mapId[id]!.mailboxName), isSubscribed: IsSubscribed(true)) + }; + + final setMailboxMethodForCreate = SetMailboxMethod(accountId) + ..addCreates(mapCreate); + + final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + final createInvocation = requestBuilder.invocation(setMailboxMethodForCreate); + + final capabilities = setMailboxMethodForCreate.requiredCapabilities.toCapabilitiesSupportTeamMailboxes(session, accountId); + + final response = await (requestBuilder + ..usings(capabilities)) + .build() + .execute(); + + final createResponse = response.parse( + createInvocation.methodCallId, + SetMailboxResponse.deserialize + ); + + final listEntriesErrors = handleSetResponse([createResponse]); + final mapErrors = Map.fromEntries(listEntriesErrors); + + if (mapErrors.isNotEmpty) { + throw SetMailboxMethodException(mapErrors); + } else { + final mapMailboxCreated = createResponse?.created ?? {}; + log('MailboxAPI::createDefaultMailbox:mapMailboxCreated: $mapMailboxCreated'); + final listMailboxCreated = _convertMapToListMailbox( + mapRoles: mapId, + mapMailboxName: mapCreate, + mapMailboxCreated: mapMailboxCreated + ); + log('MailboxAPI::createDefaultMailbox:listMailboxCreated: ${listMailboxCreated.length}'); + if (listMailboxCreated.isEmpty) { + throw NotFoundMailboxCreatedException(); + } else { + return listMailboxCreated; + } + } + } + + List _convertMapToListMailbox({ + required Map mapRoles, + required Map mapMailboxName, + required Map mapMailboxCreated + }) { + return mapRoles.keys + .where((key) => mapMailboxCreated.containsKey(key)) + .map((key) { + final mailboxName = mapMailboxName[key]?.name; + final mailboxRole = mapRoles[key]; + if (mailboxName != null && mailboxRole != null) { + return mapMailboxCreated[key]?.toMailbox( + mailboxName, + mailboxRole: mailboxRole + ); + } else { + return null; + } + }) + .whereNotNull() + .toList(); + } + + Future> setRoleDefaultMailbox( + Session session, + AccountId accountId, + List listMailbox + ) async { + final mapUpdated = { + for (var mailbox in listMailbox) + mailbox.id!.id: PatchObject({'role': mailbox.role!.value}) + }; + + final setMailboxMethodForUpdate = SetMailboxMethod(accountId) + ..addUpdates(mapUpdated); + + final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + final updateInvocation = requestBuilder.invocation(setMailboxMethodForUpdate); + + final capabilities = setMailboxMethodForUpdate.requiredCapabilities.toCapabilitiesSupportTeamMailboxes(session, accountId); + + final response = await (requestBuilder + ..usings(capabilities)) + .build() + .execute(); + + final updateResponse = response.parse( + updateInvocation.methodCallId, + SetMailboxResponse.deserialize + ); + + final listEntriesErrors = handleSetResponse([updateResponse]); + final mapErrors = Map.fromEntries(listEntriesErrors); + + if (mapErrors.isNotEmpty) { + throw SetMailboxMethodException(mapErrors); + } else { + final mapMailboxUpdated = updateResponse?.updated ?? {}; + final listMailboxIdNotUpdated = listMailbox + .map((mailbox) => mailbox.id) + .whereNotNull() + .where((mailboxId) => !mapMailboxUpdated.containsKey(mailboxId.id)) + .toList(); + log('MailboxAPI::setRoleDefaultMailbox:listMailboxIdNotUpdated: ${listMailboxIdNotUpdated.length}'); + return listMailboxIdNotUpdated; + } + } } \ 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 4a087eb1a..c379feeae 100644 --- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart +++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart @@ -206,4 +206,14 @@ class MailboxRepositoryImpl extends MailboxRepository { Future> subscribeMultipleMailbox(Session session, AccountId accountId, SubscribeMultipleMailboxRequest subscribeRequest) { return mapDataSource[DataSourceType.network]!.subscribeMultipleMailbox(session, accountId, subscribeRequest); } + + @override + Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + return mapDataSource[DataSourceType.network]!.createDefaultMailbox(session, accountId, listRole); + } + + @override + Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { + return mapDataSource[DataSourceType.network]!.setRoleDefaultMailbox(session, accountId, listMailbox); + } } \ No newline at end of file diff --git a/lib/features/mailbox/domain/constants/mailbox_constants.dart b/lib/features/mailbox/domain/constants/mailbox_constants.dart deleted file mode 100644 index 052a32b4a..000000000 --- a/lib/features/mailbox/domain/constants/mailbox_constants.dart +++ /dev/null @@ -1,3 +0,0 @@ -class MailboxConstants { - static const MAILBOX_LEVEL_SEPARATOR = "/"; -} \ No newline at end of file diff --git a/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart new file mode 100644 index 000000000..9578d6727 --- /dev/null +++ b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart @@ -0,0 +1,14 @@ + +import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; + +class SetMailboxMethodException implements Exception { + + final Map mapErrors; + + SetMailboxMethodException(this.mapErrors); +} + +class NotFoundMailboxCreatedException implements Exception {} + +class NotFoundMailboxUpdatedRoleException implements Exception {} \ No newline at end of file diff --git a/lib/features/mailbox/domain/extensions/role_extension.dart b/lib/features/mailbox/domain/extensions/role_extension.dart new file mode 100644 index 000000000..e79a57f35 --- /dev/null +++ b/lib/features/mailbox/domain/extensions/role_extension.dart @@ -0,0 +1,24 @@ + +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; + +extension RoleExtension on Role { + + String get mailboxName { + if (this == PresentationMailbox.roleInbox) { + return 'Inbox'; + } else if (this == PresentationMailbox.roleSent) { + return 'Sent'; + } else if (this == PresentationMailbox.roleOutbox) { + return 'Outbox'; + } else if (this == PresentationMailbox.roleDrafts) { + return 'Drafts'; + } else if (this == PresentationMailbox.roleTrash) { + return 'Trash'; + } else if (this == PresentationMailbox.roleSpam) { + return 'Spam'; + } else { + return ''; + } + } +} \ 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 efcc5e332..22cae0abc 100644 --- a/lib/features/mailbox/domain/repository/mailbox_repository.dart +++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart @@ -43,4 +43,8 @@ abstract class MailboxRepository { Future subscribeMailbox(Session session, AccountId accountId, SubscribeMailboxRequest request); Future> subscribeMultipleMailbox(Session session, AccountId accountId, SubscribeMultipleMailboxRequest subscribeRequest); + + Future> createDefaultMailbox(Session session, AccountId accountId, List listRole); + + Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); } \ No newline at end of file diff --git a/lib/features/mailbox/domain/state/create_default_mailbox_state.dart b/lib/features/mailbox/domain/state/create_default_mailbox_state.dart new file mode 100644 index 000000000..403ce650d --- /dev/null +++ b/lib/features/mailbox/domain/state/create_default_mailbox_state.dart @@ -0,0 +1,33 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:tmail_ui_user/features/base/state/ui_action_state.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; + +class CreateDefaultMailboxLoading extends LoadingState {} + +class CreateDefaultMailboxAllSuccess extends UIActionState { + CreateDefaultMailboxAllSuccess({ + jmap.State? currentEmailState, + jmap.State? currentMailboxState, + }) : super(currentEmailState, currentMailboxState); + + @override + List get props => [...super.props]; +} + +class CreateDefaultMailboxHasSomeFailure extends UIActionState { + CreateDefaultMailboxHasSomeFailure({ + jmap.State? currentEmailState, + jmap.State? currentMailboxState, + }) : super(currentEmailState, currentMailboxState); + + @override + List get props => [...super.props]; +} + +class CreateDefaultMailboxFailure extends FeatureFailure { + CreateDefaultMailboxFailure(dynamic exception) : super(exception: exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart b/lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart new file mode 100644 index 000000000..7d9863af8 --- /dev/null +++ b/lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart @@ -0,0 +1,54 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:core/utils/app_logger.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/create_default_mailbox_state.dart'; + +class CreateDefaultMailboxInteractor { + final MailboxRepository _mailboxRepository; + + CreateDefaultMailboxInteractor(this._mailboxRepository); + + Stream> execute( + Session session, + AccountId accountId, + List listRole + ) async* { + try { + yield Right(CreateDefaultMailboxLoading()); + + final currentMailboxState = await _mailboxRepository.getMailboxState(session, accountId); + + final listMailboxCreated = await _mailboxRepository.createDefaultMailbox( + session, + accountId, + listRole + ); + log('CreateDefaultMailboxInteractor::execute:listMailboxCreated: ${listMailboxCreated.length}'); + final listMailboxIdNotSetRole = await _mailboxRepository.setRoleDefaultMailbox( + session, + accountId, + listMailboxCreated + ); + log('CreateDefaultMailboxInteractor::execute:listMailboxIdNotSetRole: ${listMailboxIdNotSetRole.length}'); + if (listMailboxIdNotSetRole.isEmpty) { + yield Right(CreateDefaultMailboxAllSuccess(currentMailboxState: currentMailboxState)); + } else if (listMailboxIdNotSetRole.length < listMailboxCreated.length) { + yield Right(CreateDefaultMailboxHasSomeFailure(currentMailboxState: currentMailboxState)); + } else { + final mapError = await _mailboxRepository.deleteMultipleMailbox( + session, + accountId, + listMailboxIdNotSetRole + ); + yield Left(CreateDefaultMailboxFailure(mapError)); + } + } catch (e) { + yield Left(CreateDefaultMailboxFailure(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 60f17d70b..ac0a84fdc 100644 --- a/lib/features/mailbox/presentation/mailbox_bindings.dart +++ b/lib/features/mailbox/presentation/mailbox_bindings.dart @@ -15,6 +15,7 @@ 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/domain/usecases/create_new_default_mailbox_interactor.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'; @@ -54,6 +55,7 @@ class MailboxBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), Get.find(), Get.find(), Get.find(), @@ -99,6 +101,7 @@ class MailboxBindings extends BaseBindings { Get.lazyPut(() => MoveMailboxInteractor(Get.find())); Get.lazyPut(() => SubscribeMailboxInteractor(Get.find())); Get.lazyPut(() => SubscribeMultipleMailboxInteractor(Get.find())); + Get.lazyPut(() => CreateDefaultMailboxInteractor(Get.find())); } @override diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 1b1227882..32e7b2ee1 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:core/core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -34,6 +35,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_reque import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_request.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/state/create_default_mailbox_state.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'; @@ -43,6 +45,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_ import 'package:tmail_ui_user/features/mailbox/domain/state/rename_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/subscribe_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/subscribe_multiple_mailbox_state.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.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'; @@ -59,6 +62,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_catego import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/open_mailbox_view_event.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_constants.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/mailbox_creator_arguments.dart'; @@ -95,6 +99,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM final MoveMailboxInteractor _moveMailboxInteractor; final SubscribeMailboxInteractor _subscribeMailboxInteractor; final SubscribeMultipleMailboxInteractor _subscribeMultipleMailboxInteractor; + final CreateDefaultMailboxInteractor _createDefaultMailboxInteractor; final currentSelectMode = SelectMode.INACTIVE.obs; final _activeScrollTop = RxBool(false); @@ -116,6 +121,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM this._moveMailboxInteractor, this._subscribeMailboxInteractor, this._subscribeMultipleMailboxInteractor, + this._createDefaultMailboxInteractor, TreeBuilder treeBuilder, VerifyNameInteractor verifyNameInteractor, GetAllMailboxInteractor getAllMailboxInteractor, @@ -173,6 +179,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM _handleUnsubscribeMultipleMailboxAllSuccess(success); } else if (success is SubscribeMultipleMailboxHasSomeSuccess) { _handleUnsubscribeMultipleMailboxHasSomeSuccess(success); + } else if (success is CreateDefaultMailboxAllSuccess) { + _refreshMailboxChanges(currentMailboxState: success.currentMailboxState); + } else if (success is CreateDefaultMailboxHasSomeFailure) { + _refreshMailboxChanges(currentMailboxState: success.currentMailboxState); } } @@ -185,6 +195,8 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM _deleteMailboxFailure(failure); } else if (failure is RefreshChangesAllMailboxFailure) { _clearNewFolderId(); + } else if (failure is CreateDefaultMailboxFailure) { + _refreshMailboxChanges(); } } @@ -319,7 +331,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } void _initialMailboxVariableStorage({bool isRefreshChange = false}) { - _setMapMailbox(); + _setMapMailbox(isRefreshChange: isRefreshChange); _setOutboxMailbox(); if (isRefreshChange) { @@ -329,7 +341,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } } - void _setMapMailbox() { + void _setMapMailbox({bool isRefreshChange = false}) { final mapDefaultMailboxIdByRole = { for (var mailboxNode in defaultMailboxTree.value.root.childrenItems ?? List.empty()) mailboxNode.item.role!: mailboxNode.item.id @@ -342,6 +354,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM mailboxDashBoardController.setMapDefaultMailboxIdByRole(mapDefaultMailboxIdByRole); mailboxDashBoardController.setMapMailboxById(mapMailboxById); + + if (!isRefreshChange) { + _handleCreateDefaultFolderIfMissing(mapDefaultMailboxIdByRole); + } } void _setOutboxMailbox() { @@ -398,6 +414,23 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM return null; } + void _handleCreateDefaultFolderIfMissing(Map mapDefaultMailboxRole) { + final listRoleMissing = MailboxConstants.defaultMailboxRoles + .whereNot(mapDefaultMailboxRole.containsKey) + .toSet() + .toList(); + log('MailboxController::_handleCreateDefaultFolderIfMissing():listRoleMissing: $listRoleMissing'); + final accountId = mailboxDashBoardController.accountId.value; + final session = mailboxDashBoardController.sessionCurrent; + if (listRoleMissing.isNotEmpty && accountId != null && session != null) { + consumeState(_createDefaultMailboxInteractor.execute( + session, + accountId, + listRoleMissing + )); + } + } + void _handleDataFromNavigationRouter() { log('MailboxController::_handleDataFromNavigationRouter():navigationRouter: $navigationRouter'); diff --git a/lib/features/mailbox/presentation/utils/mailbox_constants.dart b/lib/features/mailbox/presentation/utils/mailbox_constants.dart new file mode 100644 index 000000000..2ae8f9607 --- /dev/null +++ b/lib/features/mailbox/presentation/utils/mailbox_constants.dart @@ -0,0 +1,12 @@ + +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; + +class MailboxConstants { + static final List defaultMailboxRoles = [ + PresentationMailbox.roleInbox, + PresentationMailbox.roleDrafts, + PresentationMailbox.roleSent, + PresentationMailbox.roleTrash + ]; +} \ No newline at end of file diff --git a/lib/main/bindings/network/network_bindings.dart b/lib/main/bindings/network/network_bindings.dart index e911309bb..7257c6d0e 100644 --- a/lib/main/bindings/network/network_bindings.dart +++ b/lib/main/bindings/network/network_bindings.dart @@ -83,7 +83,7 @@ class NetworkBindings extends Bindings { Get.put(HttpClient(Get.find())); Get.put(DownloadClient(Get.find(), Get.find())); Get.put(DownloadManager(Get.find())); - Get.put(MailboxAPI(Get.find())); + Get.put(MailboxAPI(Get.find(), Get.find())); Get.put(SessionAPI(Get.find())); Get.put(ThreadAPI(Get.find())); Get.put(EmailAPI( diff --git a/model/lib/extensions/mailbox_extension.dart b/model/lib/extensions/mailbox_extension.dart index 9331a7a59..a39976b58 100644 --- a/model/lib/extensions/mailbox_extension.dart +++ b/model/lib/extensions/mailbox_extension.dart @@ -40,12 +40,12 @@ extension MailboxExtension on Mailbox { ); } - Mailbox toMailbox(MailboxName mailboxName, {MailboxId? parentId}) { + Mailbox toMailbox(MailboxName mailboxName, {MailboxId? parentId, Role? mailboxRole}) { return Mailbox( id: id, name: mailboxName, parentId: parentId, - role: role, + role: mailboxRole ?? role, sortOrder: sortOrder, totalEmails: totalEmails, unreadEmails: unreadEmails,