diff --git a/assets/images/ic_format_quote.svg b/assets/images/ic_format_quote.svg
new file mode 100644
index 0000000000..6806d928a4
--- /dev/null
+++ b/assets/images/ic_format_quote.svg
@@ -0,0 +1,5 @@
+
diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart
index 2d26a5607e..34b2157184 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -195,6 +195,8 @@ extension AppColor on Color {
static const colorCalendarEventInformationStroke = Color(0x1F000000);
static const colorShadowCalendarDateIcon = Color(0x26000000);
static const colorOrganizerMailto = Color(0xFFB3B3B3);
+ static const colorMailto = Color(0xFFB3B3B3);
+ static const colorEventDescriptionBackground = Color(0x05000000);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index d5a010dd7c..cea00d9f59 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -198,6 +198,7 @@ class ImagePaths {
String get icEventInvited => _getImagePath('ic_event_invited.svg');
String get icEventUpdated => _getImagePath('ic_event_updated.svg');
String get icEventCanceled => _getImagePath('ic_event_canceled.svg');
+ String get icFormatQuote => _getImagePath('ic_format_quote.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/lib/features/base/styles/cupertino_loading_widget_styles.dart b/lib/features/base/styles/cupertino_loading_widget_styles.dart
new file mode 100644
index 0000000000..3000ad3694
--- /dev/null
+++ b/lib/features/base/styles/cupertino_loading_widget_styles.dart
@@ -0,0 +1,7 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class CupertinoLoadingWidgetStyles {
+ static const Color progressColor = AppColor.colorLoading;
+ static const double size = 24;
+}
\ No newline at end of file
diff --git a/lib/features/base/styles/hyper_link_widget_styles.dart b/lib/features/base/styles/hyper_link_widget_styles.dart
new file mode 100644
index 0000000000..c8668cb476
--- /dev/null
+++ b/lib/features/base/styles/hyper_link_widget_styles.dart
@@ -0,0 +1,7 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class HyperLinkWidgetStyles {
+ static const Color textColor = AppColor.primaryColor;
+ static const double textSize = 16;
+}
\ No newline at end of file
diff --git a/lib/features/base/widget/cupertino_loading_widget.dart b/lib/features/base/widget/cupertino_loading_widget.dart
new file mode 100644
index 0000000000..0c8d3e72a9
--- /dev/null
+++ b/lib/features/base/widget/cupertino_loading_widget.dart
@@ -0,0 +1,17 @@
+import 'package:flutter/cupertino.dart';
+import 'package:tmail_ui_user/features/base/styles/cupertino_loading_widget_styles.dart';
+
+class CupertinoLoadingWidget extends StatelessWidget {
+ const CupertinoLoadingWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return const Center(
+ child: SizedBox(
+ width: CupertinoLoadingWidgetStyles.size,
+ height: CupertinoLoadingWidgetStyles.size,
+ child: CupertinoActivityIndicator(color: CupertinoLoadingWidgetStyles.progressColor)
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/base/widget/hyper_link_widget.dart b/lib/features/base/widget/hyper_link_widget.dart
new file mode 100644
index 0000000000..f0249179ea
--- /dev/null
+++ b/lib/features/base/widget/hyper_link_widget.dart
@@ -0,0 +1,33 @@
+import 'package:flutter/gestures.dart';
+import 'package:flutter/widgets.dart';
+import 'package:tmail_ui_user/features/base/styles/hyper_link_widget_styles.dart';
+import 'package:url_launcher/url_launcher_string.dart';
+
+class HyperLinkWidget extends StatelessWidget {
+
+ final String urlString;
+
+ const HyperLinkWidget({Key? key, required this.urlString}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return RichText(
+ text: TextSpan(
+ text: urlString,
+ style: const TextStyle(
+ color: HyperLinkWidgetStyles.textColor,
+ fontSize: HyperLinkWidgetStyles.textSize,
+ decoration: TextDecoration.underline
+ ),
+ recognizer: TapGestureRecognizer()..onTap = () async {
+ if (await canLaunchUrlString(urlString)) {
+ launchUrlString(
+ urlString,
+ mode: LaunchMode.externalApplication
+ );
+ }
+ }
+ )
+ );
+ }
+}
diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart
index 8d75bf248e..8ad0ce6041 100644
--- a/lib/features/email/presentation/controller/single_email_controller.dart
+++ b/lib/features/email/presentation/controller/single_email_controller.dart
@@ -1279,6 +1279,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
void _handleParseCalendarEventSuccess(ParseCalendarEventSuccess success) {
if (success.calendarEventList.isNotEmpty) {
calendarEvent.value = success.calendarEventList.first;
+ _enableScrollPageView();
}
}
+
+ void _enableScrollPageView() {
+ emailSupervisorController.scrollPhysicsPageView.value = null;
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart
index f47912de2e..e3594bf0f8 100644
--- a/lib/features/email/presentation/email_view.dart
+++ b/lib/features/email/presentation/email_view.dart
@@ -22,15 +22,16 @@ import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/widget/custom_scroll_behavior.dart';
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
-import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/styles/email_view_styles.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/app_bar_mail_widget_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_action_banner_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_loading_bar_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/information_sender_and_receiver_builder.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
@@ -228,7 +229,7 @@ class EmailView extends GetWidget with AppLoaderMixin {
}
Widget _buildEmailBody(BuildContext context, PresentationEmail email) {
- if (PlatformInfo.isWeb) {
+ if (PlatformInfo.isWeb && !email.hasCalendarEvent) {
return _buildEmailMessage(context, email);
} else {
return SingleChildScrollView(
@@ -281,59 +282,41 @@ class EmailView extends GetWidget with AppLoaderMixin {
imagePaths: imagePaths,
responsiveUtils: responsiveUtils,
),
- _buildLoadingContentView(),
_buildAttachments(context),
- Obx(() {
- if (controller.calendarEvent.value != null) {
- return CalendarEventInformationWidget(
- calendarEvent: controller.calendarEvent.value!
- );
- } else {
- return const SizedBox.shrink();
- }
- }),
- Obx(() {
- if (controller.calendarEvent.value != null) {
- return CalendarEventActionBannerWidget(
- calendarEvent: controller.calendarEvent.value!,
- listFromEmailAddress: controller.currentEmail?.from
- );
- } else {
- return const SizedBox.shrink();
- }
- }),
- if (PlatformInfo.isWeb)
- Expanded(child: Padding(
- padding: const EdgeInsetsDirectional.only(start: 16, bottom: 16),
- child: _buildEmailContent(context, constraints, email)
- ))
+ Obx(() => EmailViewLoadingBarWidget(
+ viewState: controller.viewState.value,
+ selectedEmail: email
+ )),
+ if (email.hasCalendarEvent)
+ Obx(() {
+ if (controller.calendarEvent.value != null) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CalendarEventInformationWidget(
+ calendarEvent: controller.calendarEvent.value!
+ ),
+ CalendarEventActionBannerWidget(
+ calendarEvent: controller.calendarEvent.value!,
+ listFromEmailAddress: controller.currentEmail?.from
+ ),
+ CalendarEventDetailWidget(
+ calendarEvent: controller.calendarEvent.value!
+ ),
+ ],
+ );
+ } else {
+ return const SizedBox.shrink();
+ }
+ })
else
- Padding(
- padding: const EdgeInsetsDirectional.symmetric(
- vertical: EmailViewStyles.mobileContentVerticalMargin,
- horizontal: EmailViewStyles.mobileContentHorizontalMargin
- ),
- child: _buildEmailContent(context, constraints, email)
- )
+ _buildEmailContent(context, constraints, email)
],
);
});
}
- Widget _buildLoadingContentView() {
- return Obx(() {
- return controller.viewState.value.fold(
- (failure) => const SizedBox.shrink(),
- (success) {
- if (success is GetEmailContentLoading) {
- return loadingWidget;
- } else {
- return const SizedBox.shrink();
- }
- });
- });
- }
-
Widget _buildAttachments(BuildContext context) {
return Obx(() {
final attachments = controller.attachments.listAttachmentsDisplayedOutSide;
@@ -463,25 +446,36 @@ class EmailView extends GetWidget with AppLoaderMixin {
final allEmailContents = controller.emailContents.value;
if (PlatformInfo.isWeb) {
- return HtmlContentViewerOnWeb(
- widthContent: constraints.maxWidth,
- heightContent: responsiveUtils.getSizeScreenHeight(context),
- contentHtml: allEmailContents ?? "",
- controller: HtmlViewerControllerForWeb(),
- mailtoDelegate: (uri) => controller.openMailToLink(uri),
- direction: AppUtils.getCurrentDirection(context),
+ return Expanded(
+ child: Padding(
+ padding: const EdgeInsetsDirectional.only(start: 16, bottom: 16),
+ child: HtmlContentViewerOnWeb(
+ widthContent: constraints.maxWidth,
+ heightContent: responsiveUtils.getSizeScreenHeight(context),
+ contentHtml: allEmailContents ?? "",
+ controller: HtmlViewerControllerForWeb(),
+ mailtoDelegate: (uri) => controller.openMailToLink(uri),
+ direction: AppUtils.getCurrentDirection(context),
+ ),
+ ),
);
} else {
- return HtmlContentViewer(
- heightContent: responsiveUtils.getSizeScreenHeight(context),
- contentHtml: allEmailContents ?? "",
- mailtoDelegate: (uri) async => controller.openMailToLink(uri),
- onScrollHorizontalEnd: controller.toggleScrollPhysicsPagerView,
- onWebViewLoaded: (isScrollPageViewActivated) {
- log('EmailView::_buildEmailContent(): isScrollPageViewActivated: $isScrollPageViewActivated');
- controller.emailSupervisorController.updateScrollPhysicPageView(isScrollPageViewActivated: isScrollPageViewActivated);
- },
- direction: AppUtils.getCurrentDirection(context),
+ return Padding(
+ padding: const EdgeInsetsDirectional.symmetric(
+ vertical: EmailViewStyles.mobileContentVerticalMargin,
+ horizontal: EmailViewStyles.mobileContentHorizontalMargin
+ ),
+ child: HtmlContentViewer(
+ heightContent: responsiveUtils.getSizeScreenHeight(context),
+ contentHtml: allEmailContents ?? "",
+ mailtoDelegate: (uri) async => controller.openMailToLink(uri),
+ onScrollHorizontalEnd: controller.toggleScrollPhysicsPagerView,
+ onWebViewLoaded: (isScrollPageViewActivated) {
+ log('EmailView::_buildEmailContent(): isScrollPageViewActivated: $isScrollPageViewActivated');
+ controller.emailSupervisorController.updateScrollPhysicPageView(isScrollPageViewActivated: isScrollPageViewActivated);
+ },
+ direction: AppUtils.getCurrentDirection(context),
+ ),
);
}
} else {
diff --git a/lib/features/email/presentation/extensions/calendar_event_extension.dart b/lib/features/email/presentation/extensions/calendar_event_extension.dart
index ad55b6ee58..164c4d6a9a 100644
--- a/lib/features/email/presentation/extensions/calendar_event_extension.dart
+++ b/lib/features/email/presentation/extensions/calendar_event_extension.dart
@@ -269,4 +269,20 @@ extension CalendarEventExtension on CalendarEvent {
return '';
}
}
+
+ List get videoConferences {
+ if (extensionFields != null && extensionFields!.mapFields.isNotEmpty) {
+ final videoConferences = extensionFields!.mapFields['X-OPENPAAS-VIDEOCONFERENCE'];
+ if (videoConferences != null) {
+ final videoConferencesNotEmpty = videoConferences
+ .whereNotNull()
+ .where((link) => link.isNotEmpty)
+ .toList();
+ log('CalendarEventExtension::getListVideoConference: $videoConferencesNotEmpty');
+ return videoConferencesNotEmpty;
+ }
+ }
+
+ return [];
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/attendee_widget_styles.dart b/lib/features/email/presentation/styles/attendee_widget_styles.dart
new file mode 100644
index 0000000000..0a66107c97
--- /dev/null
+++ b/lib/features/email/presentation/styles/attendee_widget_styles.dart
@@ -0,0 +1,10 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class AttendeeWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const Color textColor = Colors.black;
+ static const Color mailtoColor = AppColor.colorMailto;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/calendar_event_detail_widget_styles.dart b/lib/features/email/presentation/styles/calendar_event_detail_widget_styles.dart
new file mode 100644
index 0000000000..80d262e2d9
--- /dev/null
+++ b/lib/features/email/presentation/styles/calendar_event_detail_widget_styles.dart
@@ -0,0 +1,14 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class CalendarEventDetailWidgetStyles {
+ static const double textSize = 24;
+ static const double borderRadius = 16;
+ static const double verticalMargin = 12;
+ static const double horizontalMargin = 16;
+ static const double contentPadding = 16;
+ static const double fieldTopPadding = 16;
+ static const Color borderStrokeColor = AppColor.colorCalendarEventInformationStroke;
+ static const double borderStrokeWidth = 0.5;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/calendar_event_information_widget_styles.dart b/lib/features/email/presentation/styles/calendar_event_information_widget_styles.dart
index 4ef35f7ff1..507a7b643c 100644
--- a/lib/features/email/presentation/styles/calendar_event_information_widget_styles.dart
+++ b/lib/features/email/presentation/styles/calendar_event_information_widget_styles.dart
@@ -11,7 +11,6 @@ class CalendarEventInformationWidgetStyles {
static const Color calendarDateIconBackgroundColor = AppColor.colorCalendarEventInformationBackground;
static const double calendarInformationMargin = 16;
static const double invitationMessageTextSize = 16;
- static const double titleTextSize = 24;
static const double fieldTopPadding = 16;
static const double space = 8;
static const Color titleColor = Colors.black;
diff --git a/lib/features/email/presentation/styles/event_attendee_detail_widget_styles.dart b/lib/features/email/presentation/styles/event_attendee_detail_widget_styles.dart
new file mode 100644
index 0000000000..f510184b20
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_attendee_detail_widget_styles.dart
@@ -0,0 +1,11 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class EventAttendeeDetailWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const double fieldTopPadding = 8;
+ static const Color labelColor = AppColor.colorSubTitleEventActionText;
+ static const Color valueColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/event_description_detail_widget_styles.dart b/lib/features/email/presentation/styles/event_description_detail_widget_styles.dart
new file mode 100644
index 0000000000..82b3591bd9
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_description_detail_widget_styles.dart
@@ -0,0 +1,9 @@
+
+import 'package:flutter/material.dart';
+
+class EventDescriptionDetailWidgetStyles {
+ static const double textSize = 16;
+ static const double borderRadius = 16;
+ static const double contentPadding = 16;
+ static const Color valueColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/event_link_detail_widget_styles.dart b/lib/features/email/presentation/styles/event_link_detail_widget_styles.dart
new file mode 100644
index 0000000000..e91c8ba779
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_link_detail_widget_styles.dart
@@ -0,0 +1,10 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class EventLinkDetailWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const Color labelColor = AppColor.colorSubTitleEventActionText;
+ static const Color valueColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/event_location_detail_widget_styles.dart b/lib/features/email/presentation/styles/event_location_detail_widget_styles.dart
new file mode 100644
index 0000000000..8abe0cdf06
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_location_detail_widget_styles.dart
@@ -0,0 +1,10 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class EventLocationDetailWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const Color labelColor = AppColor.colorSubTitleEventActionText;
+ static const Color valueColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/event_time_detail_widget_styles.dart b/lib/features/email/presentation/styles/event_time_detail_widget_styles.dart
new file mode 100644
index 0000000000..af54d01924
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_time_detail_widget_styles.dart
@@ -0,0 +1,10 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class EventTimeDetailWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const Color labelColor = AppColor.colorSubTitleEventActionText;
+ static const Color valueColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/event_title_widget_styles.dart b/lib/features/email/presentation/styles/event_title_widget_styles.dart
new file mode 100644
index 0000000000..f53abaf925
--- /dev/null
+++ b/lib/features/email/presentation/styles/event_title_widget_styles.dart
@@ -0,0 +1,7 @@
+
+import 'package:flutter/material.dart';
+
+class EventTitleWidgetStyles {
+ static const double textSize = 24;
+ static const Color textColor = Colors.black;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/organizer_widget_styles.dart b/lib/features/email/presentation/styles/organizer_widget_styles.dart
new file mode 100644
index 0000000000..1ea478c4bc
--- /dev/null
+++ b/lib/features/email/presentation/styles/organizer_widget_styles.dart
@@ -0,0 +1,10 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class OrganizerWidgetStyles {
+ static const double maxWidth = 100;
+ static const double textSize = 16;
+ static const Color textColor = Colors.black;
+ static const Color mailtoColor = AppColor.colorMailto;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/styles/see_all_attendees_button_widget_styles.dart b/lib/features/email/presentation/styles/see_all_attendees_button_widget_styles.dart
new file mode 100644
index 0000000000..a64f3ce54e
--- /dev/null
+++ b/lib/features/email/presentation/styles/see_all_attendees_button_widget_styles.dart
@@ -0,0 +1,12 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+
+class SeeAllAttendeesButtonWidgetStyles {
+ static const double textSize = 16;
+ static const double horizontalPadding = 8;
+ static const double verticalPadding = 4;
+ static const double borderRadius = 20;
+ static const double horizontalMargin = -8;
+ static const Color textColor = AppColor.primaryColor;
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/attendee_widget.dart b/lib/features/email/presentation/widgets/calendar_event/attendee_widget.dart
new file mode 100644
index 0000000000..03ebcf3d3d
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/attendee_widget.dart
@@ -0,0 +1,41 @@
+
+import 'package:flutter/material.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/attendee/calendar_attendee.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/attendee_widget_styles.dart';
+
+class AttendeeWidget extends StatelessWidget {
+
+ final CalendarAttendee attendee;
+
+ const AttendeeWidget({
+ super.key,
+ required this.attendee
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return RichText(
+ text: TextSpan(
+ style: const TextStyle(
+ fontSize: AttendeeWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: AttendeeWidgetStyles.textColor
+ ),
+ children: [
+ if (attendee.name?.name.isNotEmpty == true)
+ TextSpan(text: attendee.name!.name),
+ if (attendee.mailto?.mailAddress.value.isNotEmpty == true)
+ TextSpan(
+ text: ' <${attendee.mailto!.mailAddress.value}> ',
+ style: const TextStyle(
+ color: AttendeeWidgetStyles.mailtoColor,
+ fontSize: AttendeeWidgetStyles.textSize,
+ fontWeight: FontWeight.w500
+ ),
+ ),
+ const TextSpan(text: ', '),
+ ]
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart
new file mode 100644
index 0000000000..0d6c39bf21
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart
@@ -0,0 +1,78 @@
+
+import 'package:flutter/material.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.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/widgets/calendar_event/event_attendee_detail_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_description_detail_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_link_detail_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_time_detail_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_title_widget.dart';
+
+class CalendarEventDetailWidget extends StatelessWidget {
+
+ final CalendarEvent calendarEvent;
+
+ const CalendarEventDetailWidget({
+ super.key,
+ required this.calendarEvent
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: const ShapeDecoration(
+ color: Colors.white,
+ shape: RoundedRectangleBorder(
+ side: BorderSide(
+ width: CalendarEventDetailWidgetStyles.borderStrokeWidth,
+ color: CalendarEventDetailWidgetStyles.borderStrokeColor,
+ ),
+ borderRadius: BorderRadius.all(Radius.circular(CalendarEventDetailWidgetStyles.borderRadius)),
+ ),
+ ),
+ margin: const EdgeInsetsDirectional.symmetric(
+ vertical: CalendarEventDetailWidgetStyles.verticalMargin,
+ horizontal: CalendarEventDetailWidgetStyles.horizontalMargin),
+ padding: const EdgeInsets.all(CalendarEventDetailWidgetStyles.contentPadding),
+ width: double.infinity,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if (calendarEvent.title?.isNotEmpty == true)
+ EventTitleWidget(title: calendarEvent.title!),
+ if (calendarEvent.description?.isNotEmpty == true)
+ Padding(
+ padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
+ child: EventDescriptionDetailWidget(description: calendarEvent.description!)
+ ),
+ if (calendarEvent.dateTimeEventAsString.isNotEmpty)
+ Padding(
+ padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
+ child: EventTimeWidgetWidget(timeEvent: calendarEvent.dateTimeEventAsString),
+ ),
+ if (calendarEvent.videoConferences.isNotEmpty)
+ Padding(
+ padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
+ child: EventLinkDetailWidget(listHyperLink: calendarEvent.videoConferences),
+ ),
+ if (calendarEvent.location?.isNotEmpty == true)
+ Padding(
+ padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
+ child: EventLocationDetailWidget(locationEvent: calendarEvent.location!),
+ ),
+ if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
+ Padding(
+ padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
+ child: EventAttendeeDetailWidget(
+ attendees: calendarEvent.participants!,
+ organizer: calendarEvent.organizer!,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
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 ed1cde64b8..62062c4102 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
@@ -10,6 +10,7 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_date_icon_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_location_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/main/localizations/app_localizations.dart';
class CalendarEventInformationWidget extends StatelessWidget {
@@ -82,14 +83,8 @@ class CalendarEventInformationWidget extends StatelessWidget {
)
),
const SizedBox(height: CalendarEventInformationWidgetStyles.space),
- Text(
- calendarEvent.title ?? '',
- style: const TextStyle(
- fontWeight: FontWeight.w500,
- fontSize: CalendarEventInformationWidgetStyles.titleTextSize,
- color: CalendarEventInformationWidgetStyles.titleColor
- )
- ),
+ if (calendarEvent.title?.isNotEmpty == true)
+ EventTitleWidget(title: calendarEvent.title!),
if (calendarEvent.dateTimeEventAsString.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
@@ -153,14 +148,8 @@ class CalendarEventInformationWidget extends StatelessWidget {
)
),
const SizedBox(height: CalendarEventInformationWidgetStyles.space),
- Text(
- calendarEvent.title ?? '',
- style: const TextStyle(
- fontWeight: FontWeight.w500,
- fontSize: CalendarEventInformationWidgetStyles.titleTextSize,
- color: CalendarEventInformationWidgetStyles.titleColor
- )
- ),
+ if (calendarEvent.title?.isNotEmpty == true)
+ EventTitleWidget(title: calendarEvent.title!),
if (calendarEvent.dateTimeEventAsString.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_attendee_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_attendee_detail_widget.dart
new file mode 100644
index 0000000000..13f3026e6d
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_attendee_detail_widget.dart
@@ -0,0 +1,90 @@
+
+import 'package:core/utils/app_logger.dart';
+import 'package:flutter/material.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';
+import 'package:tmail_ui_user/features/email/presentation/extensions/list_attendee_extension.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_attendee_detail_widget_styles.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/attendee_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/organizer_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/see_all_attendees_button_widget.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class EventAttendeeDetailWidget extends StatefulWidget {
+
+ static const int maxAttendeeDisplayed = 6;
+
+ final List attendees;
+ final CalendarOrganizer organizer;
+
+ const EventAttendeeDetailWidget({
+ super.key,
+ required this.attendees,
+ required this.organizer
+ });
+
+ @override
+ State createState() => _EventAttendeeDetailWidgetState();
+}
+
+class _EventAttendeeDetailWidgetState extends State {
+
+ late List _attendeesDisplayed;
+ late bool _isShowAllAttendee;
+
+ @override
+ void initState() {
+ super.initState();
+ _attendeesDisplayed = _splitAttendees(widget.attendees);
+ _isShowAllAttendee = widget.attendees.length <= EventAttendeeDetailWidget.maxAttendeeDisplayed;
+ log('_EventAttendeeDetailWidgetState::initState:attendees: ${widget.attendees.length} | _isShowAllAttendee: $_isShowAllAttendee');
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: EventAttendeeDetailWidgetStyles.maxWidth,
+ child: Text(
+ AppLocalizations.of(context).attendees,
+ style: const TextStyle(
+ fontSize: EventAttendeeDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventAttendeeDetailWidgetStyles.labelColor
+ ),
+ ),
+ ),
+ Expanded(child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ OrganizerWidget(organizer: widget.organizer),
+ ..._attendeesDisplayed
+ .map((attendee) => AttendeeWidget(attendee: attendee))
+ .toList(),
+ if (!_isShowAllAttendee)
+ Padding(
+ padding: const EdgeInsets.only(top: EventAttendeeDetailWidgetStyles.fieldTopPadding),
+ child: SeeAllAttendeesButtonWidget(
+ onTap: () {
+ setState(() {
+ _attendeesDisplayed = widget.attendees.withoutOrganizer(widget.organizer);
+ _isShowAllAttendee = true;
+ });
+ }
+ ),
+ )
+ ]
+ ))
+ ],
+ );
+ }
+
+ List _splitAttendees(List attendees) {
+ final attendeesWithoutOrganizer = attendees.withoutOrganizer(widget.organizer);
+ return attendeesWithoutOrganizer.length > EventAttendeeDetailWidget.maxAttendeeDisplayed
+ ? attendeesWithoutOrganizer.sublist(0, EventAttendeeDetailWidget.maxAttendeeDisplayed - 1)
+ : attendeesWithoutOrganizer;
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_attendee_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_attendee_information_widget.dart
index 4567c94926..f38edc797a 100644
--- a/lib/features/email/presentation/widgets/calendar_event/event_attendee_information_widget.dart
+++ b/lib/features/email/presentation/widgets/calendar_event/event_attendee_information_widget.dart
@@ -1,5 +1,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/properties/attendee/calendar_attendee.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/list_attendee_extension.dart';
@@ -19,6 +21,7 @@ class EventAttendeeInformationWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final responsiveUtils = Get.find();
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -52,7 +55,11 @@ class EventAttendeeInformationWidget extends StatelessWidget {
const TextSpan(text: ', '),
TextSpan(text: attendees.withoutOrganizer(organizer).mailtoAsString)
]
- )
+ ),
+ overflow: responsiveUtils.isPortraitMobile(context)
+ ? TextOverflow.clip
+ : TextOverflow.ellipsis,
+ maxLines: responsiveUtils.isPortraitMobile(context) ? null : 2,
))
],
);
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_description_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_description_detail_widget.dart
new file mode 100644
index 0000000000..298a5465e7
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_description_detail_widget.dart
@@ -0,0 +1,48 @@
+
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_description_detail_widget_styles.dart';
+
+class EventDescriptionDetailWidget extends StatelessWidget {
+
+ final String description;
+
+ const EventDescriptionDetailWidget({
+ super.key,
+ required this.description
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final imagePath = Get.find();
+ return Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: const BoxDecoration(
+ color: AppColor.colorEventDescriptionBackground,
+ borderRadius: BorderRadius.all(Radius.circular(EventDescriptionDetailWidgetStyles.borderRadius)),
+ ),
+ width: double.infinity,
+ padding: const EdgeInsetsDirectional.all(EventDescriptionDetailWidgetStyles.contentPadding),
+ child: Stack(
+ children: [
+ Text(
+ description,
+ style: const TextStyle(
+ fontWeight: FontWeight.w500,
+ fontSize: EventDescriptionDetailWidgetStyles.textSize,
+ color: EventDescriptionDetailWidgetStyles.valueColor
+ )
+ ),
+ PositionedDirectional(
+ top: 0,
+ end: 0,
+ child: SvgPicture.asset(imagePath.icFormatQuote)
+ )
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_link_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_link_detail_widget.dart
new file mode 100644
index 0000000000..32bbccd945
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_link_detail_widget.dart
@@ -0,0 +1,39 @@
+
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/features/base/widget/hyper_link_widget.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_link_detail_widget_styles.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class EventLinkDetailWidget extends StatelessWidget {
+
+ final List listHyperLink;
+
+ const EventLinkDetailWidget({
+ super.key,
+ required this.listHyperLink
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: EventLinkDetailWidgetStyles.maxWidth,
+ child: Text(
+ AppLocalizations.of(context).link,
+ style: const TextStyle(
+ fontSize: EventLinkDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventLinkDetailWidgetStyles.labelColor
+ ),
+ ),
+ ),
+ Expanded(child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: listHyperLink.map((link) => HyperLinkWidget(urlString: link)).toList(),
+ ))
+ ],
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart
new file mode 100644
index 0000000000..36b046848d
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart
@@ -0,0 +1,42 @@
+
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_location_detail_widget_styles.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class EventLocationDetailWidget extends StatelessWidget {
+
+ final String locationEvent;
+
+ const EventLocationDetailWidget({
+ super.key,
+ required this.locationEvent
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: EventLocationDetailWidgetStyles.maxWidth,
+ child: Text(
+ AppLocalizations.of(context).location,
+ style: const TextStyle(
+ fontSize: EventLocationDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventLocationDetailWidgetStyles.labelColor
+ ),
+ ),
+ ),
+ Expanded(child: Text(
+ locationEvent,
+ style: const TextStyle(
+ fontSize: EventLocationDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventLocationDetailWidgetStyles.valueColor
+ ),
+ ))
+ ],
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart
index f19c917d71..3aa35ff053 100644
--- a/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart
+++ b/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart
@@ -1,6 +1,8 @@
+import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:flutter/material.dart';
+import 'package:get/get.dart';
import 'package:tmail_ui_user/features/email/presentation/styles/event_location_information_widget_styles.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -15,6 +17,7 @@ class EventLocationInformationWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final responsiveUtils = Get.find();
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -31,8 +34,9 @@ class EventLocationInformationWidget extends StatelessWidget {
),
Expanded(child: Text(
locationEvent,
- overflow: CommonTextStyle.defaultTextOverFlow,
- softWrap: CommonTextStyle.defaultSoftWrap,
+ overflow: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultTextOverFlow,
+ softWrap: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultSoftWrap,
+ maxLines: responsiveUtils.isPortraitMobile(context) ? null : 1,
style: const TextStyle(
fontSize: EventLocationInformationWidgetStyles.textSize,
fontWeight: FontWeight.w500,
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_time_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_time_detail_widget.dart
new file mode 100644
index 0000000000..1af9a6ca94
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_time_detail_widget.dart
@@ -0,0 +1,42 @@
+
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_time_detail_widget_styles.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class EventTimeWidgetWidget extends StatelessWidget {
+
+ final String timeEvent;
+
+ const EventTimeWidgetWidget({
+ super.key,
+ required this.timeEvent
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: EventTimeDetailWidgetStyles.maxWidth,
+ child: Text(
+ AppLocalizations.of(context).time,
+ style: const TextStyle(
+ fontSize: EventTimeDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventTimeDetailWidgetStyles.labelColor
+ ),
+ ),
+ ),
+ Expanded(child: Text(
+ timeEvent,
+ style: const TextStyle(
+ fontSize: EventTimeDetailWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: EventTimeDetailWidgetStyles.valueColor
+ ),
+ ))
+ ],
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart
index 4d8af58d42..1130e5a23e 100644
--- a/lib/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart
+++ b/lib/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart
@@ -1,6 +1,8 @@
+import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:flutter/material.dart';
+import 'package:get/get.dart';
import 'package:tmail_ui_user/features/email/presentation/styles/event_time_information_widget_styles.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -15,6 +17,7 @@ class EventTimeInformationWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final responsiveUtils = Get.find();
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -31,8 +34,9 @@ class EventTimeInformationWidget extends StatelessWidget {
),
Expanded(child: Text(
timeEvent,
- overflow: CommonTextStyle.defaultTextOverFlow,
- softWrap: CommonTextStyle.defaultSoftWrap,
+ overflow: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultTextOverFlow,
+ softWrap: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultSoftWrap,
+ maxLines: responsiveUtils.isPortraitMobile(context) ? null : 1,
style: const TextStyle(
fontSize: EventTimeInformationWidgetStyles.textSize,
fontWeight: FontWeight.w500,
diff --git a/lib/features/email/presentation/widgets/calendar_event/event_title_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_title_widget.dart
new file mode 100644
index 0000000000..99284c95c1
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/event_title_widget.dart
@@ -0,0 +1,22 @@
+
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/event_title_widget_styles.dart';
+
+class EventTitleWidget extends StatelessWidget {
+
+ final String title;
+
+ const EventTitleWidget({super.key, required this.title});
+
+ @override
+ Widget build(BuildContext context) {
+ return Text(
+ title,
+ style: const TextStyle(
+ fontWeight: FontWeight.w500,
+ fontSize: EventTitleWidgetStyles.textSize,
+ color: EventTitleWidgetStyles.textColor
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/organizer_widget.dart b/lib/features/email/presentation/widgets/calendar_event/organizer_widget.dart
new file mode 100644
index 0000000000..4ac0dce035
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/organizer_widget.dart
@@ -0,0 +1,43 @@
+
+import 'package:flutter/material.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/organizer_widget_styles.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class OrganizerWidget extends StatelessWidget {
+
+ final CalendarOrganizer organizer;
+
+ const OrganizerWidget({
+ super.key,
+ required this.organizer
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return RichText(
+ text: TextSpan(
+ style: const TextStyle(
+ fontSize: OrganizerWidgetStyles.textSize,
+ fontWeight: FontWeight.w500,
+ color: OrganizerWidgetStyles.textColor
+ ),
+ children: [
+ if (organizer.name?.isNotEmpty == true)
+ TextSpan(text: organizer.name!),
+ if (organizer.mailto?.value.isNotEmpty == true)
+ TextSpan(
+ text: ' <${organizer.mailto!.value}> ',
+ style: const TextStyle(
+ color: OrganizerWidgetStyles.mailtoColor,
+ fontSize: OrganizerWidgetStyles.textSize,
+ fontWeight: FontWeight.w500
+ ),
+ ),
+ TextSpan(text: '(${AppLocalizations.of(context).organizer})'),
+ const TextSpan(text: ', '),
+ ]
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/calendar_event/see_all_attendees_button_widget.dart b/lib/features/email/presentation/widgets/calendar_event/see_all_attendees_button_widget.dart
new file mode 100644
index 0000000000..78ce4d4dcf
--- /dev/null
+++ b/lib/features/email/presentation/widgets/calendar_event/see_all_attendees_button_widget.dart
@@ -0,0 +1,35 @@
+
+import 'package:flutter/cupertino.dart';
+import 'package:tmail_ui_user/features/base/widget/material_text_button.dart';
+import 'package:tmail_ui_user/features/email/presentation/styles/see_all_attendees_button_widget_styles.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class SeeAllAttendeesButtonWidget extends StatelessWidget {
+
+ final VoidCallback onTap;
+
+ const SeeAllAttendeesButtonWidget({
+ super.key,
+ required this.onTap
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Transform(
+ transform: Matrix4.translationValues(SeeAllAttendeesButtonWidgetStyles.horizontalMargin, 0.0, 0.0),
+ child: MaterialTextButton(
+ label: AppLocalizations.of(context).seeAllAttendees,
+ onTap: onTap,
+ borderRadius: SeeAllAttendeesButtonWidgetStyles.borderRadius,
+ padding: const EdgeInsetsDirectional.symmetric(
+ horizontal: SeeAllAttendeesButtonWidgetStyles.horizontalPadding,
+ vertical: SeeAllAttendeesButtonWidgetStyles.verticalPadding
+ ),
+ customStyle: const TextStyle(
+ fontSize: SeeAllAttendeesButtonWidgetStyles.textSize,
+ color: SeeAllAttendeesButtonWidgetStyles.textColor
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart b/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart
new file mode 100644
index 0000000000..4d92cf4785
--- /dev/null
+++ b/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart
@@ -0,0 +1,34 @@
+import 'package:core/presentation/state/failure.dart';
+import 'package:core/presentation/state/success.dart';
+import 'package:dartz/dartz.dart';
+import 'package:flutter/material.dart';
+import 'package:model/email/presentation_email.dart';
+import 'package:tmail_ui_user/features/base/widget/cupertino_loading_widget.dart';
+import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
+import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';
+
+class EmailViewLoadingBarWidget extends StatelessWidget {
+
+ final PresentationEmail selectedEmail;
+ final Either viewState;
+
+ const EmailViewLoadingBarWidget({
+ super.key,
+ required this.viewState,
+ required this.selectedEmail
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return viewState.fold(
+ (failure) => const SizedBox.shrink(),
+ (success) {
+ if (success is GetEmailContentLoading || (success is ParseCalendarEventLoading && selectedEmail.hasCalendarEvent)) {
+ return const CupertinoLoadingWidget();
+ } else {
+ return const SizedBox.shrink();
+ }
+ }
+ );
+ }
+}
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index b5aa0216c2..7dfb0a04b5 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -1,5 +1,5 @@
{
- "@@last_modified": "2023-07-26T18:42:34.026265",
+ "@@last_modified": "2023-07-28T02:46:38.430701",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -3077,5 +3077,35 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
+ },
+ "time": "Time",
+ "@time": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "location": "Location",
+ "@location": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "attendees": "Attendees",
+ "@attendees": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "seeAllAttendees": "See all attendees",
+ "@seeAllAttendees": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "link": "Link",
+ "@link": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index f4102265b6..29e81d2090 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -3173,4 +3173,35 @@ class AppLocalizations {
'Organizer',
name: 'organizer');
}
+
+ String get time {
+ return Intl.message(
+ 'Time',
+ name: 'time',
+ );
+ }
+
+ String get location {
+ return Intl.message(
+ 'Location',
+ name: 'location');
+ }
+
+ String get attendees {
+ return Intl.message(
+ 'Attendees',
+ name: 'attendees');
+ }
+
+ String get seeAllAttendees {
+ return Intl.message(
+ 'See all attendees',
+ name: 'seeAllAttendees');
+ }
+
+ String get link {
+ return Intl.message(
+ 'Link',
+ name: 'link');
+ }
}
\ No newline at end of file