Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TF-2057 Display calendar detail widget in email view #2059

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions assets/images/ic_format_quote.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions core/lib/presentation/extensions/color_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
Expand Down
1 change: 1 addition & 0 deletions core/lib/presentation/resources/image_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions lib/features/base/styles/cupertino_loading_widget_styles.dart
Original file line number Diff line number Diff line change
@@ -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;
}
7 changes: 7 additions & 0 deletions lib/features/base/styles/hyper_link_widget_styles.dart
Original file line number Diff line number Diff line change
@@ -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;
}
17 changes: 17 additions & 0 deletions lib/features/base/widget/cupertino_loading_widget.dart
Original file line number Diff line number Diff line change
@@ -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)
)
);
}
}
33 changes: 33 additions & 0 deletions lib/features/base/widget/hyper_link_widget.dart
Original file line number Diff line number Diff line change
@@ -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
);
}
}
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
124 changes: 59 additions & 65 deletions lib/features/email/presentation/email_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -228,7 +229,7 @@ class EmailView extends GetWidget<SingleEmailController> with AppLoaderMixin {
}

Widget _buildEmailBody(BuildContext context, PresentationEmail email) {
if (PlatformInfo.isWeb) {
if (PlatformInfo.isWeb && !email.hasCalendarEvent) {
return _buildEmailMessage(context, email);
} else {
return SingleChildScrollView(
Expand Down Expand Up @@ -281,59 +282,41 @@ class EmailView extends GetWidget<SingleEmailController> 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;
Expand Down Expand Up @@ -463,25 +446,36 @@ class EmailView extends GetWidget<SingleEmailController> 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,20 @@ extension CalendarEventExtension on CalendarEvent {
return '';
}
}

List<String> 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)
dab246 marked this conversation as resolved.
Show resolved Hide resolved
.toList();
log('CalendarEventExtension::getListVideoConference: $videoConferencesNotEmpty');
return videoConferencesNotEmpty;
}
}

return [];
}
}
10 changes: 10 additions & 0 deletions lib/features/email/presentation/styles/attendee_widget_styles.dart
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Loading
Loading