From 9df53ef6b96b571a1edb8eaf1673e93e112d643f Mon Sep 17 00:00:00 2001 From: DatDang Date: Wed, 16 Apr 2025 09:37:42 +0700 Subject: [PATCH] TF-3591 Implement CalendarEventCounter/accept method --- contact/pubspec.lock | 4 +- email_recovery/pubspec.lock | 4 +- fcm/pubspec.lock | 4 +- forward/pubspec.lock | 4 +- .../datasource/calendar_event_datasource.dart | 4 ++ .../calendar_event_datasource_impl.dart | 10 ++++ .../data/network/calendar_event_api.dart | 32 +++++++++++++ .../calendar_event_repository_impl.dart | 9 ++++ .../list_event_actions_extension.dart | 15 ++++++ .../email/domain/model/event_action.dart | 4 ++ .../repository/calendar_event_repository.dart | 5 ++ .../calendar_event_counter_accept_state.dart | 16 +++++++ ...endar_event_counter_accept_interactor.dart | 29 ++++++++++++ .../calendar_event_interactor_bindings.dart | 2 + .../controller/single_email_controller.dart | 28 ++++++++++- .../email/presentation/email_view.dart | 3 +- .../update_attendance_status_extension.dart | 2 + .../calendar_event_action_button_widget.dart | 10 ++++ .../calendar_event_information_widget.dart | 9 ++-- lib/l10n/intl_messages.arb | 6 +++ lib/main/localizations/app_localizations.dart | 7 +++ model/lib/extensions/session_extension.dart | 8 ++++ model/pubspec.lock | 4 +- pubspec.lock | 4 +- rule_filter/pubspec.lock | 4 +- server_settings/pubspec.lock | 4 +- .../list_event_actions_extension_test.dart | 46 +++++++++++++++++++ 27 files changed, 256 insertions(+), 21 deletions(-) create mode 100644 lib/features/email/domain/extensions/list_event_actions_extension.dart create mode 100644 lib/features/email/domain/state/calendar_event_counter_accept_state.dart create mode 100644 lib/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart create mode 100644 test/features/email/domain/extensions/list_event_actions_extension_test.dart diff --git a/contact/pubspec.lock b/contact/pubspec.lock index 297b88192..a9c43212f 100644 --- a/contact/pubspec.lock +++ b/contact/pubspec.lock @@ -653,10 +653,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/email_recovery/pubspec.lock b/email_recovery/pubspec.lock index cde1eb3ab..2d165bc68 100644 --- a/email_recovery/pubspec.lock +++ b/email_recovery/pubspec.lock @@ -296,10 +296,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/fcm/pubspec.lock b/fcm/pubspec.lock index 13c974fe0..88fcb00f9 100644 --- a/fcm/pubspec.lock +++ b/fcm/pubspec.lock @@ -296,10 +296,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/forward/pubspec.lock b/forward/pubspec.lock index 13c974fe0..88fcb00f9 100644 --- a/forward/pubspec.lock +++ b/forward/pubspec.lock @@ -296,10 +296,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/lib/features/email/data/datasource/calendar_event_datasource.dart b/lib/features/email/data/datasource/calendar_event_datasource.dart index 7097a82b4..66c8d4bc3 100644 --- a/lib/features/email/data/datasource/calendar_event_datasource.dart +++ b/lib/features/email/data/datasource/calendar_event_datasource.dart @@ -23,4 +23,8 @@ abstract class CalendarEventDataSource { AccountId accountId, Set blobIds, String? language); + + Future acceptCounterEvent( + AccountId accountId, + Set blobIds); } \ No newline at end of file diff --git a/lib/features/email/data/datasource_impl/calendar_event_datasource_impl.dart b/lib/features/email/data/datasource_impl/calendar_event_datasource_impl.dart index f969482d4..8b414ff03 100644 --- a/lib/features/email/data/datasource_impl/calendar_event_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/calendar_event_datasource_impl.dart @@ -52,4 +52,14 @@ class CalendarEventDataSourceImpl extends CalendarEventDataSource { return await _calendarEventAPI.rejectEventInvitation(accountId, blobIds, language); }).catchError(_exceptionThrower.throwException); } + + @override + Future acceptCounterEvent( + AccountId accountId, + Set blobIds, + ) { + return Future.sync(() async { + return await _calendarEventAPI.acceptCounterEvent(accountId, blobIds); + }).catchError(_exceptionThrower.throwException); + } } \ No newline at end of file diff --git a/lib/features/email/data/network/calendar_event_api.dart b/lib/features/email/data/network/calendar_event_api.dart index 3c6f0a37b..622a5ff69 100644 --- a/lib/features/email/data/network/calendar_event_api.dart +++ b/lib/features/email/data/network/calendar_event_api.dart @@ -13,6 +13,7 @@ import 'package:jmap_dart_client/jmap/mail/calendar/parse/calendar_event_parse_m import 'package:jmap_dart_client/jmap/mail/calendar/parse/calendar_event_parse_response.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_method.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_counter_accept_method.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_maybe_method.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_method.dart'; @@ -192,4 +193,35 @@ class CalendarEventAPI { throw CannotReplyCalendarEventException(mapErrors: calendarEventRejectResponse.notRejected); } } + + Future acceptCounterEvent( + AccountId accountId, + Set blobIds, + ) async { + final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); + final calendarEventCounterAcceptMethod = CalendarEventCounterAcceptMethod( + accountId, + blobIds: blobIds.toList()); + final calendarEventAcceptInvocation = requestBuilder.invocation( + calendarEventCounterAcceptMethod, + ); + final response = await (requestBuilder + ..usings(calendarEventCounterAcceptMethod.requiredCapabilities)) + .build() + .execute(); + + final calendarEventAcceptResponse = response.parse( + calendarEventAcceptInvocation.methodCallId, + CalendarEventAcceptResponse.deserialize); + + if (calendarEventAcceptResponse == null) { + throw NotAcceptableCalendarEventException(); + } + + if (calendarEventAcceptResponse.accepted?.isNotEmpty == true) { + return calendarEventAcceptResponse; + } else { + throw CannotReplyCalendarEventException(mapErrors: calendarEventAcceptResponse.notAccepted); + } + } } \ No newline at end of file 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 fc92b1fe1..4807031c8 100644 --- a/lib/features/email/data/repository/calendar_event_repository_impl.dart +++ b/lib/features/email/data/repository/calendar_event_repository_impl.dart @@ -85,4 +85,13 @@ class CalendarEventRepositoryImpl extends CalendarEventRepository { : calendarEvent.description, ); } + + @override + Future acceptCounterEvent( + AccountId accountId, + Set blobIds, + ) { + return _calendarEventDataSource[DataSourceType.network]! + .acceptCounterEvent(accountId, blobIds); + } } \ No newline at end of file diff --git a/lib/features/email/domain/extensions/list_event_actions_extension.dart b/lib/features/email/domain/extensions/list_event_actions_extension.dart new file mode 100644 index 000000000..08ad29631 --- /dev/null +++ b/lib/features/email/domain/extensions/list_event_actions_extension.dart @@ -0,0 +1,15 @@ +import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart'; +import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; + +extension ListEventActionsExtension on List { + List validActionsOfEventMethod(EventMethod? eventMethod) { + return where((action) { + if (eventMethod != EventMethod.counter) { + return action != EventActionType.acceptCounter; + } + + return action == EventActionType.acceptCounter + || action == EventActionType.mailToAttendees; + }).toList(); + } +} \ 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 53e56db41..69c8302c9 100644 --- a/lib/features/email/domain/model/event_action.dart +++ b/lib/features/email/domain/model/event_action.dart @@ -5,6 +5,7 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum EventActionType { yes, + acceptCounter, maybe, no, mailToAttendees; @@ -12,6 +13,7 @@ enum EventActionType { String getLabelButton(BuildContext context) { switch(this) { case EventActionType.yes: + case EventActionType.acceptCounter: return AppLocalizations.of(context).yes; case EventActionType.maybe: return AppLocalizations.of(context).maybe; @@ -26,6 +28,8 @@ enum EventActionType { switch(this) { case EventActionType.yes: return AppLocalizations.of(context).youWillAttendThisMeeting; + case EventActionType.acceptCounter: + return AppLocalizations.of(context).youAcceptedTheProposedTimeForThisMeeting; case EventActionType.maybe: return AppLocalizations.of(context).youMayAttendThisMeeting; case EventActionType.no: diff --git a/lib/features/email/domain/repository/calendar_event_repository.dart b/lib/features/email/domain/repository/calendar_event_repository.dart index cf2f19318..0417da8cd 100644 --- a/lib/features/email/domain/repository/calendar_event_repository.dart +++ b/lib/features/email/domain/repository/calendar_event_repository.dart @@ -28,4 +28,9 @@ abstract class CalendarEventRepository { Future> transformCalendarEventDescription( List blobCalendarEvents, TransformConfiguration transformConfiguration); + + Future acceptCounterEvent( + AccountId accountId, + Set blobIds, + ); } \ No newline at end of file diff --git a/lib/features/email/domain/state/calendar_event_counter_accept_state.dart b/lib/features/email/domain/state/calendar_event_counter_accept_state.dart new file mode 100644 index 000000000..fbbae9d47 --- /dev/null +++ b/lib/features/email/domain/state/calendar_event_counter_accept_state.dart @@ -0,0 +1,16 @@ +import 'package:core/presentation/state/success.dart'; +import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.dart'; + +class CalendarEventCounterAccepting extends LoadingState {} + +class CalendarEventCounterAccepted extends CalendarEventReplySuccess { + CalendarEventCounterAccepted(super.calendarEventAcceptResponse, super.emailId); + + @override + EventActionType getEventActionType() => EventActionType.acceptCounter; +} + +class CalendarEventCounterAcceptFailure extends CalendarEventReplyFailure { + CalendarEventCounterAcceptFailure({super.exception}); +} \ No newline at end of file diff --git a/lib/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart b/lib/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart new file mode 100644 index 000000000..87ee13446 --- /dev/null +++ b/lib/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart @@ -0,0 +1,29 @@ +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/id.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_counter_accept_state.dart'; + +class AcceptCounterCalendarEventInteractor { + AcceptCounterCalendarEventInteractor(this._calendarEventRepository); + + final CalendarEventRepository _calendarEventRepository; + + Stream> execute( + AccountId accountId, + Set blobIds, + EmailId emailId, + ) async* { + try { + yield Right(CalendarEventCounterAccepting()); + final result = await _calendarEventRepository + .acceptCounterEvent(accountId, blobIds); + yield Right(CalendarEventCounterAccepted(result, emailId)); + } catch (e) { + yield Left(CalendarEventCounterAcceptFailure(exception: e)); + } + } +} \ No newline at end of file diff --git a/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart b/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart index 7d841f8ea..ed9508c0c 100644 --- a/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart +++ b/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart @@ -11,6 +11,7 @@ import 'package:tmail_ui_user/features/email/data/network/calendar_event_api.dar import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart'; import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart'; +import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_counter_accept_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/maybe_calendar_event_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart'; @@ -42,6 +43,7 @@ class CalendarEventInteractorBindings extends InteractorsBindings { Get.lazyPut(() => AcceptCalendarEventInteractor(Get.find())); Get.lazyPut(() => MaybeCalendarEventInteractor(Get.find())); Get.lazyPut(() => RejectCalendarEventInteractor(Get.find())); + Get.lazyPut(() => AcceptCounterCalendarEventInteractor(Get.find())); } @override diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index ab7b5c09f..15bd1f03c 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -58,6 +58,7 @@ import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_requ import 'package:tmail_ui_user/features/email/domain/model/send_receipt_to_sender_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.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_counter_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/calendar_event_reply_state.dart'; @@ -80,6 +81,7 @@ 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/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/calendar_event_counter_accept_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/download_all_attachments_for_web_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_entire_message_as_document_interactor.dart'; @@ -184,6 +186,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { AcceptCalendarEventInteractor? _acceptCalendarEventInteractor; MaybeCalendarEventInteractor? _maybeCalendarEventInteractor; RejectCalendarEventInteractor? _rejectCalendarEventInteractor; + AcceptCounterCalendarEventInteractor? _acceptCounterCalendarEventInteractor; final emailContents = RxnString(); final attachments = [].obs; @@ -535,6 +538,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { _acceptCalendarEventInteractor = getBinding(); _maybeCalendarEventInteractor = getBinding(); _rejectCalendarEventInteractor = getBinding(); + _acceptCounterCalendarEventInteractor = getBinding(); } void _injectCalendarEventBindings(Session? session, AccountId? accountId) { @@ -2084,6 +2088,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { case EventActionType.yes: _acceptCalendarEventAction(emailId); break; + case EventActionType.acceptCounter: + _acceptCounterCalendarEventAction(emailId); case EventActionType.maybe: _maybeCalendarEventAction(emailId); break; @@ -2095,6 +2101,25 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } + void _acceptCounterCalendarEventAction(EmailId emailId) { + if (canNotAcceptCounterCalendarEvent) { + consumeState(Stream.value(Left(CalendarEventCounterAcceptFailure()))); + } else { + consumeState(_acceptCounterCalendarEventInteractor!.execute( + accountId!, + {_displayingEventBlobId!}, + emailId, + )); + } + } + + bool get canNotAcceptCounterCalendarEvent => _acceptCounterCalendarEventInteractor == null + || _displayingEventBlobId == null + || accountId == null + || session == null + || session!.validateCalendarEventCapability(accountId!).isAvailable == false + || !session!.validateAcceptCounterCalendarEventCapability(accountId!); + void _acceptCalendarEventAction(EmailId emailId) { if (_acceptCalendarEventInteractor == null || _displayingEventBlobId == null @@ -2167,7 +2192,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { appToast.showToastSuccessMessage( currentOverlayContext!, - success.getEventActionType().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 d24b324d0..957c185e3 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -366,12 +366,13 @@ class EmailView extends GetWidget { onOpenComposerAction: controller.openNewComposerAction, onOpenNewTabAction: controller.openNewTabAction, onCalendarEventReplyActionClick: (eventActionType) => - controller.onCalendarEventReplyAction(eventActionType, presentationEmail.id!), + controller.onCalendarEventReplyAction(eventActionType, presentationEmail.id!), calendarEventReplying: controller.calendarEventProcessing, attendanceStatus: controller.attendanceStatus.value, onMailtoAttendeesAction: controller.handleMailToAttendees, openEmailAddressDetailAction: controller.openEmailAddressDialog, isFree: controller.isCalendarEventFree, + listEmailAddressSender: emailAddressSender ?? [], )), if (_validateDisplayEventActionBanner( context: context, diff --git a/lib/features/email/presentation/extensions/update_attendance_status_extension.dart b/lib/features/email/presentation/extensions/update_attendance_status_extension.dart index fd5afaf32..973be5dd0 100644 --- a/lib/features/email/presentation/extensions/update_attendance_status_extension.dart +++ b/lib/features/email/presentation/extensions/update_attendance_status_extension.dart @@ -1,6 +1,7 @@ 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_counter_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'; @@ -15,6 +16,7 @@ extension UpdateAttendanceStatusExtension on SingleEmailController { CalendarEventAccepted() => AttendanceStatus.accepted, CalendarEventMaybeSuccess() => AttendanceStatus.tentativelyAccepted, CalendarEventRejected() => AttendanceStatus.rejected, + CalendarEventCounterAccepted() => AttendanceStatus.accepted, _ => attendanceStatus.value, }; } 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 19fc34c56..e2a6a1a54 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 @@ -3,6 +3,8 @@ import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart'; +import 'package:tmail_ui_user/features/email/domain/extensions/list_event_actions_extension.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,6 +15,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { final EdgeInsetsGeometry? margin; final OnCalendarEventReplyActionClick onCalendarEventReplyActionClick; final bool calendarEventReplying; + final EventMethod? eventMethod; final AttendanceStatus? attendanceStatus; final VoidCallback? onMailToAttendeesAction; @@ -22,6 +25,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { super.key, required this.onCalendarEventReplyActionClick, required this.calendarEventReplying, + required this.eventMethod, this.margin, this.attendanceStatus, this.onMailToAttendeesAction, @@ -39,6 +43,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { spacing: CalendarEventActionButtonWidgetStyles.space, runSpacing: CalendarEventActionButtonWidgetStyles.space, children: EventActionType.values + .validActionsOfEventMethod(eventMethod) .map((action) => AbsorbPointer( absorbing: _getCallbackFunction(action) == null, child: TMailButtonWidget( @@ -99,6 +104,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return CalendarEventActionButtonWidgetStyles.backgroundColor; case EventActionType.mailToAttendees: + case EventActionType.acceptCounter: return CalendarEventActionButtonWidgetStyles.backgroundColor; } } @@ -124,6 +130,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.mailToAttendees: + case EventActionType.acceptCounter: return CalendarEventActionButtonWidgetStyles.textColor; } } @@ -149,6 +156,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return CalendarEventActionButtonWidgetStyles.textColor; case EventActionType.mailToAttendees: + case EventActionType.acceptCounter: return CalendarEventActionButtonWidgetStyles.textColor; } } @@ -160,6 +168,8 @@ class CalendarEventActionButtonWidget extends StatelessWidget { return null; } return () => onCalendarEventReplyActionClick(eventActionType); + case EventActionType.acceptCounter: + return () => onCalendarEventReplyActionClick(eventActionType); case EventActionType.maybe: if (attendanceStatus == AttendanceStatus.tentativelyAccepted || calendarEventReplying) { return null; 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 e592161d5..cebd3617a 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 @@ -16,7 +16,6 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_title_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_sender_builder.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; typedef OnOpenNewTabAction = void Function(String link); @@ -33,6 +32,7 @@ class CalendarEventInformationWidget extends StatelessWidget { final OnMailtoAttendeesAction? onMailtoAttendeesAction; final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction; final bool isFree; + final List listEmailAddressSender; final _responsiveUtils = Get.find(); @@ -47,6 +47,7 @@ class CalendarEventInformationWidget extends StatelessWidget { this.attendanceStatus, this.onMailtoAttendeesAction, this.openEmailAddressDetailAction, + this.listEmailAddressSender = const [], }); @override @@ -107,7 +108,7 @@ class CalendarEventInformationWidget extends StatelessWidget { fontWeight: FontWeight.w700 ), ), - TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation) + TextSpan(text: calendarEvent.getTitleEventAction(context, listEmailAddressSender)) ] ) ), @@ -142,6 +143,7 @@ class CalendarEventInformationWidget extends StatelessWidget { CalendarEventActionButtonWidget( margin: EdgeInsetsDirectional.zero, onCalendarEventReplyActionClick: onCalendarEventReplyActionClick, + eventMethod: calendarEvent.method, calendarEventReplying: calendarEventReplying, attendanceStatus: attendanceStatus, onMailToAttendeesAction: () => onMailtoAttendeesAction?.call( @@ -193,7 +195,7 @@ class CalendarEventInformationWidget extends StatelessWidget { fontWeight: FontWeight.w700 ), ), - TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation) + TextSpan(text: calendarEvent.getTitleEventAction(context, listEmailAddressSender)) ] ) ), @@ -228,6 +230,7 @@ class CalendarEventInformationWidget extends StatelessWidget { CalendarEventActionButtonWidget( margin: EdgeInsetsDirectional.zero, onCalendarEventReplyActionClick: onCalendarEventReplyActionClick, + eventMethod: calendarEvent.method, calendarEventReplying: calendarEventReplying, attendanceStatus: attendanceStatus, onMailToAttendeesAction: () => onMailtoAttendeesAction?.call( diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index f7dac30be..7c996afc6 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -3832,6 +3832,12 @@ "placeholders_order": [], "placeholders": {} }, + "youAcceptedTheProposedTimeForThisMeeting": "You accepted the proposed time for this meeting", + "@youAcceptedTheProposedTimeForThisMeeting": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, "downloadMessageAsEML": "Download message as EML", "@downloadMessageAsEML": { "type": "text", diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 154a96ea6..e0a57f205 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -3989,6 +3989,13 @@ class AppLocalizations { ); } + String get youAcceptedTheProposedTimeForThisMeeting { + return Intl.message( + 'You accepted the proposed time for this meeting', + name: 'youAcceptedTheProposedTimeForThisMeeting', + ); + } + String get downloadMessageAsEML { return Intl.message( 'Download message as EML', diff --git a/model/lib/extensions/session_extension.dart b/model/lib/extensions/session_extension.dart index 5fb3fb342..8e9b34fa6 100644 --- a/model/lib/extensions/session_extension.dart +++ b/model/lib/extensions/session_extension.dart @@ -130,6 +130,14 @@ extension SessionExtension on Session { return (isAvailable: capability != null, calendarEventCapability: capability); } + bool validateAcceptCounterCalendarEventCapability(AccountId accountId) { + final capability = getCapabilityProperties( + accountId, + CapabilityIdentifier.jamesCalendarEvent); + + return capability?.counterSupport == true; + } + String? getLanguageForCalendarEvent( Locale locale, AccountId accountId, diff --git a/model/pubspec.lock b/model/pubspec.lock index feaaeff93..9b01cba24 100644 --- a/model/pubspec.lock +++ b/model/pubspec.lock @@ -645,10 +645,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/pubspec.lock b/pubspec.lock index 320ee2f6d..f6fd6914f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1325,10 +1325,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/rule_filter/pubspec.lock b/rule_filter/pubspec.lock index 13c974fe0..88fcb00f9 100644 --- a/rule_filter/pubspec.lock +++ b/rule_filter/pubspec.lock @@ -296,10 +296,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/server_settings/pubspec.lock b/server_settings/pubspec.lock index e4f7c775f..2e887cb09 100644 --- a/server_settings/pubspec.lock +++ b/server_settings/pubspec.lock @@ -288,10 +288,10 @@ packages: description: path: "." ref: main - resolved-ref: "708658c13e013882fde91c5afba886bd67641f8f" + resolved-ref: "131bdbb2fb5ed268b8c8469d532f70b42ac4e15a" url: "https://github.com/linagora/jmap-dart-client.git" source: git - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: diff --git a/test/features/email/domain/extensions/list_event_actions_extension_test.dart b/test/features/email/domain/extensions/list_event_actions_extension_test.dart new file mode 100644 index 000000000..08694d9b4 --- /dev/null +++ b/test/features/email/domain/extensions/list_event_actions_extension_test.dart @@ -0,0 +1,46 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart'; +import 'package:tmail_ui_user/features/email/domain/extensions/list_event_actions_extension.dart'; +import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; + +void main() { + group('list event actions extension test:', () { + group('validActionsOfEventMethod test:', () { + test( + 'should return all but acceptCounter ' + 'when event method is not counter', + () { + // arrange + const method = EventMethod.add; + + // act + final result = EventActionType.values.validActionsOfEventMethod(method); + + // assert + expect(result, equals([ + EventActionType.yes, + EventActionType.maybe, + EventActionType.no, + EventActionType.mailToAttendees, + ])); + }); + + test( + 'should only return acceptCounter and mailToAttendees ' + 'when event method is counter', + () { + // arrange + const method = EventMethod.counter; + + // act + final result = EventActionType.values.validActionsOfEventMethod(method); + + // assert + expect(result, equals([ + EventActionType.acceptCounter, + EventActionType.mailToAttendees, + ])); + }); + }); + }); +} \ No newline at end of file