From a8cc19ada2d6ede8a571af2242dff8ddd542c728 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 21 Feb 2025 16:59:14 +0700 Subject: [PATCH] Hot fix cannot send email on cyrus server when the first open app Signed-off-by: dab246 --- ...box_mailbox_id_for_composer_extension.dart | 6 +- .../email/data/network/email_api.dart | 3 +- .../data/datasource/mailbox_datasource.dart | 4 +- .../mailbox_cache_datasource_impl.dart | 4 +- .../mailbox_datasource_impl.dart | 4 +- .../mailbox/data/network/mailbox_api.dart | 86 ++++++++++--------- .../repository/mailbox_repository_impl.dart | 4 +- .../set_mailbox_method_exception.dart | 11 --- .../domain/repository/mailbox_repository.dart | 4 +- .../state/create_default_mailbox_state.dart | 21 ++--- ...create_new_default_mailbox_interactor.dart | 40 ++++++--- .../presentation/mailbox_controller.dart | 25 ++++++ model/lib/extensions/mailbox_extension.dart | 18 ++++ 13 files changed, 138 insertions(+), 92 deletions(-) diff --git a/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart b/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart index 5b860fc4b..b6de89915 100644 --- a/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart +++ b/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart @@ -6,9 +6,7 @@ import 'package:tmail_ui_user/features/composer/presentation/composer_controller extension GetOutboxMailboxIdForComposerExtension on ComposerController { MailboxId? getOutboxMailboxIdForComposer() { - final defaultOutboxMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[ - PresentationMailbox.roleOutbox - ]; + final defaultOutboxMailboxId = mailboxDashBoardController.outboxMailbox?.mailboxId; final lowercaseOutboxRole = PresentationMailbox.roleOutbox.value.toLowerCase(); return mailboxDashBoardController.mapMailboxById.entries @@ -17,6 +15,6 @@ extension GetOutboxMailboxIdForComposerExtension on ComposerController { return mailbox.emailTeamMailBoxes == identitySelected.value?.email && mailbox.name?.name.toLowerCase() == lowercaseOutboxRole; }) - ?.key ?? defaultOutboxMailbox; + ?.key ?? defaultOutboxMailboxId; } } \ 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 ae2c40567..720027c28 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -174,7 +174,8 @@ class EmailAPI with HandleSetErrorMixin { final emailSubmissionId = EmailSubmissionId(ReferenceId(ReferencePrefix.defaultPrefix, submissionCreateId)); Map mapEmailSubmissionUpdated = { emailSubmissionId: PatchObject({ - emailRequest.sentMailboxId!.generatePath() : true, + if (emailRequest.sentMailboxId != null) + emailRequest.sentMailboxId!.generatePath() : true, outboxMailboxId!.generatePath() : null, KeyWordIdentifier.emailSeen.generatePath(): true, KeyWordIdentifier.emailDraft.generatePath(): null diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart index 5a70c5b6e..aa553bca6 100644 --- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart +++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart @@ -52,9 +52,9 @@ abstract class MailboxDataSource { Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request); - Future> createDefaultMailbox(Session session, AccountId accountId, List listRole); + Future<(List mailboxes, Map mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List listRole); - Future setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); Future getMailboxByRole(Session session, AccountId accountId, Role role); 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 29d609211..12d7f8933 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 @@ -141,12 +141,12 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource { } @override - Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + Future<(List mailboxes, Map mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List listRole) { throw UnimplementedError(); } @override - Future> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { 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 2464f76bd..e616c445c 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart @@ -130,14 +130,14 @@ class MailboxDataSourceImpl extends MailboxDataSource { } @override - Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + Future<(List mailboxes, Map mapErrors)> 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) { + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { return Future.sync(() async { return await mailboxAPI.setRoleDefaultMailbox(session, accountId, listMailbox); }).catchError(_exceptionThrower.throwException); diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart index 5d5332120..0ee986197 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -34,7 +34,6 @@ import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart'; import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart'; -import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_rights_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'; @@ -454,19 +453,19 @@ class MailboxAPI with HandleSetErrorMixin { } } - Future> createDefaultMailbox( + Future<(List mailboxes, Map mapErrors)> createDefaultMailbox( Session session, AccountId accountId, List listRole ) async { - final mapId = { + final mapRoles = { 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)) + for (var id in mapRoles.keys) + id : Mailbox(name: MailboxName(mapRoles[id]!.mailboxName), isSubscribed: IsSubscribed(true)) }; final setMailboxMethodForCreate = SetMailboxMethod(accountId) @@ -488,53 +487,40 @@ class MailboxAPI with HandleSetErrorMixin { ); final mapErrors = handleSetResponse([createResponse]); + final mapMailboxCreated = createResponse?.created ?? {}; - 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; - } - } + final listMailboxCreated = _convertMapToListMailbox( + mapRoles: mapRoles, + mapMailboxName: mapCreate, + mapMailboxCreated: mapMailboxCreated, + ); + + return (listMailboxCreated, mapErrors); } List _convertMapToListMailbox({ required Map mapRoles, required Map mapMailboxName, - required Map mapMailboxCreated + 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; - } + return mapMailboxCreated + .entries + .map((mailboxEntry) { + final id = mailboxEntry.key; + final mailbox = mailboxEntry.value; + return mailbox.copyWith( + name: mapMailboxName[id]?.name, + role: mapRoles[id], + isSubscribed: IsSubscribed(true), + ); }) - .whereNotNull() .toList(); } - Future setRoleDefaultMailbox( + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox( Session session, AccountId accountId, - List listMailbox + List listMailbox, ) async { final mapUpdated = { for (var mailbox in listMailbox) @@ -560,9 +546,27 @@ class MailboxAPI with HandleSetErrorMixin { ); final mapErrors = handleSetResponse([updateResponse]); - if (mapErrors.isNotEmpty) { - throw SetMailboxMethodException(mapErrors); + final listUpdatedMailboxId = updateResponse?.updated?.keys ?? []; + + if (listUpdatedMailboxId.isEmpty) { + final listMailboxWithoutRole = listMailbox + .map((mailbox) => mailbox.toMailboxWithoutRole()) + .toList(); + + return (listMailboxWithoutRole, mapErrors); } + + final listUpdatedMailbox = listMailbox + .map((mailbox) { + if (listUpdatedMailboxId.contains(mailbox.id!.id)) { + return mailbox; + } else { + return mailbox.toMailboxWithoutRole(); + } + }) + .toList(); + + return (listUpdatedMailbox, mapErrors); } Future getMailboxByRole( diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart index 0ab32b1de..38db39162 100644 --- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart +++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart @@ -292,12 +292,12 @@ class MailboxRepositoryImpl extends MailboxRepository { } @override - Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) { + Future<(List mailboxes, Map mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List listRole) { return mapDataSource[DataSourceType.network]!.createDefaultMailbox(session, accountId, listRole); } @override - Future setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox) { return mapDataSource[DataSourceType.network]!.setRoleDefaultMailbox(session, accountId, listMailbox); } diff --git a/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart index 9578d6727..9585b5c45 100644 --- a/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart +++ b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart @@ -1,14 +1,3 @@ - -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/repository/mailbox_repository.dart b/lib/features/mailbox/domain/repository/mailbox_repository.dart index 8f65b1ff9..1a22deed7 100644 --- a/lib/features/mailbox/domain/repository/mailbox_repository.dart +++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart @@ -49,9 +49,9 @@ abstract class MailboxRepository { Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request); - Future> createDefaultMailbox(Session session, AccountId accountId, List listRole); + Future<(List mailboxes, Map mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List listRole); - Future setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); + Future<(List mailboxes, Map mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox); Future getMailboxByRole(Session session, AccountId accountId, Role role, {UnsignedInt? limit}); } \ 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 index 39f4c8a92..eeb16f62b 100644 --- a/lib/features/mailbox/domain/state/create_default_mailbox_state.dart +++ b/lib/features/mailbox/domain/state/create_default_mailbox_state.dart @@ -1,25 +1,20 @@ 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; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; class CreateDefaultMailboxLoading extends LoadingState {} -class CreateDefaultMailboxAllSuccess extends UIActionState { - CreateDefaultMailboxAllSuccess({ - jmap.State? currentEmailState, - jmap.State? currentMailboxState, - }) : super(currentEmailState, currentMailboxState); +class CreateDefaultMailboxAllSuccess extends UIState { + + final List listMailbox; + + CreateDefaultMailboxAllSuccess(this.listMailbox); @override - List get props => [...super.props]; + List get props => [listMailbox]; } class CreateDefaultMailboxFailure extends FeatureFailure { - final jmap.State? currentMailboxState; - CreateDefaultMailboxFailure(this.currentMailboxState, dynamic exception) : super(exception: exception); - - @override - List get props => [currentMailboxState, exception]; + CreateDefaultMailboxFailure(dynamic exception) : super(exception: 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 index dce6e6297..3c2a1d785 100644 --- a/lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart +++ b/lib/features/mailbox/domain/usecases/create_new_default_mailbox_interactor.dart @@ -4,8 +4,8 @@ import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart' as dartz; 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/core/state.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.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'; @@ -19,32 +19,48 @@ class CreateDefaultMailboxInteractor { AccountId accountId, List listRole ) async* { - final currentMailboxState = await _getCurrentMailboxState(session, accountId); try { yield dartz.Right(CreateDefaultMailboxLoading()); - final listMailboxCreated = await _mailboxRepository.createDefaultMailbox( + final mailboxesRecord = await _mailboxRepository.createDefaultMailbox( session, accountId, listRole ); - await _mailboxRepository.setRoleDefaultMailbox( + + final listMailboxCreated = mailboxesRecord.$1; + log('CreateDefaultMailboxInteractor::execute:listMailboxCreated = $listMailboxCreated'); + if (listMailboxCreated.isEmpty) { + yield dartz.Left(CreateDefaultMailboxFailure(NotFoundMailboxCreatedException())); + return; + } + + final listMailboxUpdated = await _updateRoleToListMailbox( session, accountId, - listMailboxCreated + listMailboxCreated, ); - yield dartz.Right(CreateDefaultMailboxAllSuccess(currentMailboxState: currentMailboxState)); + + yield dartz.Right(CreateDefaultMailboxAllSuccess(listMailboxUpdated)); } catch (e) { - yield dartz.Left(CreateDefaultMailboxFailure(currentMailboxState, e)); + yield dartz.Left(CreateDefaultMailboxFailure(e)); } } - Future _getCurrentMailboxState(Session session, AccountId accountId) async { + Future> _updateRoleToListMailbox( + Session session, + AccountId accountId, + List mailboxes, + ) async { try { - final currentMailboxState = await _mailboxRepository.getMailboxState(session, accountId); - log('CreateDefaultMailboxInteractor::_getCurrentMailboxState:currentMailboxState: $currentMailboxState'); - return currentMailboxState; + final mailboxUpdatedRecord = await _mailboxRepository.setRoleDefaultMailbox( + session, + accountId, + mailboxes, + ); + return mailboxUpdatedRecord.$1; } catch (e) { - return null; + logError('CreateDefaultMailboxInteractor::_updateRoleToListMailbox:Exception = $e'); + return mailboxes; } } } \ No newline at end of file diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 407f46bb8..0fc64917b 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -45,6 +45,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_reques 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'; @@ -203,6 +204,8 @@ class MailboxController extends BaseMailboxController _handleUnsubscribeMultipleMailboxHasSomeSuccess(success); } else if (success is SubaddressingSuccess) { _handleSubaddressingSuccess(success); + } else if (success is CreateDefaultMailboxAllSuccess) { + _handleCreateDefaultFolderIfMissingSuccess(success); } } @@ -657,6 +660,28 @@ class MailboxController extends BaseMailboxController } } + Future _handleCreateDefaultFolderIfMissingSuccess(CreateDefaultMailboxAllSuccess success) async { + if (success.listMailbox.isEmpty) return; + + Set existingRoles = {}; + Set existingNamesWithoutParent = {}; + + for (var mailbox in success.listMailbox) { + if (mailbox.role != null && !existingRoles.add(mailbox.role)) continue; + + if (mailbox.parentId == null && mailbox.name != null && !existingNamesWithoutParent.add(mailbox.name!)) continue; + + allMailboxes.add(mailbox.toPresentationMailbox()); + } + + await buildTree(allMailboxes); + if (currentContext != null) { + syncAllMailboxWithDisplayName(currentContext!); + } + _setMapMailbox(); + _setOutboxMailbox(); + } + void _handleDataFromNavigationRouter() { log('MailboxController::_handleDataFromNavigationRouter():navigationRouter: $_navigationRouter'); if (!PlatformInfo.isWeb || _navigationRouter == null) { diff --git a/model/lib/extensions/mailbox_extension.dart b/model/lib/extensions/mailbox_extension.dart index d5f0d2719..677f50c8a 100644 --- a/model/lib/extensions/mailbox_extension.dart +++ b/model/lib/extensions/mailbox_extension.dart @@ -56,6 +56,24 @@ extension MailboxExtension on Mailbox { ); } + Mailbox toMailboxWithoutRole() { + return Mailbox( + id: id, + name: name, + parentId: parentId, + role: null, + sortOrder: sortOrder, + totalEmails: totalEmails, + unreadEmails: unreadEmails, + totalThreads: totalThreads, + unreadThreads: unreadThreads, + myRights: myRights, + isSubscribed: isSubscribed, + namespace: namespace, + rights: rights, + ); + } + Mailbox toMailbox(MailboxName mailboxName, {MailboxId? parentId, Role? mailboxRole}) { return Mailbox( id: id,