From 17499e70db3727ae131c20cddb0adb69f73bcf52 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 9 Mar 2022 19:27:45 +0700 Subject: [PATCH] TF-313 Apply new ui for email address detail --- assets/images/ic_unread_status.svg | 3 + .../extensions/color_extension.dart | 1 + .../presentation/resources/image_paths.dart | 1 + .../presentation/composer_controller.dart | 5 + .../email/presentation/email_controller.dart | 90 +++++++- .../email/presentation/email_view.dart | 75 ++++--- .../model/composer_arguments.dart | 4 + .../widgets/app_bar_mail_widget_builder.dart | 1 - .../email_address_bottom_sheet_builder.dart | 136 ++++++++++++ .../widgets/email_address_dialog_builder.dart | 117 ++++++++++ ...and_receiver_information_tile_builder.dart | 209 ------------------ .../widgets/email_tile_builder.dart | 2 +- lib/main/localizations/app_localizations.dart | 18 ++ model/lib/email/email_action_type.dart | 1 + 14 files changed, 411 insertions(+), 252 deletions(-) create mode 100644 assets/images/ic_unread_status.svg create mode 100644 lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart create mode 100644 lib/features/email/presentation/widgets/email_address_dialog_builder.dart delete mode 100644 lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart diff --git a/assets/images/ic_unread_status.svg b/assets/images/ic_unread_status.svg new file mode 100644 index 000000000..bd8053fad --- /dev/null +++ b/assets/images/ic_unread_status.svg @@ -0,0 +1,3 @@ + + + diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 1a703c6ce..b2fac64cd 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -93,6 +93,7 @@ extension AppColor on Color { static const colorTime = Color(0xFF92A1B4); static const colorEmailAddressPrefix = Color(0xFF9AA7B6); static const colorEmailAddressTag = Color(0x146D7885); + static const colorLineLeftEmailView = Color(0x2999A2AD); 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 ea2f20404..6c4cac104 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -65,6 +65,7 @@ class ImagePaths { String get icDeleteEmailAddress => _getImagePath('ic_delete_email_address.svg'); String get icDeleteEmail => _getImagePath('ic_delete_email.svg'); String get icNewMessage => _getImagePath('ic_new_message.svg'); + String get icUnreadStatus => _getImagePath('ic_unread_status.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index c9d057eca..c02ae82c5 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -250,6 +250,9 @@ class ComposerController extends BaseController { if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) { isInitialRecipient.value = true; } + } else if (arguments.emailAddress != null) { + listToEmailAddress.add(arguments.emailAddress!); + isInitialRecipient.value = true; } _updateStatusEmailSendButton(); } @@ -265,6 +268,8 @@ class ComposerController extends BaseController { case PrefixEmailAddress.bcc: listBccEmailAddress = newListEmailAddress; break; + default: + break; } _updateStatusEmailSendButton(); } diff --git a/lib/features/email/presentation/email_controller.dart b/lib/features/email/presentation/email_controller.dart index c29feeaaa..34a4462bc 100644 --- a/lib/features/email/presentation/email_controller.dart +++ b/lib/features/email/presentation/email_controller.dart @@ -3,9 +3,11 @@ import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/model.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; @@ -27,6 +29,8 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; +import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart'; +import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -38,6 +42,7 @@ class EmailController extends BaseController { final mailboxDashBoardController = Get.find(); final responsiveUtils = Get.find(); + final imagePaths = Get.find(); final GetEmailContentInteractor _getEmailContentInteractor; final MarkAsEmailReadInteractor _markAsEmailReadInteractor; @@ -398,7 +403,9 @@ class EmailController extends BaseController { mailboxDashBoardController.dispatchState(Right(success)); } - void handleEmailAction(PresentationEmail presentationEmail, EmailActionType actionType) { + void handleEmailAction(BuildContext context, PresentationEmail presentationEmail, EmailActionType actionType) { + popBack(); + switch(actionType) { case EmailActionType.markAsUnread: markAsEmailRead(presentationEmail, ReadActions.markAsUnread); @@ -413,6 +420,7 @@ class EmailController extends BaseController { moveToMailboxAction(presentationEmail); break; case EmailActionType.delete: + _appToast.showToast(AppLocalizations.of(context).the_feature_is_under_development); break; default: break; @@ -440,6 +448,51 @@ class EmailController extends BaseController { isDisplayFullEmailAddress.value = true; } + void openEmailAddressDialog(BuildContext context, EmailAddress emailAddress) { + if (responsiveUtils.isMobile(context) || responsiveUtils.isMobileDevice(context)) { + (EmailAddressBottomSheetBuilder(context, imagePaths, emailAddress) + ..addOnCloseContextMenuAction(() => popBack()) + ..addOnCopyEmailAddressAction((emailAddress) => copyEmailAddress(context, emailAddress)) + ..addOnComposeEmailAction((emailAddress) => composeEmailFromEmailAddress(emailAddress))) + .show(); + } else { + showDialog( + context: context, + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + builder: (BuildContext context) => (EmailAddressDialogBuilder(context, imagePaths, emailAddress) + ..addOnCloseContextMenuAction(() => popBack()) + ..addOnCopyEmailAddressAction((emailAddress) => copyEmailAddress(context, emailAddress)) + ..addOnComposeEmailAction((emailAddress) => composeEmailFromEmailAddress(emailAddress))) + .build()); + } + } + + void copyEmailAddress(BuildContext context, EmailAddress emailAddress) { + popBack(); + + Clipboard.setData(ClipboardData(text: emailAddress.emailAddress)).then((_){ + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(AppLocalizations.of(context).email_address_copied_to_clipboard)) + ); + }); + } + + void composeEmailFromEmailAddress(EmailAddress emailAddress) { + popBack(); + + if (canComposeEmail()) { + push( + AppRoutes.COMPOSER, + arguments: ComposerArguments( + emailActionType: EmailActionType.composeFromEmailAddress, + emailAddress: emailAddress, + mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role, + session: mailboxDashBoardController.sessionCurrent!, + userProfile: mailboxDashBoardController.userProfile.value!, + mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId)); + } + } + void closeMoreMenu() { popBack(); } @@ -457,18 +510,33 @@ class EmailController extends BaseController { } void pressEmailAction(EmailActionType emailActionType) { + if (emailActionType == EmailActionType.compose) { + composeEmailAction(); + } else { + if (canComposeEmail()) { + push( + AppRoutes.COMPOSER, + arguments: ComposerArguments( + emailActionType: emailActionType, + presentationEmail: mailboxDashBoardController.selectedEmail.value!, + emailContents: emailContents, + attachments: attachments, + mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role, + session: mailboxDashBoardController.sessionCurrent!, + userProfile: mailboxDashBoardController.userProfile.value!, + mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId)); + } + } + } + + void composeEmailAction() { if (canComposeEmail()) { push( - AppRoutes.COMPOSER, - arguments: ComposerArguments( - emailActionType: emailActionType, - presentationEmail: mailboxDashBoardController.selectedEmail.value!, - emailContents: emailContents, - attachments: attachments, - mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role, - session: mailboxDashBoardController.sessionCurrent!, - userProfile: mailboxDashBoardController.userProfile.value!, - mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId)); + AppRoutes.COMPOSER, + arguments: ComposerArguments( + session: mailboxDashBoardController.sessionCurrent!, + userProfile: mailboxDashBoardController.userProfile.value!, + mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId)); } } } \ 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 8311a87be..0338c471a 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -31,21 +31,33 @@ class EmailView extends GetView { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: AppColor.primaryLightColor, - body: SafeArea( - right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), - left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildAppBar(context), - _buildDivider(), - Expanded(child: _buildEmailBody(context)), - Divider(color: AppColor.colorDividerEmailView, height: 1), - _buildBottomBar(context), - ] - ) - )); + backgroundColor: Colors.white, + body: Container( + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: !(responsiveUtils.isMobile(context) && responsiveUtils.isMobileDevice(context)) + ? BoxDecoration(border: Border(left: BorderSide(color: AppColor.colorLineLeftEmailView, width: 1.0))) + : null, + child: SafeArea( + right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), + left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildAppBar(context), + Obx(() => emailController.currentEmail != null + ? _buildDivider() + : SizedBox.shrink()), + Expanded(child: _buildEmailBody(context)), + Obx(() => emailController.currentEmail != null + ? Divider(color: AppColor.colorDividerEmailView, height: 1) + : SizedBox.shrink()), + _buildBottomBar(context), + ] + ) + ), + ) + ); } Widget _buildDivider({EdgeInsets? edgeInsets}){ @@ -64,7 +76,7 @@ class EmailView extends GetView { emailController.currentEmail, emailController.currentMailbox) ..onBackActionClick(() => emailController.backToThreadView()) - ..addOnEmailActionClick((email, action) => emailController.handleEmailAction(email, action)) + ..addOnEmailActionClick((email, action) => emailController.handleEmailAction(context, email, action)) ..addOnMoreActionClick((email, position) => responsiveUtils.isMobileDevice(context) ? emailController.openMoreMenuEmailAction( context, @@ -235,20 +247,23 @@ class EmailView extends GetView { ...displayedEmailAddress.map((emailAddress) { return Padding( padding: EdgeInsets.only(left: 10), - child: Chip( - labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2), - label: Text('${emailAddress.emailAddress}', maxLines: 1, overflow: TextOverflow.ellipsis), - labelStyle: TextStyle(color: AppColor.colorNameEmail, fontSize: 15, fontWeight: FontWeight.normal), - backgroundColor: AppColor.colorEmailAddressTag, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag), + child: GestureDetector( + onTap: () => emailController.openEmailAddressDialog(context, emailAddress), + child: Chip( + labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2), + label: Text('${emailAddress.asString()}', maxLines: 1, overflow: TextOverflow.ellipsis), + labelStyle: TextStyle(color: AppColor.colorNameEmail, fontSize: 15, fontWeight: FontWeight.normal), + backgroundColor: AppColor.colorEmailAddressTag, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag), + ), + avatar: (AvatarBuilder() + ..text('${emailAddress.asString().characters.first.toUpperCase()}') + ..addTextStyle(TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600)) + ..avatarColor(emailAddress.avatarColors)) + .build(), ), - avatar: (AvatarBuilder() - ..text('${emailAddress.emailAddress.characters.first.toUpperCase()}') - ..addTextStyle(TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600)) - ..avatarColor(emailAddress.avatarColors)) - .build(), ) ); }).toList(), @@ -484,7 +499,7 @@ class EmailView extends GetView { iconRightPadding: responsiveUtils.isMobile(context) ? EdgeInsets.only(right: 12) : EdgeInsets.zero) - ..onActionClick((email) => emailController.handleEmailAction(email, EmailActionType.markAsUnread))) + ..onActionClick((email) => emailController.handleEmailAction(context, email, EmailActionType.markAsUnread))) .build(); } diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 1cc49ea7c..8f323f726 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -1,6 +1,7 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; @@ -8,6 +9,7 @@ class ComposerArguments with EquatableMixin { final EmailActionType emailActionType; final PresentationEmail? presentationEmail; final List? emailContents; + final EmailAddress? emailAddress; final List? attachments; final Session session; final UserProfile userProfile; @@ -20,6 +22,7 @@ class ComposerArguments with EquatableMixin { this.emailContents, this.attachments, this.mailboxRole, + this.emailAddress, required this.session, required this.userProfile, required this.mapMailboxId, @@ -31,6 +34,7 @@ class ComposerArguments with EquatableMixin { emailContents, attachments, mailboxRole, + emailAddress, session, userProfile, mapMailboxId, diff --git a/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart b/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart index e4e6b631d..5675ab258 100644 --- a/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart +++ b/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart @@ -99,7 +99,6 @@ class AppBarMailWidgetBuilder { (_presentationEmail != null && _presentationEmail!.isFlaggedEmail()) ? _imagePaths.icStar : _imagePaths.icUnStar, - color: AppColor.colorButton, fit: BoxFit.fill), onPressed: () { if (_presentationEmail != null) { diff --git a/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart b/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart new file mode 100644 index 000000000..19ed3ae2b --- /dev/null +++ b/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart @@ -0,0 +1,136 @@ + +import 'package:core/core.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnCloseBottomSheetAction = void Function(); +typedef OnCopyEmailAddressBottomSheetAction = void Function(EmailAddress); +typedef OnComposeEmailBottomSheetAction = void Function(EmailAddress); + +class EmailAddressBottomSheetBuilder { + + final BuildContext _context; + final ImagePaths _imagePaths; + final EmailAddress _emailAddress; + + OnCloseBottomSheetAction? _onCloseBottomSheetAction; + OnCopyEmailAddressBottomSheetAction? _onCopyEmailAddressAction; + OnComposeEmailBottomSheetAction? _onComposeEmailAction; + + EmailAddressBottomSheetBuilder( + this._context, + this._imagePaths, + this._emailAddress + ); + + void addOnCloseContextMenuAction(OnCloseBottomSheetAction onCloseBottomSheetAction) { + _onCloseBottomSheetAction = onCloseBottomSheetAction; + } + + void addOnCopyEmailAddressAction(OnCopyEmailAddressBottomSheetAction onCopyEmailAddressAction) { + _onCopyEmailAddressAction = onCopyEmailAddressAction; + } + + void addOnComposeEmailAction(OnComposeEmailBottomSheetAction onComposeEmailAction) { + _onComposeEmailAction = onComposeEmailAction; + } + + RoundedRectangleBorder _shape() { + return RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0))); + } + + BoxDecoration _decoration(BuildContext context) { + return BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: const Radius.circular(20.0), + topRight: const Radius.circular(20.0))); + } + + void show() { + Get.bottomSheet( + GestureDetector( + onTap: () => _onCloseBottomSheetAction?.call(), + child: SingleChildScrollView( + child: Container( + margin: EdgeInsets.zero, + decoration: _decoration(_context), + child: SafeArea(child: GestureDetector( + onTap: () => {}, + child: Column( + children: [ + Align( + alignment: Alignment.centerRight, + child: IconButton( + padding: EdgeInsets.only(top: 16, right: 16), + onPressed: () => _onCloseBottomSheetAction?.call(), + icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))), + (AvatarBuilder() + ..text('${_emailAddress.asString().characters.first.toUpperCase()}') + ..size(64) + ..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white)) + ..avatarColor(_emailAddress.avatarColors)) + .build(), + if (_emailAddress.displayName.isNotEmpty) + Padding( + padding: EdgeInsets.only(left: 16, right: 16, top: 16), + child: Text( + _emailAddress.asString(), + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail), + )), + Padding( + padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16), + child: Text( + _emailAddress.emailAddress, + style: TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog), + )), + Material( + borderRadius: BorderRadius.circular(20), + color: Colors.transparent, + child: TextButton( + child: Text( + AppLocalizations.of(_context).copy_email_address, + style: TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal), + ), + onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress) + ) + ), + SizedBox(height: _emailAddress.displayName.isNotEmpty ? 100 : 130), + Padding( + padding: EdgeInsets.only(left: 16, right: 16, bottom: 20), + child: SizedBox( + key: Key('compose_email_button'), + width: double.infinity, + height: 48, + child: ElevatedButton( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.resolveWith((Set states) => Colors.white), + backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.colorTextButton), + shape: MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(width: 0, color: AppColor.colorTextButton)))), + child: Text(AppLocalizations.of(_context).compose_email, style: TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)), + onPressed: () => _onComposeEmailAction?.call(_emailAddress)), + ) + ) + ], + ), + )), + ), + ), + ), + useRootNavigator: true, + shape: _shape(), + isScrollControlled: true, + enableDrag: false, + backgroundColor: Colors.transparent + ); + } +} \ No newline at end of file diff --git a/lib/features/email/presentation/widgets/email_address_dialog_builder.dart b/lib/features/email/presentation/widgets/email_address_dialog_builder.dart new file mode 100644 index 000000000..b4f256629 --- /dev/null +++ b/lib/features/email/presentation/widgets/email_address_dialog_builder.dart @@ -0,0 +1,117 @@ + +import 'package:core/core.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnCloseDialogAction = void Function(); +typedef OnCopyEmailAddressDialogAction = void Function(EmailAddress); +typedef OnComposeEmailDialogAction = void Function(EmailAddress); + +class EmailAddressDialogBuilder { + + final BuildContext _context; + final ImagePaths _imagePaths; + final EmailAddress _emailAddress; + + OnCloseDialogAction? _onCloseDialogAction; + OnCopyEmailAddressDialogAction? _onCopyEmailAddressAction; + OnComposeEmailDialogAction? _onComposeEmailAction; + + EmailAddressDialogBuilder( + this._context, + this._imagePaths, + this._emailAddress + ); + + void addOnCloseContextMenuAction(OnCloseDialogAction onCloseDialogAction) { + _onCloseDialogAction = onCloseDialogAction; + } + + void addOnCopyEmailAddressAction(OnCopyEmailAddressDialogAction onCopyEmailAddressAction) { + _onCopyEmailAddressAction = onCopyEmailAddressAction; + } + + void addOnComposeEmailAction(OnComposeEmailDialogAction onComposeEmailAction) { + _onComposeEmailAction = onComposeEmailAction; + } + + Widget build() { + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), + insetPadding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), + child: Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + width: 400, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16))), + child: Wrap( + children: [ + Align( + alignment: Alignment.centerRight, + child: IconButton( + padding: EdgeInsets.only(top: 16, right: 16), + onPressed: () => _onCloseDialogAction?.call(), + icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))), + Padding(padding: EdgeInsets.symmetric(horizontal: 16), + child: Center(child: (AvatarBuilder() + ..text('${_emailAddress.asString().characters.first.toUpperCase()}') + ..size(64) + ..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white)) + ..avatarColor(_emailAddress.avatarColors)) + .build())), + if (_emailAddress.displayName.isNotEmpty) + Padding( + padding: EdgeInsets.only(left: 16, right: 16, top: 16), + child: Center(child: Text( + _emailAddress.asString(), + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail), + )) + ), + Padding( + padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16), + child: Center(child: Text( + _emailAddress.emailAddress, + style: TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog), + )) + ), + Padding(padding: EdgeInsets.symmetric(horizontal: 16), + child: Center(child: Material( + borderRadius: BorderRadius.circular(20), + color: Colors.transparent, + child: TextButton( + child: Text( + AppLocalizations.of(_context).copy_email_address, + style: TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal), + ), + onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress) + ) + ))), + SizedBox(height: _emailAddress.displayName.isNotEmpty ? 100 : 130), + Padding( + padding: EdgeInsets.only(left: 16, right: 16, bottom: 20), + child: SizedBox( + key: Key('compose_email_button'), + width: double.infinity, + height: 48, + child: ElevatedButton( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.resolveWith((Set states) => Colors.white), + backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.colorTextButton), + shape: MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(width: 0, color: AppColor.colorTextButton)))), + child: Text(AppLocalizations.of(_context).compose_email, style: TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)), + onPressed: () => _onComposeEmailAction?.call(_emailAddress)), + ) + ) + ], + ) + ), + ); + } +} diff --git a/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart b/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart deleted file mode 100644 index 13a01f7ee..000000000 --- a/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart +++ /dev/null @@ -1,209 +0,0 @@ - -import 'package:core/core.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; -import 'package:model/model.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -typedef OnOpenExpandAddressReceiverActionClick = void Function(); - -class SenderAndReceiverInformationTileBuilder { - - static const int LIMIT_ADDRESS_DISPLAY = 1; - - final ImagePaths _imagePaths; - final BuildContext _context; - final PresentationEmail? _presentationEmail; - final ExpandMode _expandMode; - - OnOpenExpandAddressReceiverActionClick? _onOpenExpandAddressReceiverActionClick; - - SenderAndReceiverInformationTileBuilder( - this._context, - this._imagePaths, - this._presentationEmail, - this._expandMode, - ); - - SenderAndReceiverInformationTileBuilder onOpenExpandAddressReceiverActionClick(OnOpenExpandAddressReceiverActionClick onOpenExpandAddressReceiverActionClick) { - _onOpenExpandAddressReceiverActionClick = onOpenExpandAddressReceiverActionClick; - return this; - } - - Widget build() { - if (_presentationEmail == null) { - return SizedBox.shrink(); - } - return Theme( - data: ThemeData( - splashColor: Colors.transparent, - highlightColor: Colors.transparent), - child: MediaQuery( - data: MediaQueryData(padding: EdgeInsets.zero), - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: Transform( - transform: Matrix4.translationValues(0.0, 0.0, 0.0), - child: (AvatarBuilder() - ..text('${_presentationEmail!.getAvatarText()}') - ..textColor(Colors.white) - ..avatarColor(_presentationEmail?.avatarColors) - ..size(GetPlatform.isWeb ? 48 : 56)) - // .iconStatus(_imagePaths.icOffline) - .build()), - title: Transform( - transform: Matrix4.translationValues(0.0, 0.0, 0.0), - child: Row(children: [ - Expanded(child: Text( - '${_presentationEmail!.getSenderName()}', - style: TextStyle(fontSize: 17, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500), - )), - Padding( - padding: EdgeInsets.only(left: 8), - child: Text( - '${_presentationEmail!.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}', - maxLines: 1, - overflow:TextOverflow.ellipsis, - style: TextStyle(fontSize: 15, color: AppColor.colorContentEmail))) - ])), - subtitle: Transform( - transform: Matrix4.translationValues(0.0, 0.0, 0.0), - child: Row(children: [ - Expanded(child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (_presentationEmail!.to.numberEmailAddress() > 0) _buildAddressToReceiverWidget(), - if (_presentationEmail!.cc.numberEmailAddress() > 0) _buildAddressCcReceiverWidget(), - if (_presentationEmail!.bcc.numberEmailAddress() > 0) _buildAddressBccReceiverWidget(), - ], - )), - if (_presentationEmail?.hasAttachment == true) - Padding( - padding: EdgeInsets.only(left: 8), - child: (ButtonBuilder(_imagePaths.icAttachment) - ..paddingIcon(EdgeInsets.zero) - ..size(16)) - .build()), - ])) - ) - ) - ); - } - - Widget _buildExpandAddressWidget(String typeReceiver, String nameAddress) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '$typeReceiver: ', - style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)), - Expanded(child: Text( - '$nameAddress', - style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500), - )) - ]); - } - - Widget _buildCollapseAddressWidget(String typeReceiver, String nameAddress) { - return Row( - children: [ - Text( - '$typeReceiver: $nameAddress', - style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)), - if (_expandMode == ExpandMode.COLLAPSE - && _presentationEmail != null - && _presentationEmail!.numberOfAllEmailAddress() > LIMIT_ADDRESS_DISPLAY) - _buildButtonExpandAddress() - ]); - } - - Widget _buildAddressWidget(String typeReceiver, String nameAddress) { - if (_expandMode == ExpandMode.EXPAND - || (_presentationEmail != null && _presentationEmail!.numberOfAllEmailAddress() <= LIMIT_ADDRESS_DISPLAY)) { - return Padding( - padding: EdgeInsets.only(top: 6), - child: _buildExpandAddressWidget(typeReceiver, nameAddress)); - } else { - return Padding( - padding: EdgeInsets.only(top: 6), - child: _buildCollapseAddressWidget(typeReceiver, nameAddress)); - } - } - - Widget _buildAddressToReceiverWidget() { - return _buildAddressWidget( - AppLocalizations.of(_context).to_email_address_prefix, - _presentationEmail!.to.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)); - } - - Widget _buildAddressCcReceiverWidget() { - if (_presentationEmail!.to.numberEmailAddress() > 0) { - if (_expandMode == ExpandMode.EXPAND) { - return Padding( - padding: EdgeInsets.only(top: 6), - child: _buildExpandAddressWidget(AppLocalizations.of(_context).cc_email_address_prefix, _presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY))); - } else { - return SizedBox.shrink(); - } - } else { - return _buildAddressWidget( - AppLocalizations.of(_context).cc_email_address_prefix, - _presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)); - } - } - - Widget _buildAddressBccReceiverWidget() { - if (_presentationEmail!.to.numberEmailAddress() > 0) { - if (_expandMode == ExpandMode.EXPAND) { - return Padding( - padding: EdgeInsets.only(top: 6), - child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY))); - } else { - return SizedBox.shrink(); - } - } else { - if (_presentationEmail!.cc.numberEmailAddress() > 0) { - if (_expandMode == ExpandMode.EXPAND) { - return Padding( - padding: EdgeInsets.only(top: 6), - child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY))); - } else { - return SizedBox.shrink(); - } - } else { - return _buildAddressWidget( - AppLocalizations.of(_context).bcc_email_address_prefix, - _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)); - } - } - } - - String getRemainCountAddressReceiver() { - if (_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY >= 999) { - return '999'; - } - return '${_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY}'; - } - - Widget _buildButtonExpandAddress() { - return GestureDetector( - onTap: () { - if (_onOpenExpandAddressReceiverActionClick != null) { - _onOpenExpandAddressReceiverActionClick!(); - }}, - child: Row( - children: [ - SizedBox(width: 8), - Text( - '+${getRemainCountAddressReceiver()}', - style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500), - ), - SvgPicture.asset(_imagePaths.icMoreReceiver, width: 14, height: 14, fit: BoxFit.fill), - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/features/thread/presentation/widgets/email_tile_builder.dart b/lib/features/thread/presentation/widgets/email_tile_builder.dart index 2803f1313..ff8882a69 100644 --- a/lib/features/thread/presentation/widgets/email_tile_builder.dart +++ b/lib/features/thread/presentation/widgets/email_tile_builder.dart @@ -81,7 +81,7 @@ class EmailTileBuilder { if (_presentationEmail.isUnReadEmail()) Padding( padding: EdgeInsets.only(right: 5), - child: SvgPicture.asset(_imagePaths.icUnread, width: 9, height: 9, fit: BoxFit.fill)), + child: SvgPicture.asset(_imagePaths.icUnreadStatus, width: 9, height: 9, fit: BoxFit.fill)), Expanded( child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty ? RichTextBuilder( diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index eebc6d68e..c256b2937 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -755,4 +755,22 @@ class AppLocalizations { 'Hide', name: 'hide'); } + + String get copy_email_address { + return Intl.message( + 'Copy email address', + name: 'copy_email_address'); + } + + String get compose_email { + return Intl.message( + 'Compose email', + name: 'compose_email'); + } + + String get email_address_copied_to_clipboard { + return Intl.message( + 'Email address copied to clipboard', + name: 'email_address_copied_to_clipboard'); + } } \ No newline at end of file diff --git a/model/lib/email/email_action_type.dart b/model/lib/email/email_action_type.dart index 5fe47ad48..a6bfce7ac 100644 --- a/model/lib/email/email_action_type.dart +++ b/model/lib/email/email_action_type.dart @@ -13,4 +13,5 @@ enum EmailActionType { markAsSpam, delete, edit, + composeFromEmailAddress } \ No newline at end of file