From ad05c684531848e35bb657f760e5d3dd7e989328 Mon Sep 17 00:00:00 2001 From: DatDang Date: Thu, 3 Apr 2025 13:38:51 +0700 Subject: [PATCH] TF-3589 Calendar event attendance status --- .../data/datasource/email_datasource.dart | 7 - .../email_datasource_impl.dart | 17 --- .../email_hive_cache_datasource_impl.dart | 6 - .../email_local_storage_datasource_impl.dart | 6 - ...email_session_storage_datasource_impl.dart | 6 - .../data/network/calendar_event_api.dart | 8 +- .../email/data/network/email_api.dart | 39 ----- .../calendar_event_repository_impl.dart | 1 + .../repository/email_repository_impl.dart | 15 -- .../extensions/email_id_extensions.dart | 12 -- .../email/domain/model/event_action.dart | 53 ------- .../domain/repository/email_repository.dart | 7 - .../store_event_attendance_status_state.dart | 20 --- ...re_event_attendance_status_interactor.dart | 36 ----- .../presentation/bindings/email_bindings.dart | 3 - .../controller/single_email_controller.dart | 38 ++--- .../email/presentation/email_view.dart | 2 +- .../update_attendance_status_extension.dart | 21 +++ .../model/blob_calendar_event.dart | 10 +- .../calendar_event_action_button_widget.dart | 30 ++-- .../calendar_event_information_widget.dart | 10 +- model/lib/email/presentation_email.dart | 6 - .../keyword_identifier_extension.dart | 3 - ...ent_attendance_status_interactor_test.dart | 93 ------------ .../single_email_controller_test.dart | 89 ----------- ...date_attendance_status_extension_test.dart | 141 ++++++++++++++++++ 26 files changed, 208 insertions(+), 471 deletions(-) delete mode 100644 lib/features/email/domain/extensions/email_id_extensions.dart delete mode 100644 lib/features/email/domain/state/store_event_attendance_status_state.dart delete mode 100644 lib/features/email/domain/usecases/store_event_attendance_status_interactor.dart create mode 100644 lib/features/email/presentation/extensions/update_attendance_status_extension.dart delete mode 100644 test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart create mode 100644 test/features/email/presentation/extensions/update_attendance_status_extension_test.dart diff --git a/lib/features/email/data/datasource/email_datasource.dart b/lib/features/email/data/datasource/email_datasource.dart index e96b700d7..652405b32 100644 --- a/lib/features/email/data/datasource/email_datasource.dart +++ b/lib/features/email/data/datasource/email_datasource.dart @@ -22,7 +22,6 @@ import 'package:model/email/mark_star_action.dart'; import 'package:model/email/read_actions.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -173,12 +172,6 @@ abstract class EmailDataSource { Future getRestoredDeletedMessage(EmailRecoveryActionId emailRecoveryActionId); - Future storeEventAttendanceStatus( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType); - Future markAsAnswered( Session session, AccountId accountId, diff --git a/lib/features/email/data/datasource_impl/email_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_datasource_impl.dart index 8cf17e351..32b149a57 100644 --- a/lib/features/email/data/datasource_impl/email_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_datasource_impl.dart @@ -32,7 +32,6 @@ import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.da import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -372,22 +371,6 @@ class EmailDataSourceImpl extends EmailDataSource { }).catchError(_exceptionThrower.throwException); } - @override - Future storeEventAttendanceStatus( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType - ) { - return Future.sync(() async { - return await emailAPI.storeEventAttendanceStatus( - session, - accountId, - emailId, - eventActionType); - }).catchError(_exceptionThrower.throwException); - } - @override Future markAsAnswered(Session session, AccountId accountId, List emailIds) { throw UnimplementedError(); diff --git a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart index eb3f4c1cc..c860d09b1 100644 --- a/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart @@ -32,7 +32,6 @@ import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.da import 'package:tmail_ui_user/features/email/domain/extensions/detailed_email_extension.dart'; import 'package:tmail_ui_user/features/email/domain/extensions/detailed_email_hive_cache_extension.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -475,11 +474,6 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource { throw UnimplementedError(); } - @override - Future storeEventAttendanceStatus(Session session, AccountId accountId, EmailId emailId, EventActionType eventActionType) { - throw UnimplementedError(); - } - @override Future markAsAnswered(Session session, AccountId accountId, List emailIds) async { final cacheEmails = await _emailCacheManager.getMultipleStoredEmails( diff --git a/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart index b53c505c8..86cc04855 100644 --- a/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart @@ -36,7 +36,6 @@ import 'package:tmail_ui_user/features/caching/utils/local_storage_manager.dart' import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -201,11 +200,6 @@ class EmailLocalStorageDataSourceImpl extends EmailDataSource { throw UnimplementedError(); } - @override - Future storeEventAttendanceStatus(Session session, AccountId accountId, EmailId emailId, EventActionType eventActionType) { - throw UnimplementedError(); - } - @override Future storeOpenedEmail(Session session, AccountId accountId, DetailedEmail detailedEmail) { throw UnimplementedError(); diff --git a/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart index bd61a9ae1..4f0feceab 100644 --- a/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart @@ -26,7 +26,6 @@ import 'package:tmail_ui_user/features/caching/utils/session_storage_manager.dar import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -181,11 +180,6 @@ class EmailSessionStorageDatasourceImpl extends EmailDataSource { throw UnimplementedError(); } - @override - Future storeEventAttendanceStatus(Session session, AccountId accountId, EmailId emailId, EventActionType eventActionType) { - throw UnimplementedError(); - } - @override Future storeOpenedEmail(Session session, AccountId accountId, DetailedEmail detailedEmail) { throw UnimplementedError(); diff --git a/lib/features/email/data/network/calendar_event_api.dart b/lib/features/email/data/network/calendar_event_api.dart index ba3adf82e..3c6f0a37b 100644 --- a/lib/features/email/data/network/calendar_event_api.dart +++ b/lib/features/email/data/network/calendar_event_api.dart @@ -58,7 +58,10 @@ class CalendarEventAPI { (calendarEventAttendanceGetResponse?.list ?? []).map( (calendarEventAttendance) => MapEntry( calendarEventAttendance.blobId, - calendarEventAttendance.isFree, + ( + isFree: calendarEventAttendance.isFree, + attendanceStatus: calendarEventAttendance.eventAttendanceStatus, + ), ), ), ); @@ -67,7 +70,8 @@ class CalendarEventAPI { return calendarEventParseResponse!.parsed!.entries .map((entry) => BlobCalendarEvent( blobId: entry.key, - isFree: calendarBlobIdStatusMap[entry.key] ?? true, + isFree: calendarBlobIdStatusMap[entry.key]?.isFree ?? true, + attendanceStatus: calendarBlobIdStatusMap[entry.key]?.attendanceStatus, calendarEventList: entry.value)) .toList(); } else if (calendarEventParseResponse?.notParsable?.isNotEmpty == true) { diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 720027c28..75e7cc0d1 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -63,8 +63,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/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart'; -import 'package:tmail_ui_user/features/email/domain/extensions/email_id_extensions.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; import 'package:tmail_ui_user/features/email/domain/state/download_all_attachments_for_web_state.dart'; @@ -949,43 +947,6 @@ class EmailAPI with HandleSetErrorMixin { } } - Future storeEventAttendanceStatus( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType - ) async { - final setEmailMethod = SetEmailMethod(accountId) - ..addUpdates(emailId.generateMapUpdateObjectEventAttendanceStatus(eventActionType)); - - final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); - - final setEmailInvocation = requestBuilder.invocation(setEmailMethod); - - final capabilities = setEmailMethod.requiredCapabilities - .toCapabilitiesSupportTeamMailboxes(session, accountId); - - final response = await (requestBuilder - ..usings(capabilities)) - .build() - .execute(); - - final setEmailResponse = response.parse( - setEmailInvocation.methodCallId, - SetEmailResponse.deserialize, - ); - - final emailIdUpdated = setEmailResponse?.updated - ?.keys - .map((id) => EmailId(id)) - .toList() ?? []; - final mapErrors = handleSetResponse([setEmailResponse]); - - if (emailIdUpdated.isEmpty) { - throw SetMethodException(mapErrors); - } - } - Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) async { final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); final parseEmailMethod = ParseEmailMethod(accountId, blobIds) diff --git a/lib/features/email/data/repository/calendar_event_repository_impl.dart b/lib/features/email/data/repository/calendar_event_repository_impl.dart index 8c5df318a..fc92b1fe1 100644 --- a/lib/features/email/data/repository/calendar_event_repository_impl.dart +++ b/lib/features/email/data/repository/calendar_event_repository_impl.dart @@ -67,6 +67,7 @@ class CalendarEventRepositoryImpl extends CalendarEventRepository { return _transformCalendarEventDescription(calendarEvent, transformConfiguration); })), isFree: blobCalendarEvent.isFree, + attendanceStatus: blobCalendarEvent.attendanceStatus, ); })); } diff --git a/lib/features/email/data/repository/email_repository_impl.dart b/lib/features/email/data/repository/email_repository_impl.dart index 78274d00c..d8598196e 100644 --- a/lib/features/email/data/repository/email_repository_impl.dart +++ b/lib/features/email/data/repository/email_repository_impl.dart @@ -30,7 +30,6 @@ import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dar import 'package:tmail_ui_user/features/email/data/datasource/print_file_datasource.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; import 'package:tmail_ui_user/features/email/domain/model/email_print.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -473,20 +472,6 @@ class EmailRepositoryImpl extends EmailRepository { return _printFileDataSource.printEmail(emailPrint); } - @override - Future storeEventAttendanceStatus( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType - ) { - return emailDataSource[DataSourceType.network]!.storeEventAttendanceStatus( - session, - accountId, - emailId, - eventActionType); - } - @override Future> parseEmailByBlobIds(AccountId accountId, Set blobIds) { return emailDataSource[DataSourceType.network]!.parseEmailByBlobIds(accountId, blobIds); diff --git a/lib/features/email/domain/extensions/email_id_extensions.dart b/lib/features/email/domain/extensions/email_id_extensions.dart deleted file mode 100644 index 012912598..000000000 --- a/lib/features/email/domain/extensions/email_id_extensions.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:jmap_dart_client/jmap/core/id.dart'; -import 'package:jmap_dart_client/jmap/core/patch_object.dart'; -import 'package:jmap_dart_client/jmap/mail/email/email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; - -extension EmailIdExtension on EmailId { - Map generateMapUpdateObjectEventAttendanceStatus(EventActionType eventActionType) { - return { - id: eventActionType.generateEventAttendanceStatusActionPath() - }; - } -} \ No newline at end of file diff --git a/lib/features/email/domain/model/event_action.dart b/lib/features/email/domain/model/event_action.dart index 098ba6b33..53e56db41 100644 --- a/lib/features/email/domain/model/event_action.dart +++ b/lib/features/email/domain/model/event_action.dart @@ -1,9 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; -import 'package:jmap_dart_client/jmap/core/patch_object.dart'; -import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; -import 'package:model/extensions/keyword_identifier_extension.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum EventActionType { @@ -25,31 +22,6 @@ enum EventActionType { } } - PatchObject generateEventAttendanceStatusActionPath() { - switch(this) { - case EventActionType.yes: - return PatchObject({ - KeyWordIdentifierExtension.acceptedEventAttendance.generatePath(): true, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance.generatePath(): null, - KeyWordIdentifierExtension.rejectedEventAttendance.generatePath(): null, - }); - case EventActionType.maybe: - return PatchObject({ - KeyWordIdentifierExtension.acceptedEventAttendance.generatePath(): null, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance.generatePath(): true, - KeyWordIdentifierExtension.rejectedEventAttendance.generatePath(): null, - }); - case EventActionType.no: - return PatchObject({ - KeyWordIdentifierExtension.acceptedEventAttendance.generatePath(): null, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance.generatePath(): null, - KeyWordIdentifierExtension.rejectedEventAttendance.generatePath(): true, - }); - case EventActionType.mailToAttendees: - return PatchObject({}); - } - } - String getToastMessageSuccess(BuildContext context) { switch(this) { case EventActionType.yes: @@ -62,31 +34,6 @@ enum EventActionType { return ''; } } - - Map getMapKeywords() { - switch(this) { - case EventActionType.yes: - return { - KeyWordIdentifierExtension.acceptedEventAttendance: true, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance: false, - KeyWordIdentifierExtension.rejectedEventAttendance: false, - }; - case EventActionType.maybe: - return { - KeyWordIdentifierExtension.acceptedEventAttendance: false, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance: true, - KeyWordIdentifierExtension.rejectedEventAttendance: false, - }; - case EventActionType.no: - return { - KeyWordIdentifierExtension.acceptedEventAttendance: false, - KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance: false, - KeyWordIdentifierExtension.rejectedEventAttendance: true, - }; - case EventActionType.mailToAttendees: - return {}; - } - } } class EventAction with EquatableMixin { diff --git a/lib/features/email/domain/repository/email_repository.dart b/lib/features/email/domain/repository/email_repository.dart index 99e91b455..67d55fc90 100644 --- a/lib/features/email/domain/repository/email_repository.dart +++ b/lib/features/email/domain/repository/email_repository.dart @@ -25,7 +25,6 @@ import 'package:model/email/read_actions.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart'; import 'package:tmail_ui_user/features/email/domain/model/email_print.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart'; @@ -177,12 +176,6 @@ abstract class EmailRepository { Future printEmail(EmailPrint emailPrint); - Future storeEventAttendanceStatus( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType); - Future> parseEmailByBlobIds(AccountId accountId, Set blobIds); Future generatePreviewEmailEMLContent(PreviewEmailEMLRequest previewEmailEMLRequest); diff --git a/lib/features/email/domain/state/store_event_attendance_status_state.dart b/lib/features/email/domain/state/store_event_attendance_status_state.dart deleted file mode 100644 index 835f41a65..000000000 --- a/lib/features/email/domain/state/store_event_attendance_status_state.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; - -class StoreEventAttendanceStatusLoading extends LoadingState {} - -class StoreEventAttendanceStatusSuccess extends UIState { - - final EventActionType eventActionType; - - StoreEventAttendanceStatusSuccess(this.eventActionType); - - @override - List get props => [eventActionType]; -} - -class StoreEventAttendanceStatusFailure extends FeatureFailure { - - StoreEventAttendanceStatusFailure({dynamic exception}) : super(exception: exception); -} \ No newline at end of file diff --git a/lib/features/email/domain/usecases/store_event_attendance_status_interactor.dart b/lib/features/email/domain/usecases/store_event_attendance_status_interactor.dart deleted file mode 100644 index da3fd94a4..000000000 --- a/lib/features/email/domain/usecases/store_event_attendance_status_interactor.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:core/presentation/state/failure.dart'; -import 'package:core/presentation/state/success.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/email/email.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; -import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; -import 'package:tmail_ui_user/features/email/domain/state/store_event_attendance_status_state.dart'; - -class StoreEventAttendanceStatusInteractor { - final EmailRepository _emailRepository; - - StoreEventAttendanceStatusInteractor(this._emailRepository); - - Stream> execute( - Session session, - AccountId accountId, - EmailId emailId, - EventActionType eventActionType - ) async* { - try { - yield Right(StoreEventAttendanceStatusLoading()); - - await _emailRepository.storeEventAttendanceStatus( - session, - accountId, - emailId, - eventActionType); - - yield Right(StoreEventAttendanceStatusSuccess(eventActionType)); - } catch (e) { - yield Left(StoreEventAttendanceStatusFailure(exception: e)); - } - } -} \ No newline at end of file diff --git a/lib/features/email/presentation/bindings/email_bindings.dart b/lib/features/email/presentation/bindings/email_bindings.dart index a6a52aa86..dfc18ff45 100644 --- a/lib/features/email/presentation/bindings/email_bindings.dart +++ b/lib/features/email/presentation/bindings/email_bindings.dart @@ -31,7 +31,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart'; import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart'; @@ -79,7 +78,6 @@ class EmailBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), Get.find(), Get.find(), @@ -169,7 +167,6 @@ class EmailBindings extends BaseBindings { Get.lazyPut(() => GetStoredEmailStateInteractor(Get.find())); Get.lazyPut(() => StoreOpenedEmailInteractor(Get.find())); Get.lazyPut(() => PrintEmailInteractor(Get.find())); - Get.lazyPut(() => StoreEventAttendanceStatusInteractor(Get.find())); Get.lazyPut(() => ParseEmailByBlobIdInteractor(Get.find())); Get.lazyPut(() => PreviewEmailFromEmlFileInteractor(Get.find())); IdentityInteractorsBindings().dependencies(); diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index a47f7fc64..fd0593e9c 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -25,6 +25,7 @@ import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/properties/attendee/calendar_attendee.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart'; @@ -76,7 +77,6 @@ import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml import 'package:tmail_ui_user/features/email/domain/state/preview_pdf_file_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/print_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/send_receipt_to_sender_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/store_event_attendance_status_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/download_all_attachments_for_web_interactor.dart'; @@ -97,7 +97,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_ import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_html_content_from_attachment_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/send_receipt_to_sender_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/bindings/calendar_event_interactor_bindings.dart'; @@ -105,6 +104,7 @@ import 'package:tmail_ui_user/features/email/presentation/controller/email_super import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_attendee_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_organizer_extension.dart'; +import 'package:tmail_ui_user/features/email/presentation/extensions/update_attendance_status_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/model/blob_calendar_event.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart'; @@ -171,7 +171,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final StoreOpenedEmailInteractor _storeOpenedEmailInteractor; final PrintEmailInteractor _printEmailInteractor; - final StoreEventAttendanceStatusInteractor _storeEventAttendanceStatusInteractor; final ParseEmailByBlobIdInteractor _parseEmailByBlobIdInteractor; final PreviewEmailFromEmlFileInteractor _previewEmailFromEmlFileInteractor; final GetHtmlContentFromAttachmentInteractor _getHtmlContentFromAttachmentInteractor; @@ -194,6 +193,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { final isEmailContentHidden = RxBool(false); final currentEmailLoaded = Rxn(); final isEmailContentClipped = RxBool(false); + final attendanceStatus = Rxn(); EmailId? _currentEmailId; Identity? _identitySelected; @@ -207,7 +207,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { bool get calendarEventProcessing => viewState.value.fold( (failure) => false, - (success) => success is CalendarEventReplying || success is StoreEventAttendanceStatusLoading); + (success) => success is CalendarEventReplying); CalendarEvent? get calendarEvent => blobCalendarEvent.value?.calendarEventList.firstOrNull; Id? get _displayingEventBlobId => blobCalendarEvent.value?.blobId; @@ -231,7 +231,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { this._getAllIdentitiesInteractor, this._storeOpenedEmailInteractor, this._printEmailInteractor, - this._storeEventAttendanceStatusInteractor, this._parseEmailByBlobIdInteractor, this._previewEmailFromEmlFileInteractor, this._getHtmlContentFromAttachmentInteractor, @@ -294,8 +293,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { _handlePrintEmailSuccess(success); } else if (success is CalendarEventReplySuccess) { calendarEventSuccess(success); - } else if (success is StoreEventAttendanceStatusSuccess) { - _showToastMessageEventAttendanceSuccess(success); } else if (success is ParseEmailByBlobIdSuccess) { _handleParseEmailByBlobIdSuccess(success); } else if (success is PreviewEmailFromEmlFileSuccess) { @@ -338,8 +335,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { emailLoadedViewState.value = Left(failure); } else if (failure is PrintEmailFailure) { _showMessageWhenEmailPrintingFailed(failure); - } else if (failure is CalendarEventReplyFailure - || failure is StoreEventAttendanceStatusFailure) { + } else if (failure is CalendarEventReplyFailure) { _calendarEventFailure(failure); } else if (failure is ParseEmailByBlobIdFailure) { _handleParseEmailByBlobIdFailure(failure); @@ -1869,10 +1865,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void _handleParseCalendarEventSuccess(ParseCalendarEventSuccess success) { emailLoadedViewState.value = Right(success); - blobCalendarEvent.value = success.blobCalendarEventList.first; + blobCalendarEvent.value = success.blobCalendarEventList.firstOrNull; if (PlatformInfo.isMobile) { _enableScrollPageView(); } + updateAttendanceStatus(success); } void _handleParseCalendarEventFailure(ParseCalendarEventFailure failure) { @@ -2142,24 +2139,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } void calendarEventSuccess(CalendarEventReplySuccess success) { - if (session == null || accountId == null) { - consumeState(Stream.value(Left(StoreEventAttendanceStatusFailure(exception: NotFoundSessionException())))); - return; - } - - consumeState(_storeEventAttendanceStatusInteractor.execute( - session!, - accountId!, - success.emailId, - success.getEventActionType() - )); - } - - void _showToastMessageEventAttendanceSuccess(StoreEventAttendanceStatusSuccess success) { - final newEmail = currentEmail?.updateKeywords( - success.eventActionType.getMapKeywords(), - ); - mailboxDashBoardController.setSelectedEmail(newEmail); + updateAttendanceStatus(success); if (currentOverlayContext == null || currentContext == null) { return; @@ -2167,7 +2147,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { appToast.showToastSuccessMessage( currentOverlayContext!, - success.eventActionType.getToastMessageSuccess(currentContext!)); + success.getEventActionType().getToastMessageSuccess(currentContext!)); } void _calendarEventFailure(Failure failure) { diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index aaf9ef2b8..ad5733132 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -368,7 +368,7 @@ class EmailView extends GetWidget { onCalendarEventReplyActionClick: (eventActionType) => controller.onCalendarEventReplyAction(eventActionType, presentationEmail.id!), calendarEventReplying: controller.calendarEventProcessing, - presentationEmail: controller.currentEmail, + attendanceStatus: controller.attendanceStatus.value, onMailtoAttendeesAction: controller.handleMailToAttendees, openEmailAddressDetailAction: controller.openEmailAddressDialog, isFree: controller.isCalendarEventFree, diff --git a/lib/features/email/presentation/extensions/update_attendance_status_extension.dart b/lib/features/email/presentation/extensions/update_attendance_status_extension.dart new file mode 100644 index 000000000..fd5afaf32 --- /dev/null +++ b/lib/features/email/presentation/extensions/update_attendance_status_extension.dart @@ -0,0 +1,21 @@ +import 'package:core/presentation/state/success.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_accept_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_maybe_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reject_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; +import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart'; + +extension UpdateAttendanceStatusExtension on SingleEmailController { + void updateAttendanceStatus(UIState viewState) { + attendanceStatus.value = switch (viewState) { + ParseCalendarEventSuccess( + blobCalendarEventList: final blobCalendarEventList, + ) => blobCalendarEventList.firstOrNull?.attendanceStatus, + CalendarEventAccepted() => AttendanceStatus.accepted, + CalendarEventMaybeSuccess() => AttendanceStatus.tentativelyAccepted, + CalendarEventRejected() => AttendanceStatus.rejected, + _ => attendanceStatus.value, + }; + } +} \ No newline at end of file diff --git a/lib/features/email/presentation/model/blob_calendar_event.dart b/lib/features/email/presentation/model/blob_calendar_event.dart index 9fba0be5e..6be90a7c3 100644 --- a/lib/features/email/presentation/model/blob_calendar_event.dart +++ b/lib/features/email/presentation/model/blob_calendar_event.dart @@ -1,18 +1,26 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart'; class BlobCalendarEvent with EquatableMixin { final Id blobId; final List calendarEventList; final bool isFree; + final AttendanceStatus? attendanceStatus; BlobCalendarEvent({ required this.blobId, required this.calendarEventList, this.isFree = true, + this.attendanceStatus, }); @override - List get props => [blobId, calendarEventList, isFree]; + List get props => [ + blobId, + calendarEventList, + isFree, + attendanceStatus, + ]; } \ No newline at end of file diff --git a/lib/features/email/presentation/widgets/calendar_event/calendar_event_action_button_widget.dart b/lib/features/email/presentation/widgets/calendar_event/calendar_event_action_button_widget.dart index 73dd1e37c..19fc34c56 100644 --- a/lib/features/email/presentation/widgets/calendar_event/calendar_event_action_button_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/calendar_event_action_button_widget.dart @@ -2,7 +2,7 @@ import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:model/email/presentation_email.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_action_button_widget_styles.dart'; @@ -13,7 +13,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { final EdgeInsetsGeometry? margin; final OnCalendarEventReplyActionClick onCalendarEventReplyActionClick; final bool calendarEventReplying; - final PresentationEmail? presentationEmail; + final AttendanceStatus? attendanceStatus; final VoidCallback? onMailToAttendeesAction; final _responsiveUtils = Get.find(); @@ -23,7 +23,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { required this.onCalendarEventReplyActionClick, required this.calendarEventReplying, this.margin, - this.presentationEmail, + this.attendanceStatus, this.onMailToAttendeesAction, }); @@ -69,7 +69,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { Color _getButtonBackgroundColor(EventActionType eventActionType) { switch (eventActionType) { case EventActionType.yes: - if (presentationEmail?.isAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.accepted) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } @@ -79,7 +79,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return CalendarEventActionButtonWidgetStyles.backgroundColor; case EventActionType.maybe: - if (presentationEmail!.isTentativelyAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.tentativelyAccepted) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } @@ -89,7 +89,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return CalendarEventActionButtonWidgetStyles.backgroundColor; case EventActionType.no: - if (presentationEmail?.isRejectedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.rejected) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } @@ -106,19 +106,19 @@ class CalendarEventActionButtonWidget extends StatelessWidget { Color _getButtonTextColor(EventActionType eventActionType) { switch (eventActionType) { case EventActionType.yes: - if (presentationEmail?.isAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.accepted) { return CalendarEventActionButtonWidgetStyles.selectedTextColor; } return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.maybe: - if (presentationEmail?.isTentativelyAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.tentativelyAccepted) { return CalendarEventActionButtonWidgetStyles.selectedTextColor; } return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.no: - if (presentationEmail?.isRejectedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.rejected) { return CalendarEventActionButtonWidgetStyles.selectedTextColor; } @@ -131,19 +131,19 @@ class CalendarEventActionButtonWidget extends StatelessWidget { Color _getButtonBorderColor(EventActionType eventActionType) { switch (eventActionType) { case EventActionType.yes: - if (presentationEmail?.isAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.accepted) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.maybe: - if (presentationEmail?.isTentativelyAcceptedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.tentativelyAccepted) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.no: - if (presentationEmail?.isRejectedEventAttendance == true) { + if (attendanceStatus == AttendanceStatus.rejected) { return CalendarEventActionButtonWidgetStyles.selectedBackgroundColor; } @@ -156,17 +156,17 @@ class CalendarEventActionButtonWidget extends StatelessWidget { Function()? _getCallbackFunction(EventActionType eventActionType) { switch (eventActionType) { case EventActionType.yes: - if (presentationEmail?.isAcceptedEventAttendance == true || calendarEventReplying) { + if (attendanceStatus == AttendanceStatus.accepted || calendarEventReplying) { return null; } return () => onCalendarEventReplyActionClick(eventActionType); case EventActionType.maybe: - if (presentationEmail?.isTentativelyAcceptedEventAttendance == true || calendarEventReplying) { + if (attendanceStatus == AttendanceStatus.tentativelyAccepted || calendarEventReplying) { return null; } return () => onCalendarEventReplyActionClick(eventActionType); case EventActionType.no: - if (presentationEmail?.isRejectedEventAttendance == true || calendarEventReplying) { + if (attendanceStatus == AttendanceStatus.rejected || calendarEventReplying) { return null; } return () => onCalendarEventReplyActionClick(eventActionType); diff --git a/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart index 4f4877cf1..e592161d5 100644 --- a/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart @@ -3,7 +3,7 @@ import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart'; -import 'package:model/email/presentation_email.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_detail_widget_styles.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_information_widget_styles.dart'; @@ -29,7 +29,7 @@ class CalendarEventInformationWidget extends StatelessWidget { final OnOpenComposerAction? onOpenComposerAction; final OnCalendarEventReplyActionClick onCalendarEventReplyActionClick; final bool calendarEventReplying; - final PresentationEmail? presentationEmail; + final AttendanceStatus? attendanceStatus; final OnMailtoAttendeesAction? onMailtoAttendeesAction; final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction; final bool isFree; @@ -44,7 +44,7 @@ class CalendarEventInformationWidget extends StatelessWidget { required this.isFree, this.onOpenNewTabAction, this.onOpenComposerAction, - this.presentationEmail, + this.attendanceStatus, this.onMailtoAttendeesAction, this.openEmailAddressDetailAction, }); @@ -143,7 +143,7 @@ class CalendarEventInformationWidget extends StatelessWidget { margin: EdgeInsetsDirectional.zero, onCalendarEventReplyActionClick: onCalendarEventReplyActionClick, calendarEventReplying: calendarEventReplying, - presentationEmail: presentationEmail, + attendanceStatus: attendanceStatus, onMailToAttendeesAction: () => onMailtoAttendeesAction?.call( calendarEvent.organizer, calendarEvent.participants, @@ -229,7 +229,7 @@ class CalendarEventInformationWidget extends StatelessWidget { margin: EdgeInsetsDirectional.zero, onCalendarEventReplyActionClick: onCalendarEventReplyActionClick, calendarEventReplying: calendarEventReplying, - presentationEmail: presentationEmail, + attendanceStatus: attendanceStatus, onMailToAttendeesAction: () => onMailtoAttendeesAction?.call( calendarEvent.organizer, calendarEvent.participants, diff --git a/model/lib/email/presentation_email.dart b/model/lib/email/presentation_email.dart index 7da5ce58a..eadce0da2 100644 --- a/model/lib/email/presentation_email.dart +++ b/model/lib/email/presentation_email.dart @@ -124,12 +124,6 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { bool get isSubscribed => keywords?.containsKey(KeyWordIdentifierExtension.unsubscribeMail) == true; - bool get isAcceptedEventAttendance => keywords?.containsKey(KeyWordIdentifierExtension.acceptedEventAttendance) == true; - - bool get isTentativelyAcceptedEventAttendance => keywords?.containsKey(KeyWordIdentifierExtension.tentativelyAcceptedEventAttendance) == true; - - bool get isRejectedEventAttendance => keywords?.containsKey(KeyWordIdentifierExtension.rejectedEventAttendance) == true; - bool get isAnsweredAndForwarded => isAnswered && isForwarded; bool get withAttachments => hasAttachment == true; diff --git a/model/lib/extensions/keyword_identifier_extension.dart b/model/lib/extensions/keyword_identifier_extension.dart index 4cf8d3e00..4f0bcfeec 100644 --- a/model/lib/extensions/keyword_identifier_extension.dart +++ b/model/lib/extensions/keyword_identifier_extension.dart @@ -5,9 +5,6 @@ import 'package:model/email/read_actions.dart'; extension KeyWordIdentifierExtension on KeyWordIdentifier { static final unsubscribeMail = KeyWordIdentifier('\$unsubscribe'); - static final acceptedEventAttendance = KeyWordIdentifier('\$accepted'); - static final tentativelyAcceptedEventAttendance = KeyWordIdentifier('\$tentativelyaccepted'); - static final rejectedEventAttendance = KeyWordIdentifier('\$rejected'); String generatePath() { return '${PatchObject.keywordsProperty}/$value'; diff --git a/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart b/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart deleted file mode 100644 index 096c62f91..000000000 --- a/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart +++ /dev/null @@ -1,93 +0,0 @@ -import 'package:dartz/dartz.dart' hide State; -import 'package:flutter_test/flutter_test.dart'; -import 'package:jmap_dart_client/jmap/mail/email/email.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; -import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; -import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; -import 'package:tmail_ui_user/features/email/domain/state/store_event_attendance_status_state.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart'; - -import '../../../../fixtures/account_fixtures.dart'; -import '../../../../fixtures/email_fixtures.dart'; -import '../../../../fixtures/session_fixtures.dart'; - -import 'store_event_attendance_status_interactor_test.mocks.dart'; - -@GenerateNiceMocks([ - MockSpec() -]) -void main() { - group('StoreEventAttendanceStatusInteractor test', () { - late MockEmailRepository mockEmailRepository; - late StoreEventAttendanceStatusInteractor storeEventAttendanceStatusInteractor; - - setUp(() { - mockEmailRepository = MockEmailRepository(); - storeEventAttendanceStatusInteractor = StoreEventAttendanceStatusInteractor(mockEmailRepository); - }); - - final sessionFixture = SessionFixtures.aliceSession; - final accountIdFixture = AccountFixtures.aliceAccountId; - final emailIdFixture = EmailFixtures.emailId; - const eventActionType = EventActionType.yes; - - test('SHOULD emit loading and success states when storeEventAttendanceStatus is successful', () async { - final updatedEmail = Email(id: emailIdFixture); - - when(mockEmailRepository.storeEventAttendanceStatus( - sessionFixture, - accountIdFixture, - emailIdFixture, - eventActionType - )).thenAnswer((_) async => updatedEmail); - - final result = storeEventAttendanceStatusInteractor.execute( - sessionFixture, - accountIdFixture, - emailIdFixture, - eventActionType); - - await expectLater( - result, - emitsInOrder([ - Right(StoreEventAttendanceStatusLoading()), - Right(StoreEventAttendanceStatusSuccess(eventActionType)), - ]), - ); - - verify(mockEmailRepository.storeEventAttendanceStatus( - sessionFixture, - accountIdFixture, - emailIdFixture, - eventActionType - )).called(1); - verifyNoMoreInteractions(mockEmailRepository); - }); - - test('SHOULD emit loading and failure states when storeEventAttendanceStatus throws an exception', () async { - final exception = Exception(); - - when(mockEmailRepository.storeEventAttendanceStatus( - sessionFixture, - accountIdFixture, - emailIdFixture, - eventActionType, - )).thenThrow(exception); - - final result = storeEventAttendanceStatusInteractor.execute( - sessionFixture, - accountIdFixture, - emailIdFixture, - eventActionType); - - await expectLater( - result, - emitsInOrder([ - Right(StoreEventAttendanceStatusLoading()), - Left(StoreEventAttendanceStatusFailure(exception: exception)), - ]), - ); - }); - }); -} \ No newline at end of file diff --git a/test/features/email/presentation/controller/single_email_controller_test.dart b/test/features/email/presentation/controller/single_email_controller_test.dart index a6e38d6b7..73ea634e5 100644 --- a/test/features/email/presentation/controller/single_email_controller_test.dart +++ b/test/features/email/presentation/controller/single_email_controller_test.dart @@ -14,7 +14,6 @@ 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/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart'; -import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -25,7 +24,6 @@ import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasourc import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart'; import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart'; import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; -import 'package:tmail_ui_user/features/email/domain/state/calendar_event_accept_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/download_all_attachments_for_web_interactor.dart'; @@ -44,7 +42,6 @@ import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_even import 'package:tmail_ui_user/features/email/domain/usecases/parse_email_by_blob_id_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/preview_email_from_eml_file_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart'; -import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart'; @@ -65,7 +62,6 @@ import 'package:tmail_ui_user/main/utils/twake_app_manager.dart'; import 'package:uuid/uuid.dart'; import '../../../../fixtures/account_fixtures.dart'; -import '../../../../fixtures/email_fixtures.dart'; import 'single_email_controller_test.mocks.dart'; mockControllerCallback() => InternalFinalCallback(callback: () {}); @@ -103,7 +99,6 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), - MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -146,7 +141,6 @@ void main() { final responsiveUtils = MockResponsiveUtils(); final uuid = MockUuid(); final printEmailInteractor = MockPrintEmailInteractor(); - final storeEventAttendanceStatusInteractor = MockStoreEventAttendanceStatusInteractor(); final parseEmailByBlobIdInteractor = MockParseEmailByBlobIdInteractor(); final previewEmailFromEmlFileInteractor = MockPreviewEmailFromEmlFileInteractor(); final printUtils = MockPrintUtils(); @@ -211,7 +205,6 @@ void main() { getAllIdentitiesInteractor, storeOpenedEmailInteractor, printEmailInteractor, - storeEventAttendanceStatusInteractor, parseEmailByBlobIdInteractor, previewEmailFromEmlFileInteractor, getHtmlContentFromAttachmentInteractor, @@ -320,88 +313,6 @@ void main() { }); }); - group('StoreEventAttendanceStatusInteractor test', () { - - setUp(() { - debugDefaultTargetPlatformOverride = TargetPlatform.macOS; - }); - - group('calendarEventSuccess method test', () { - test( - 'SHOULD call execute on StoreEventAttendanceStatusInteractor\n' - 'WHEN calendarEventSuccess method is called', - () { - when(mailboxDashboardController.sessionCurrent).thenReturn(testSession); - - final eventAcceptedSuccess = CalendarEventAccepted( - CalendarEventAcceptResponse(testAccountId, null), - EmailFixtures.emailId); - - singleEmailController.calendarEventSuccess(eventAcceptedSuccess); - - verify(storeEventAttendanceStatusInteractor.execute( - testSession, - testAccountId, - EmailFixtures.emailId, - EventActionType.yes, - )).called(1); - }); - }); - - group('onCalendarEventReplyAction method test', () { - test( - 'SHOULD call execute on StoreEventAttendanceStatusInteractor\n' - 'WHEN onCalendarEventReplyAction is called on EventActionType.yes\n' - 'AND return success', - () async { - final acceptCalendarEventInteractor = MockAcceptCalendarEventInteractor(); - final blobId = Id('abc123'); - final emailId = EmailId(Id('xyz123')); - final calendarEvent = CalendarEvent(); - - when(mailboxDashboardController.sessionCurrent).thenReturn(testSession); - when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(null)); - when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(null)); - when(mailboxDashboardController.viewState).thenReturn(Rx(Right(UIState.idle))); - - singleEmailController.onInit(); - - Get.put(acceptCalendarEventInteractor); - - mailboxDashboardController.accountId.refresh(); - - singleEmailController.handleSuccessViewState( - ParseCalendarEventSuccess([ - BlobCalendarEvent( - blobId: blobId, - calendarEventList: [calendarEvent] - ) - ]) - ); - - singleEmailController.onCalendarEventReplyAction(EventActionType.yes, emailId); - - singleEmailController.calendarEventSuccess(CalendarEventAccepted( - CalendarEventAcceptResponse(testAccountId, null), - emailId - )); - - await untilCalled(storeEventAttendanceStatusInteractor.execute(any, any, any, any)); - - verify(storeEventAttendanceStatusInteractor.execute( - testSession, - testAccountId, - emailId, - EventActionType.yes, - )).called(1); - }); - }); - - tearDown(() { - debugDefaultTargetPlatformOverride = null; - }); - }); - group('_parseCalendarEventAction method test:', () { final calendarEventDataSource = MockCalendarEventDataSource(); final calendarEventRepository = CalendarEventRepositoryImpl( diff --git a/test/features/email/presentation/extensions/update_attendance_status_extension_test.dart b/test/features/email/presentation/extensions/update_attendance_status_extension_test.dart new file mode 100644 index 000000000..d0373707a --- /dev/null +++ b/test/features/email/presentation/extensions/update_attendance_status_extension_test.dart @@ -0,0 +1,141 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_maybe_response.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_reject_response.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_accept_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_maybe_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reject_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; +import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart'; +import 'package:tmail_ui_user/features/email/presentation/extensions/update_attendance_status_extension.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/blob_calendar_event.dart'; + +import 'update_attendance_status_extension_test.mocks.dart'; + +@GenerateNiceMocks([ + MockSpec(), +]) +void main() { + final controller = MockSingleEmailController(); + group('update attendance status extension test', () { + test( + 'should update attendance status ' + 'when viewState is ParseCalendarEventSuccess', + () { + // Arrange + when(controller.attendanceStatus).thenReturn( + Rxn(AttendanceStatus.accepted), + ); + final viewState = ParseCalendarEventSuccess([ + BlobCalendarEvent( + blobId: Id('1'), + calendarEventList: [], + attendanceStatus: AttendanceStatus.accepted, + ), + ]); + + // Act + controller.updateAttendanceStatus(viewState); + + // Assert + expect( + controller.attendanceStatus.value, + viewState.blobCalendarEventList.firstOrNull?.attendanceStatus, + ); + }); + test( + 'should return current attendance status ' + 'when viewState is CalendarEventAccepted', + () { + // Arrange + when(controller.attendanceStatus).thenReturn(Rxn()); + final viewState = CalendarEventAccepted( + CalendarEventAcceptResponse( + AccountId(Id('1')), + [Id('1')], + ), + EmailId(Id('1')), + ); + + // Act + controller.updateAttendanceStatus(viewState); + + // Assert + expect( + controller.attendanceStatus.value, + AttendanceStatus.accepted, + ); + }); + test( + 'should return current attendance status ' + 'when viewState is CalendarEventMaybeSuccess', + () { + // Arrange + when(controller.attendanceStatus).thenReturn(Rxn()); + final viewState = CalendarEventMaybeSuccess( + CalendarEventMaybeResponse( + AccountId(Id('1')), + [Id('1')], + ), + EmailId(Id('1')), + ); + + // Act + controller.updateAttendanceStatus(viewState); + + // Assert + expect( + controller.attendanceStatus.value, + AttendanceStatus.tentativelyAccepted, + ); + }); + test( + 'should return current attendance status ' + 'when viewState is CalendarEventRejected', + () { + // Arrange + when(controller.attendanceStatus).thenReturn(Rxn()); + final viewState = CalendarEventRejected( + CalendarEventRejectResponse( + AccountId(Id('1')), + [Id('1')], + ), + EmailId(Id('1')), + ); + + // Act + controller.updateAttendanceStatus(viewState); + + // Assert + expect( + controller.attendanceStatus.value, + AttendanceStatus.rejected, + ); + }); + test( + 'should keep current attendance status ' + 'when viewState is other', + () { + // Arrange + const currentStatus = AttendanceStatus.accepted; + when(controller.attendanceStatus).thenReturn(Rxn(currentStatus)); + final viewState = ParseCalendarEventLoading(); + + // Act + controller.updateAttendanceStatus(viewState); + + // Assert + expect( + controller.attendanceStatus.value, + currentStatus, + ); + }); + }); +} \ No newline at end of file