TF-3792 Hide buttons of blue bar in case of event not belong to this account and change
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -134,7 +134,7 @@ class PreviewEmlFileUtils {
|
|||||||
|
|
||||||
String generatePreviewEml({
|
String generatePreviewEml({
|
||||||
required String appName,
|
required String appName,
|
||||||
required String userName,
|
required String ownEmailAddress,
|
||||||
required String subjectPrefix,
|
required String subjectPrefix,
|
||||||
required String subject,
|
required String subject,
|
||||||
required String emailContent,
|
required String emailContent,
|
||||||
@@ -154,7 +154,7 @@ class PreviewEmlFileUtils {
|
|||||||
String? replyToAddress,
|
String? replyToAddress,
|
||||||
List<PreviewAttachment>? listAttachment,
|
List<PreviewAttachment>? listAttachment,
|
||||||
}) {
|
}) {
|
||||||
Document document = parse(HtmlUtils.createTemplateHtmlDocument(title: '$subject - $userName'));
|
Document document = parse(HtmlUtils.createTemplateHtmlDocument(title: '$subject - $ownEmailAddress'));
|
||||||
|
|
||||||
Element? emailElement = _createEmailElement(
|
Element? emailElement = _createEmailElement(
|
||||||
subjectPrefix: subjectPrefix,
|
subjectPrefix: subjectPrefix,
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ class EmailDataSourceImpl extends EmailDataSource {
|
|||||||
|
|
||||||
final previewEmlHtmlDocument = _previewEmailUtils.generatePreviewEml(
|
final previewEmlHtmlDocument = _previewEmailUtils.generatePreviewEml(
|
||||||
appName: appLocalizations.app_name,
|
appName: appLocalizations.app_name,
|
||||||
userName: previewEmailEMLRequest.userName.value,
|
ownEmailAddress: previewEmailEMLRequest.ownEmailAddress,
|
||||||
subjectPrefix: appLocalizations.subject,
|
subjectPrefix: appLocalizations.subject,
|
||||||
subject: previewEmailEMLRequest.email.subject?.escapeLtGtHtmlString() ?? '',
|
subject: previewEmailEMLRequest.email.subject?.escapeLtGtHtmlString() ?? '',
|
||||||
emailContent: emailContentEscaped,
|
emailContent: emailContentEscaped,
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ class EmailLocalStorageDataSourceImpl extends EmailDataSource {
|
|||||||
|
|
||||||
final htmlDocument = _previewEmlFileUtils.generatePreviewEml(
|
final htmlDocument = _previewEmlFileUtils.generatePreviewEml(
|
||||||
appName: appLocalizations.app_name,
|
appName: appLocalizations.app_name,
|
||||||
userName: entireMessageRequest.userName.value,
|
ownEmailAddress: entireMessageRequest.ownEmailAddress,
|
||||||
subjectPrefix: appLocalizations.subject,
|
subjectPrefix: appLocalizations.subject,
|
||||||
subject: email.subject?.escapeLtGtHtmlString() ?? '',
|
subject: email.subject?.escapeLtGtHtmlString() ?? '',
|
||||||
emailContent: emailContentEscaped,
|
emailContent: emailContentEscaped,
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
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<EventActionType> {
|
|
||||||
List<EventActionType> validActionsOfEventMethod(EventMethod? eventMethod) {
|
|
||||||
return where((action) {
|
|
||||||
if (eventMethod != EventMethod.counter) {
|
|
||||||
return action != EventActionType.acceptCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return action == EventActionType.acceptCounter
|
|
||||||
|| action == EventActionType.mailToAttendees;
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,13 +2,12 @@ import 'package:equatable/equatable.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.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/core/id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class PreviewEmailEMLRequest with EquatableMixin {
|
class PreviewEmailEMLRequest with EquatableMixin {
|
||||||
final AccountId accountId;
|
final AccountId accountId;
|
||||||
final UserName userName;
|
final String ownEmailAddress;
|
||||||
final Id blobId;
|
final Id blobId;
|
||||||
final Email email;
|
final Email email;
|
||||||
final Locale locale;
|
final Locale locale;
|
||||||
@@ -18,7 +17,7 @@ class PreviewEmailEMLRequest with EquatableMixin {
|
|||||||
|
|
||||||
PreviewEmailEMLRequest({
|
PreviewEmailEMLRequest({
|
||||||
required this.accountId,
|
required this.accountId,
|
||||||
required this.userName,
|
required this.ownEmailAddress,
|
||||||
required this.blobId,
|
required this.blobId,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.locale,
|
required this.locale,
|
||||||
@@ -29,12 +28,14 @@ class PreviewEmailEMLRequest with EquatableMixin {
|
|||||||
|
|
||||||
String get keyStored => blobId.value;
|
String get keyStored => blobId.value;
|
||||||
|
|
||||||
String get title => '${email.subject?.trim().isNotEmpty == true ? email.subject : appLocalizations.app_name} - ${userName.value}';
|
String get title => '${email.subject?.trim().isNotEmpty == true
|
||||||
|
? email.subject
|
||||||
|
: appLocalizations.app_name} - $ownEmailAddress';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
accountId,
|
accountId,
|
||||||
userName,
|
ownEmailAddress,
|
||||||
blobId,
|
blobId,
|
||||||
email,
|
email,
|
||||||
locale,
|
locale,
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
|
||||||
import 'package:model/email/attachment.dart';
|
import 'package:model/email/attachment.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class ViewEntireMessageRequest with EquatableMixin {
|
class ViewEntireMessageRequest with EquatableMixin {
|
||||||
final UserName userName;
|
final String ownEmailAddress;
|
||||||
final PresentationEmail presentationEmail;
|
final PresentationEmail presentationEmail;
|
||||||
final List<Attachment> attachments;
|
final List<Attachment> attachments;
|
||||||
final String emailContent;
|
final String emailContent;
|
||||||
@@ -14,7 +13,7 @@ class ViewEntireMessageRequest with EquatableMixin {
|
|||||||
final AppLocalizations appLocalizations;
|
final AppLocalizations appLocalizations;
|
||||||
|
|
||||||
ViewEntireMessageRequest({
|
ViewEntireMessageRequest({
|
||||||
required this.userName,
|
required this.ownEmailAddress,
|
||||||
required this.presentationEmail,
|
required this.presentationEmail,
|
||||||
required this.attachments,
|
required this.attachments,
|
||||||
required this.emailContent,
|
required this.emailContent,
|
||||||
@@ -24,7 +23,7 @@ class ViewEntireMessageRequest with EquatableMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
userName,
|
ownEmailAddress,
|
||||||
presentationEmail,
|
presentationEmail,
|
||||||
attachments,
|
attachments,
|
||||||
emailContent,
|
emailContent,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
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/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/identities/identity.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.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/calendar_event.dart';
|
||||||
@@ -45,7 +44,6 @@ import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
|||||||
import 'package:tmail_ui_user/features/base/state/button_state.dart';
|
import 'package:tmail_ui_user/features/base/state/button_state.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
|
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_exceptions.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
|
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
|
||||||
@@ -222,7 +220,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
|
|
||||||
Session? get session => mailboxDashBoardController.sessionCurrent;
|
Session? get session => mailboxDashBoardController.sessionCurrent;
|
||||||
|
|
||||||
UserName? get userName => session?.username;
|
String get ownEmailAddress => mailboxDashBoardController.getOwnEmailAddress();
|
||||||
|
|
||||||
SingleEmailController(
|
SingleEmailController(
|
||||||
this._getEmailContentInteractor,
|
this._getEmailContentInteractor,
|
||||||
@@ -776,6 +774,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
emailUnsubscribe.value = null;
|
emailUnsubscribe.value = null;
|
||||||
_identitySelected = null;
|
_identitySelected = null;
|
||||||
isEmailContentClipped.value = false;
|
isEmailContentClipped.value = false;
|
||||||
|
attendanceStatus.value = null;
|
||||||
if (isEmailClosing) {
|
if (isEmailClosing) {
|
||||||
emailLoadedViewState.value = Right(UIState.idle);
|
emailLoadedViewState.value = Right(UIState.idle);
|
||||||
viewState.value = Right(UIState.idle);
|
viewState.value = Right(UIState.idle);
|
||||||
@@ -2195,26 +2194,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _calendarEventFailure(Failure failure) {
|
void _calendarEventFailure(CalendarEventReplyFailure failure) {
|
||||||
if (currentOverlayContext == null || currentContext == null) {
|
toastManager.showMessageFailure(failure);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure is CalendarEventReplyFailure && failure.exception is CannotReplyCalendarEventException) {
|
|
||||||
final replyEventException = failure.exception as CannotReplyCalendarEventException;
|
|
||||||
|
|
||||||
if (replyEventException.mapErrors?.isNotEmpty == true) {
|
|
||||||
appToast.showToastErrorMessage(
|
|
||||||
currentOverlayContext!,
|
|
||||||
replyEventException.mapErrors!.values.first.description
|
|
||||||
?? AppLocalizations.of(currentContext!).eventReplyWasSentUnsuccessfully);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appToast.showToastErrorMessage(
|
|
||||||
currentOverlayContext!,
|
|
||||||
AppLocalizations.of(currentContext!).eventReplyWasSentUnsuccessfully);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _downloadMessageAsEML(PresentationEmail presentationEmail) {
|
void _downloadMessageAsEML(PresentationEmail presentationEmail) {
|
||||||
@@ -2408,7 +2389,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
consumeState(_previewEmailFromEmlFileInteractor.execute(
|
consumeState(_previewEmailFromEmlFileInteractor.execute(
|
||||||
PreviewEmailEMLRequest(
|
PreviewEmailEMLRequest(
|
||||||
accountId: accountId!,
|
accountId: accountId!,
|
||||||
userName: userName!,
|
ownEmailAddress: ownEmailAddress,
|
||||||
blobId: success.blobId,
|
blobId: success.blobId,
|
||||||
email: success.email,
|
email: success.email,
|
||||||
locale: Localizations.localeOf(currentContext!),
|
locale: Localizations.localeOf(currentContext!),
|
||||||
@@ -2589,7 +2570,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final viewEntireMessageRequest = ViewEntireMessageRequest(
|
final viewEntireMessageRequest = ViewEntireMessageRequest(
|
||||||
userName: userName ?? UserName(''),
|
ownEmailAddress: ownEmailAddress,
|
||||||
presentationEmail: presentationEmail,
|
presentationEmail: presentationEmail,
|
||||||
attachments: List.from(attachments),
|
attachments: List.from(attachments),
|
||||||
emailContent: emailContent,
|
emailContent: emailContent,
|
||||||
|
|||||||
@@ -367,13 +367,22 @@ class EmailView extends GetWidget<SingleEmailController> {
|
|||||||
onOpenComposerAction: controller.openNewComposerAction,
|
onOpenComposerAction: controller.openNewComposerAction,
|
||||||
onOpenNewTabAction: controller.openNewTabAction,
|
onOpenNewTabAction: controller.openNewTabAction,
|
||||||
onCalendarEventReplyActionClick: (eventActionType) =>
|
onCalendarEventReplyActionClick: (eventActionType) =>
|
||||||
controller.onCalendarEventReplyAction(eventActionType, presentationEmail.id!),
|
controller.onCalendarEventReplyAction(
|
||||||
|
eventActionType,
|
||||||
|
presentationEmail.id!,
|
||||||
|
),
|
||||||
calendarEventReplying: controller.calendarEventProcessing,
|
calendarEventReplying: controller.calendarEventProcessing,
|
||||||
attendanceStatus: controller.attendanceStatus.value,
|
attendanceStatus: controller.attendanceStatus.value,
|
||||||
|
ownEmailAddress: controller
|
||||||
|
.mailboxDashBoardController
|
||||||
|
.getOwnEmailAddress(),
|
||||||
onMailtoAttendeesAction: controller.handleMailToAttendees,
|
onMailtoAttendeesAction: controller.handleMailToAttendees,
|
||||||
openEmailAddressDetailAction: controller.openEmailAddressDialog,
|
openEmailAddressDetailAction: controller.openEmailAddressDialog,
|
||||||
isFree: controller.isCalendarEventFree,
|
isFree: controller.isCalendarEventFree,
|
||||||
listEmailAddressSender: emailAddressSender ?? [],
|
listEmailAddressSender: emailAddressSender ?? [],
|
||||||
|
isPortraitMobile: controller
|
||||||
|
.responsiveUtils
|
||||||
|
.isPortraitMobile(context),
|
||||||
)),
|
)),
|
||||||
if (_validateDisplayEventActionBanner(
|
if (_validateDisplayEventActionBanner(
|
||||||
context: context,
|
context: context,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_sequence
|
|||||||
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/properties/recurrence_rule/recurrence_rule.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/recurrence_rule/recurrence_rule.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||||
|
|
||||||
@@ -382,16 +383,50 @@ extension CalendarEventExtension on CalendarEvent {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isDisplayedEventReplyAction => method != null
|
bool isDisplayedEventReplyAction(String ownerEmailAddress) => method != null
|
||||||
&& _methodIsRepliable
|
&& _methodIsRepliable
|
||||||
&& organizer != null
|
&& organizer != null
|
||||||
&& participants?.isNotEmpty == true;
|
&& participants?.isNotEmpty == true
|
||||||
|
&& !validateUserIsNotListedInParticipants(ownerEmailAddress);
|
||||||
|
|
||||||
bool get _methodIsRepliable =>
|
bool get _methodIsRepliable =>
|
||||||
method == EventMethod.request ||
|
method == EventMethod.request ||
|
||||||
method == EventMethod.add ||
|
method == EventMethod.add ||
|
||||||
method == EventMethod.counter;
|
method == EventMethod.counter;
|
||||||
|
|
||||||
|
bool validateUserIsNotListedInParticipants(String ownEmailAddress) {
|
||||||
|
final participant = participants?.firstWhereOrNull((participant) =>
|
||||||
|
participant.mailto?.mailAddress.value == ownEmailAddress);
|
||||||
|
return participant == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get isDisplayedMailToAttendees =>
|
||||||
|
organizer != null || participants?.isNotEmpty == true;
|
||||||
|
|
||||||
|
List<EventActionType> getEventActionTypesIsDisplayed(
|
||||||
|
String ownerEmailAddress,
|
||||||
|
) {
|
||||||
|
if (isDisplayedEventReplyAction(ownerEmailAddress)) {
|
||||||
|
return [
|
||||||
|
if (method == EventMethod.counter)
|
||||||
|
EventActionType.acceptCounter
|
||||||
|
else
|
||||||
|
...[
|
||||||
|
EventActionType.yes,
|
||||||
|
EventActionType.maybe,
|
||||||
|
EventActionType.no,
|
||||||
|
],
|
||||||
|
EventActionType.mailToAttendees,
|
||||||
|
];
|
||||||
|
} else if (isDisplayedMailToAttendees) {
|
||||||
|
return [
|
||||||
|
EventActionType.mailToAttendees,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CalendarEvent copyWith({
|
CalendarEvent copyWith({
|
||||||
EventId? eventId,
|
EventId? eventId,
|
||||||
String? title,
|
String? title,
|
||||||
|
|||||||
@@ -20,5 +20,4 @@ class CalendarEventActionButtonWidgetStyles {
|
|||||||
static const EdgeInsetsGeometry buttonPadding = EdgeInsetsDirectional.symmetric(vertical: 8, horizontal: 12);
|
static const EdgeInsetsGeometry buttonPadding = EdgeInsetsDirectional.symmetric(vertical: 8, horizontal: 12);
|
||||||
static const EdgeInsetsGeometry paddingMobile = EdgeInsetsDirectional.only(top: 16);
|
static const EdgeInsetsGeometry paddingMobile = EdgeInsetsDirectional.only(top: 16);
|
||||||
static const EdgeInsetsGeometry paddingWeb = EdgeInsetsDirectional.only(start: 100, end: 16, top: 16);
|
static const EdgeInsetsGeometry paddingWeb = EdgeInsetsDirectional.only(start: 100, end: 16, top: 16);
|
||||||
static const EdgeInsetsGeometry margin = EdgeInsetsDirectional.only(top: 16);
|
|
||||||
}
|
}
|
||||||
+2
-1
@@ -3,7 +3,6 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class CalendarEventInformationWidgetStyles {
|
class CalendarEventInformationWidgetStyles {
|
||||||
static const double borderRadius = 16;
|
|
||||||
static const double contentPadding = 16;
|
static const double contentPadding = 16;
|
||||||
static const double verticalMargin = 12;
|
static const double verticalMargin = 12;
|
||||||
static const double horizontalMargin = 16;
|
static const double horizontalMargin = 16;
|
||||||
@@ -15,4 +14,6 @@ class CalendarEventInformationWidgetStyles {
|
|||||||
static const double space = 8;
|
static const double space = 8;
|
||||||
static const Color titleColor = Colors.black;
|
static const Color titleColor = Colors.black;
|
||||||
static const Color invitationMessageColor = Colors.black;
|
static const Color invitationMessageColor = Colors.black;
|
||||||
|
|
||||||
|
static const radius = Radius.circular(16);
|
||||||
}
|
}
|
||||||
+8
-16
@@ -1,10 +1,6 @@
|
|||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
|
||||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||||
import 'package:flutter/material.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/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/domain/model/event_action.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_action_button_widget_styles.dart';
|
import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_action_button_widget_styles.dart';
|
||||||
|
|
||||||
@@ -12,22 +8,20 @@ typedef OnCalendarEventReplyActionClick = void Function(EventActionType eventAct
|
|||||||
|
|
||||||
class CalendarEventActionButtonWidget extends StatelessWidget {
|
class CalendarEventActionButtonWidget extends StatelessWidget {
|
||||||
|
|
||||||
final EdgeInsetsGeometry? margin;
|
final List<EventActionType> eventActions;
|
||||||
final OnCalendarEventReplyActionClick onCalendarEventReplyActionClick;
|
final OnCalendarEventReplyActionClick onCalendarEventReplyActionClick;
|
||||||
final bool calendarEventReplying;
|
final bool calendarEventReplying;
|
||||||
final EventMethod? eventMethod;
|
|
||||||
final AttendanceStatus? attendanceStatus;
|
final AttendanceStatus? attendanceStatus;
|
||||||
|
final bool isPortraitMobile;
|
||||||
final VoidCallback? onMailToAttendeesAction;
|
final VoidCallback? onMailToAttendeesAction;
|
||||||
|
|
||||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
const CalendarEventActionButtonWidget({
|
||||||
|
|
||||||
CalendarEventActionButtonWidget({
|
|
||||||
super.key,
|
super.key,
|
||||||
|
required this.eventActions,
|
||||||
required this.onCalendarEventReplyActionClick,
|
required this.onCalendarEventReplyActionClick,
|
||||||
required this.calendarEventReplying,
|
required this.calendarEventReplying,
|
||||||
required this.eventMethod,
|
|
||||||
this.margin,
|
|
||||||
this.attendanceStatus,
|
this.attendanceStatus,
|
||||||
|
this.isPortraitMobile = false,
|
||||||
this.onMailToAttendeesAction,
|
this.onMailToAttendeesAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,15 +29,13 @@ class CalendarEventActionButtonWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
margin: margin ?? CalendarEventActionButtonWidgetStyles.margin,
|
padding: isPortraitMobile
|
||||||
padding: _responsiveUtils.isPortraitMobile(context)
|
|
||||||
? CalendarEventActionButtonWidgetStyles.paddingMobile
|
? CalendarEventActionButtonWidgetStyles.paddingMobile
|
||||||
: CalendarEventActionButtonWidgetStyles.paddingWeb,
|
: CalendarEventActionButtonWidgetStyles.paddingWeb,
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: CalendarEventActionButtonWidgetStyles.space,
|
spacing: CalendarEventActionButtonWidgetStyles.space,
|
||||||
runSpacing: CalendarEventActionButtonWidgetStyles.space,
|
runSpacing: CalendarEventActionButtonWidgetStyles.space,
|
||||||
children: EventActionType.values
|
children: eventActions
|
||||||
.validActionsOfEventMethod(eventMethod)
|
|
||||||
.map((action) => AbsorbPointer(
|
.map((action) => AbsorbPointer(
|
||||||
absorbing: _getCallbackFunction(action) == null,
|
absorbing: _getCallbackFunction(action) == null,
|
||||||
child: TMailButtonWidget(
|
child: TMailButtonWidget(
|
||||||
@@ -58,7 +50,7 @@ class CalendarEventActionButtonWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
minWidth: CalendarEventActionButtonWidgetStyles.minWidth,
|
minWidth: CalendarEventActionButtonWidgetStyles.minWidth,
|
||||||
width: _responsiveUtils.isPortraitMobile(context) ? double.infinity : null,
|
width: isPortraitMobile ? double.infinity : null,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
width: CalendarEventActionButtonWidgetStyles.borderWidth,
|
width: CalendarEventActionButtonWidgetStyles.borderWidth,
|
||||||
color: _getButtonBorderColor(action)
|
color: _getButtonBorderColor(action)
|
||||||
|
|||||||
+144
-167
@@ -1,7 +1,5 @@
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/attendance/calendar_event_attendance.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/extensions/calendar_event_extension.dart';
|
||||||
@@ -16,6 +14,7 @@ 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_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/calendar_event/event_title_widget.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_sender_builder.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';
|
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||||
|
|
||||||
typedef OnOpenNewTabAction = void Function(String link);
|
typedef OnOpenNewTabAction = void Function(String link);
|
||||||
@@ -33,25 +32,159 @@ class CalendarEventInformationWidget extends StatelessWidget {
|
|||||||
final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction;
|
final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction;
|
||||||
final bool isFree;
|
final bool isFree;
|
||||||
final List<String> listEmailAddressSender;
|
final List<String> listEmailAddressSender;
|
||||||
|
final String ownEmailAddress;
|
||||||
|
final bool isPortraitMobile;
|
||||||
|
|
||||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
const CalendarEventInformationWidget({
|
||||||
|
|
||||||
CalendarEventInformationWidget({
|
|
||||||
super.key,
|
super.key,
|
||||||
required this.calendarEvent,
|
required this.calendarEvent,
|
||||||
required this.onCalendarEventReplyActionClick,
|
required this.onCalendarEventReplyActionClick,
|
||||||
required this.calendarEventReplying,
|
required this.calendarEventReplying,
|
||||||
required this.isFree,
|
required this.isFree,
|
||||||
|
required this.ownEmailAddress,
|
||||||
this.onOpenNewTabAction,
|
this.onOpenNewTabAction,
|
||||||
this.onOpenComposerAction,
|
this.onOpenComposerAction,
|
||||||
this.attendanceStatus,
|
this.attendanceStatus,
|
||||||
this.onMailtoAttendeesAction,
|
this.onMailtoAttendeesAction,
|
||||||
this.openEmailAddressDetailAction,
|
this.openEmailAddressDetailAction,
|
||||||
this.listEmailAddressSender = const [],
|
this.listEmailAddressSender = const [],
|
||||||
|
this.isPortraitMobile = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final bodyBorderRadius = isPortraitMobile
|
||||||
|
? const BorderRadiusDirectional.only(
|
||||||
|
bottomStart: CalendarEventInformationWidgetStyles.radius,
|
||||||
|
bottomEnd: CalendarEventInformationWidgetStyles.radius,
|
||||||
|
)
|
||||||
|
: const BorderRadiusDirectional.only(
|
||||||
|
topEnd: CalendarEventInformationWidgetStyles.radius,
|
||||||
|
bottomEnd: CalendarEventInformationWidgetStyles.radius,
|
||||||
|
);
|
||||||
|
|
||||||
|
final eventActionTypes = calendarEvent.getEventActionTypesIsDisplayed(
|
||||||
|
ownEmailAddress,
|
||||||
|
);
|
||||||
|
|
||||||
|
final bodyWidget = Container(
|
||||||
|
decoration: ShapeDecoration(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: bodyBorderRadius),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
padding: const EdgeInsets.all(
|
||||||
|
CalendarEventInformationWidgetStyles.calendarInformationMargin,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (calendarEvent.organizerName.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: CalendarEventInformationWidgetStyles.space,
|
||||||
|
),
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: CalendarEventInformationWidgetStyles
|
||||||
|
.invitationMessageTextSize,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: CalendarEventInformationWidgetStyles
|
||||||
|
.invitationMessageColor,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: calendarEvent.organizerName,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CalendarEventInformationWidgetStyles
|
||||||
|
.invitationMessageColor,
|
||||||
|
fontSize: CalendarEventInformationWidgetStyles
|
||||||
|
.invitationMessageTextSize,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: calendarEvent.getTitleEventAction(
|
||||||
|
context,
|
||||||
|
listEmailAddressSender,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (calendarEvent.title?.isNotEmpty == true)
|
||||||
|
EventTitleWidget(title: calendarEvent.title!),
|
||||||
|
_buildEventTimeInformationWidget(),
|
||||||
|
if (calendarEvent.location?.isNotEmpty == true)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: CalendarEventInformationWidgetStyles.fieldTopPadding,
|
||||||
|
),
|
||||||
|
child: EventLocationInformationWidget(
|
||||||
|
locationEvent: calendarEvent.location!,
|
||||||
|
onOpenComposerAction: onOpenComposerAction,
|
||||||
|
onOpenNewTabAction: onOpenNewTabAction,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (calendarEvent.videoConferences.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: CalendarEventDetailWidgetStyles.fieldTopPadding,
|
||||||
|
),
|
||||||
|
child: EventLinkDetailWidget(
|
||||||
|
listHyperLink: calendarEvent.videoConferences,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (calendarEvent.participants?.isNotEmpty == true ||
|
||||||
|
calendarEvent.organizer != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: CalendarEventDetailWidgetStyles.fieldTopPadding,
|
||||||
|
),
|
||||||
|
child: EventAttendeeDetailWidget(
|
||||||
|
attendees: calendarEvent.participants ?? [],
|
||||||
|
organizer: calendarEvent.organizer,
|
||||||
|
openEmailAddressDetailAction: openEmailAddressDetailAction,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (calendarEvent.validateUserIsNotListedInParticipants(
|
||||||
|
ownEmailAddress,
|
||||||
|
))
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsetsDirectional.only(
|
||||||
|
top: CalendarEventInformationWidgetStyles.fieldTopPadding,
|
||||||
|
start: isPortraitMobile ? 0 : 100,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations
|
||||||
|
.of(context)
|
||||||
|
.youAreNotInvitedToThisEventPleaseContactTheOrganiser,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: CalendarEventInformationWidgetStyles
|
||||||
|
.invitationMessageTextSize,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColor.colorMaybeEventActionText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (eventActionTypes.isNotEmpty)
|
||||||
|
CalendarEventActionButtonWidget(
|
||||||
|
eventActions: eventActionTypes,
|
||||||
|
onCalendarEventReplyActionClick: onCalendarEventReplyActionClick,
|
||||||
|
calendarEventReplying: calendarEventReplying,
|
||||||
|
attendanceStatus: attendanceStatus,
|
||||||
|
isPortraitMobile: isPortraitMobile,
|
||||||
|
onMailToAttendeesAction: () => onMailtoAttendeesAction?.call(
|
||||||
|
calendarEvent.organizer,
|
||||||
|
calendarEvent.participants,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
decoration: const ShapeDecoration(
|
decoration: const ShapeDecoration(
|
||||||
@@ -61,99 +194,22 @@ class CalendarEventInformationWidget extends StatelessWidget {
|
|||||||
width: 0.5,
|
width: 0.5,
|
||||||
color: AppColor.colorCalendarEventInformationStroke,
|
color: AppColor.colorCalendarEventInformationStroke,
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(CalendarEventInformationWidgetStyles.borderRadius)),
|
borderRadius: BorderRadius.all(
|
||||||
|
CalendarEventInformationWidgetStyles.radius,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
margin: const EdgeInsetsDirectional.symmetric(
|
margin: const EdgeInsetsDirectional.symmetric(
|
||||||
vertical: CalendarEventInformationWidgetStyles.verticalMargin,
|
vertical: CalendarEventInformationWidgetStyles.verticalMargin,
|
||||||
horizontal: CalendarEventInformationWidgetStyles.horizontalMargin),
|
horizontal: CalendarEventInformationWidgetStyles.horizontalMargin),
|
||||||
child: _responsiveUtils.isPortraitMobile(context)
|
child: isPortraitMobile
|
||||||
? Column(
|
? Column(
|
||||||
children: [
|
children: [
|
||||||
CalendarDateIconWidget(
|
CalendarDateIconWidget(
|
||||||
calendarEvent: calendarEvent,
|
calendarEvent: calendarEvent,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
),
|
),
|
||||||
Container(
|
bodyWidget,
|
||||||
decoration: const ShapeDecoration(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
bottomLeft: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius),
|
|
||||||
bottomRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color: Colors.white
|
|
||||||
),
|
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
padding: const EdgeInsets.all(CalendarEventInformationWidgetStyles.calendarInformationMargin),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (calendarEvent.organizerName.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: CalendarEventInformationWidgetStyles.space),
|
|
||||||
child: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: CalendarEventInformationWidgetStyles.invitationMessageColor
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: calendarEvent.organizerName,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
|
|
||||||
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
|
|
||||||
fontWeight: FontWeight.w700
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(text: calendarEvent.getTitleEventAction(context, listEmailAddressSender))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.title?.isNotEmpty == true)
|
|
||||||
EventTitleWidget(title: calendarEvent.title!),
|
|
||||||
_buildEventTimeInformationWidget(),
|
|
||||||
if (calendarEvent.location?.isNotEmpty == true)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventLocationInformationWidget(
|
|
||||||
locationEvent: calendarEvent.location!,
|
|
||||||
onOpenComposerAction: onOpenComposerAction,
|
|
||||||
onOpenNewTabAction: onOpenNewTabAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.videoConferences.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventLinkDetailWidget(listHyperLink: calendarEvent.videoConferences),
|
|
||||||
),
|
|
||||||
if (calendarEvent.participants?.isNotEmpty == true || calendarEvent.organizer != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventAttendeeDetailWidget(
|
|
||||||
attendees: calendarEvent.participants ?? [],
|
|
||||||
organizer: calendarEvent.organizer,
|
|
||||||
openEmailAddressDetailAction: openEmailAddressDetailAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.isDisplayedEventReplyAction)
|
|
||||||
CalendarEventActionButtonWidget(
|
|
||||||
margin: EdgeInsetsDirectional.zero,
|
|
||||||
onCalendarEventReplyActionClick: onCalendarEventReplyActionClick,
|
|
||||||
eventMethod: calendarEvent.method,
|
|
||||||
calendarEventReplying: calendarEventReplying,
|
|
||||||
attendanceStatus: attendanceStatus,
|
|
||||||
onMailToAttendeesAction: () => onMailtoAttendeesAction?.call(
|
|
||||||
calendarEvent.organizer,
|
|
||||||
calendarEvent.participants,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: IntrinsicHeight(
|
: IntrinsicHeight(
|
||||||
@@ -161,86 +217,7 @@ class CalendarEventInformationWidget extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
CalendarDateIconWidget(calendarEvent: calendarEvent),
|
CalendarDateIconWidget(calendarEvent: calendarEvent),
|
||||||
Expanded(child: Container(
|
Expanded(child: bodyWidget),
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
decoration: const ShapeDecoration(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius),
|
|
||||||
bottomRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color: Colors.white
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(CalendarEventInformationWidgetStyles.calendarInformationMargin),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (calendarEvent.organizerName.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: CalendarEventInformationWidgetStyles.space),
|
|
||||||
child: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: CalendarEventInformationWidgetStyles.invitationMessageColor
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: calendarEvent.organizerName,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
|
|
||||||
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
|
|
||||||
fontWeight: FontWeight.w700
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(text: calendarEvent.getTitleEventAction(context, listEmailAddressSender))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.title?.isNotEmpty == true)
|
|
||||||
EventTitleWidget(title: calendarEvent.title!),
|
|
||||||
_buildEventTimeInformationWidget(),
|
|
||||||
if (calendarEvent.location?.isNotEmpty == true)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventLocationInformationWidget(
|
|
||||||
locationEvent: calendarEvent.location!,
|
|
||||||
onOpenComposerAction: onOpenComposerAction,
|
|
||||||
onOpenNewTabAction: onOpenNewTabAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.videoConferences.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventLinkDetailWidget(listHyperLink: calendarEvent.videoConferences),
|
|
||||||
),
|
|
||||||
if (calendarEvent.participants?.isNotEmpty == true || calendarEvent.organizer != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
|
|
||||||
child: EventAttendeeDetailWidget(
|
|
||||||
attendees: calendarEvent.participants ?? [],
|
|
||||||
organizer: calendarEvent.organizer,
|
|
||||||
openEmailAddressDetailAction: openEmailAddressDetailAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (calendarEvent.isDisplayedEventReplyAction)
|
|
||||||
CalendarEventActionButtonWidget(
|
|
||||||
margin: EdgeInsetsDirectional.zero,
|
|
||||||
onCalendarEventReplyActionClick: onCalendarEventReplyActionClick,
|
|
||||||
eventMethod: calendarEvent.method,
|
|
||||||
calendarEventReplying: calendarEventReplying,
|
|
||||||
attendanceStatus: attendanceStatus,
|
|
||||||
onMailToAttendeesAction: () => onMailtoAttendeesAction?.call(
|
|
||||||
calendarEvent.organizer,
|
|
||||||
calendarEvent.participants,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ class EmailPreviewerController extends ReloadableController {
|
|||||||
consumeState(_previewEmailFromEmlFileInteractor.execute(
|
consumeState(_previewEmailFromEmlFileInteractor.execute(
|
||||||
PreviewEmailEMLRequest(
|
PreviewEmailEMLRequest(
|
||||||
accountId: _accountId!,
|
accountId: _accountId!,
|
||||||
userName: _session!.username,
|
ownEmailAddress: _session!.getOwnEmailAddressOrEmpty(),
|
||||||
blobId: success.blobId,
|
blobId: success.blobId,
|
||||||
email: success.email,
|
email: success.email,
|
||||||
locale: Localizations.localeOf(currentContext!),
|
locale: Localizations.localeOf(currentContext!),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2025-06-02T18:48:11.159281",
|
"@@last_modified": "2025-06-19T11:06:29.579174",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -4551,5 +4551,11 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"youAreNotInvitedToThisEventPleaseContactTheOrganiser": "You are not invited to this event. Please contact the organiser.",
|
||||||
|
"@youAreNotInvitedToThisEventPleaseContactTheOrganiser": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4794,4 +4794,11 @@ class AppLocalizations {
|
|||||||
name: 'createFilterRuleFailed',
|
name: 'createFilterRuleFailed',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get youAreNotInvitedToThisEventPleaseContactTheOrganiser {
|
||||||
|
return Intl.message(
|
||||||
|
'You are not invited to this event. Please contact the organiser.',
|
||||||
|
name: 'youAreNotInvitedToThisEventPleaseContactTheOrganiser',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
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,
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -4,11 +4,22 @@ import 'package:date_format/date_format.dart' as date_format;
|
|||||||
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.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/attendee/calendar_attendee.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/attendee/calendar_attendee_mail_to.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart';
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/calendar/properties/mail_address.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart';
|
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
const ownerEmail = 'user@example.com';
|
||||||
|
final matchingParticipant = CalendarAttendee(
|
||||||
|
mailto: CalendarAttendeeMailTo(MailAddress(ownerEmail)),
|
||||||
|
);
|
||||||
|
final nonMatchingParticipant = CalendarAttendee(
|
||||||
|
mailto: CalendarAttendeeMailTo(MailAddress('someone@else.com')),
|
||||||
|
);
|
||||||
|
|
||||||
group('calendar_event_extension::formatDateTime::test', () {
|
group('calendar_event_extension::formatDateTime::test', () {
|
||||||
final dateTime = DateTime(2021, 10, 10, 10, 30, 00, 00, 00);
|
final dateTime = DateTime(2021, 10, 10, 10, 30, 00, 00, 00);
|
||||||
|
|
||||||
@@ -77,121 +88,145 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('calendar_event_extension::isDisplayedEventReplyAction::test:', () {
|
group('isDisplayedEventReplyAction', () {
|
||||||
CalendarEvent calendarEventFromEventMethod(EventMethod eventMethod) {
|
test('returns true when all conditions are met and user is in participants', () {
|
||||||
return CalendarEvent(
|
final event = CalendarEvent(
|
||||||
method: eventMethod,
|
method: EventMethod.request,
|
||||||
organizer: CalendarOrganizer(),
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
participants: [CalendarAttendee()]
|
participants: [matchingParticipant],
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
group('should return true', () {
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isTrue);
|
||||||
test(
|
|
||||||
'when event method is request',
|
|
||||||
() {
|
|
||||||
// arrange
|
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.request);
|
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
|
||||||
'when event method is add',
|
|
||||||
() {
|
|
||||||
// arrange
|
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.add);
|
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
|
||||||
'when event method is counter',
|
|
||||||
() {
|
|
||||||
// arrange
|
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.counter);
|
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('should return false', () {
|
test('returns false when method is null', () {
|
||||||
test(
|
final event = CalendarEvent(
|
||||||
'when event method is publish',
|
method: null,
|
||||||
() {
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
// arrange
|
participants: [matchingParticipant],
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.publish);
|
);
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
'when event method is reply',
|
});
|
||||||
() {
|
|
||||||
// arrange
|
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.reply);
|
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
test('returns false when method is not repliable', () {
|
||||||
'when event method is cancel',
|
final event = CalendarEvent(
|
||||||
() {
|
method: EventMethod.cancel,
|
||||||
// arrange
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.cancel);
|
participants: [matchingParticipant],
|
||||||
|
);
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
'when event method is refresh',
|
});
|
||||||
() {
|
|
||||||
// arrange
|
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.refresh);
|
|
||||||
|
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
|
||||||
|
|
||||||
// assert
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
test('returns false when organizer is null', () {
|
||||||
'when event method is declineCounter',
|
final event = CalendarEvent(
|
||||||
() {
|
method: EventMethod.request,
|
||||||
// arrange
|
organizer: null,
|
||||||
final calendarEvent = calendarEventFromEventMethod(EventMethod.declineCounter);
|
participants: [matchingParticipant],
|
||||||
|
);
|
||||||
// act
|
|
||||||
final result = calendarEvent.isDisplayedEventReplyAction;
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
|
});
|
||||||
// assert
|
|
||||||
expect(result, false);
|
test('returns false when participants is empty', () {
|
||||||
});
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns false when participants is null', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns false when user is NOT listed in participants', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [nonMatchingParticipant],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(event.isDisplayedEventReplyAction(ownerEmail), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('calendar_event_extension::getEventActionTypesIsDisplayed:', () {
|
||||||
|
test('Should returns yes/maybe/no + mailToAttendees when method is request and user is in participants', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [matchingParticipant],
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = event.getEventActionTypesIsDisplayed(ownerEmail);
|
||||||
|
|
||||||
|
expect(actions, [
|
||||||
|
EventActionType.yes,
|
||||||
|
EventActionType.maybe,
|
||||||
|
EventActionType.no,
|
||||||
|
EventActionType.mailToAttendees,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns acceptCounter + mailToAttendees when method is counter and user is in participants', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.counter,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [matchingParticipant],
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = event.getEventActionTypesIsDisplayed(ownerEmail);
|
||||||
|
|
||||||
|
expect(actions, [
|
||||||
|
EventActionType.acceptCounter,
|
||||||
|
EventActionType.mailToAttendees,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns only mailToAttendees when method is not repliable but organizer is present', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.cancel,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [matchingParticipant],
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = event.getEventActionTypesIsDisplayed(ownerEmail);
|
||||||
|
|
||||||
|
expect(actions, [EventActionType.mailToAttendees]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns only mailToAttendees when user is NOT in participants but organizer is present', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: CalendarOrganizer(mailto: MailAddress(ownerEmail)),
|
||||||
|
participants: [nonMatchingParticipant],
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = event.getEventActionTypesIsDisplayed(ownerEmail);
|
||||||
|
|
||||||
|
expect(actions, [EventActionType.mailToAttendees]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns empty list when no organizer and no participants', () {
|
||||||
|
final event = CalendarEvent(
|
||||||
|
method: EventMethod.request,
|
||||||
|
organizer: null,
|
||||||
|
participants: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = event.getEventActionTypesIsDisplayed(ownerEmail);
|
||||||
|
|
||||||
|
expect(actions, []);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user