From 43554e26ca14d45cabfd15d34db547b05ebe7f2a Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Tue, 11 Apr 2023 17:08:15 +0700 Subject: [PATCH] TF-1100: Support display answered and forwarded (cherry picked from commit cb67c81998264efbb75ae4543621a20522f3dbc4) --- assets/images/ic_forwarded.svg | 3 ++ assets/images/ic_reply_and_forward.svg | 4 ++ .../presentation/resources/image_paths.dart | 2 + .../composer/domain/model/email_request.dart | 12 ++++- .../presentation/composer_controller.dart | 3 +- .../email/data/network/email_api.dart | 4 +- .../mixin/base_email_item_tile.dart | 54 +++++++++++++++++++ .../widgets/email_tile_builder.dart | 1 + .../widgets/email_tile_web_builder.dart | 9 +++- lib/main/localizations/app_localizations.dart | 18 +++++++ model/lib/email/presentation_email.dart | 6 +++ 11 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 assets/images/ic_forwarded.svg create mode 100644 assets/images/ic_reply_and_forward.svg diff --git a/assets/images/ic_forwarded.svg b/assets/images/ic_forwarded.svg new file mode 100644 index 000000000..02d03edc3 --- /dev/null +++ b/assets/images/ic_forwarded.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/ic_reply_and_forward.svg b/assets/images/ic_reply_and_forward.svg new file mode 100644 index 000000000..946753f15 --- /dev/null +++ b/assets/images/ic_reply_and_forward.svg @@ -0,0 +1,4 @@ + + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index b64bb10ea..73adbba3f 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -177,6 +177,8 @@ class ImagePaths { String get icShowMailbox => _getImagePath('ic_show_mailbox.svg'); String get icMailboxVisibility => _getImagePath('ic_mailbox_visibility.svg'); String get icToastSuccessMessage => _getImagePath('ic_toast_success_message.svg'); + String get icForwarded => _getImagePath('ic_forwarded.svg'); + String get icReplyAndForward => _getImagePath('ic_reply_and_forward.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/composer/domain/model/email_request.dart b/lib/features/composer/domain/model/email_request.dart index b4ac81c6a..513239400 100644 --- a/lib/features/composer/domain/model/email_request.dart +++ b/lib/features/composer/domain/model/email_request.dart @@ -4,6 +4,7 @@ import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/email/email_action_type.dart'; class EmailRequest with EquatableMixin { @@ -12,11 +13,13 @@ class EmailRequest with EquatableMixin { final MailboxId? sentMailboxId; final EmailId? emailIdDestroyed; final Identity? identity; + final EmailActionType? emailActionType; EmailRequest(this.email, this.submissionCreateId, { this.sentMailboxId, this.identity, - this.emailIdDestroyed + this.emailIdDestroyed, + this.emailActionType }); @override @@ -25,6 +28,11 @@ class EmailRequest with EquatableMixin { submissionCreateId, sentMailboxId, identity, - emailIdDestroyed + emailIdDestroyed, + emailActionType ]; + + bool get isEmailAnswered => emailActionType == EmailActionType.reply; + + bool get isEmailForwarded => emailActionType == EmailActionType.forward; } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 4844177c4..b52ca73ec 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -806,7 +806,8 @@ class ComposerController extends BaseController { identity: identitySelected.value, emailIdDestroyed: arguments.emailActionType == EmailActionType.edit ? arguments.presentationEmail?.id - : null + : null, + emailActionType: arguments.emailActionType ); final mailboxRequest = outboxMailboxId == null ? CreateNewMailboxRequest(Id(_uuid.v1()), PresentationMailbox.outboxMailboxName) diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 8275391f9..d0d7e4684 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -159,7 +159,9 @@ class EmailAPI with HandleSetErrorMixin { emailRequest.sentMailboxId!.generatePath() : true, outboxMailboxId!.generatePath() : null, KeyWordIdentifier.emailSeen.generatePath(): true, - KeyWordIdentifier.emailDraft.generatePath(): null + KeyWordIdentifier.emailDraft.generatePath(): null, + KeyWordIdentifier.emailAnswered.generatePath(): emailRequest.isEmailAnswered ? true : null, + KeyWordIdentifier.emailForwarded.generatePath(): emailRequest.isEmailForwarded ? true : null }) }); diff --git a/lib/features/thread/presentation/mixin/base_email_item_tile.dart b/lib/features/thread/presentation/mixin/base_email_item_tile.dart index d1ad35349..da339fe6c 100644 --- a/lib/features/thread/presentation/mixin/base_email_item_tile.dart +++ b/lib/features/thread/presentation/mixin/base_email_item_tile.dart @@ -14,6 +14,7 @@ import 'package:model/extensions/presentation_email_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; typedef OnPressEmailActionClick = void Function(EmailActionType, PresentationEmail); typedef OnMoreActionClick = void Function(PresentationEmail, RelativeRect?); @@ -274,4 +275,57 @@ mixin BaseEmailItemTile { width: 24, height: 24)); } } + + Widget buildIconAnsweredOrForwarded({ + required PresentationEmail presentationEmail, + double? width, + double? height + }) { + if (presentationEmail.isAnsweredAndForwarded) { + return _iconAnsweredOrForwardedWidget( + iconPath: imagePaths.icReplyAndForward, + width: width, + height: height + ); + } else if (presentationEmail.isAnswered) { + return _iconAnsweredOrForwardedWidget( + iconPath: imagePaths.icReply, + width: width, + height: height + ); + } else if (presentationEmail.isForwarded) { + return _iconAnsweredOrForwardedWidget( + iconPath: imagePaths.icForwarded, + width: width, + height: height + ); + } else { + return const SizedBox(width: 16, height: 16); + } + } + + Widget _iconAnsweredOrForwardedWidget({ + required String iconPath, + double? width, + double? height + }) { + return SvgPicture.asset( + iconPath, + width: width ?? 20, + height: height ?? 20, + colorFilter: AppColor.colorAttachmentIcon.asFilter(), + fit: BoxFit.fill); + } + + String? messageToolTipForAnsweredOrForwarded(BuildContext context, PresentationEmail presentationEmail) { + if (presentationEmail.isAnsweredAndForwarded) { + return AppLocalizations.of(context).repliedAndForwardedMessage; + } else if (presentationEmail.isAnswered) { + return AppLocalizations.of(context).repliedMessage; + } else if (presentationEmail.isForwarded){ + return AppLocalizations.of(context).forwardedMessage; + } else { + return null; + } + } } \ 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 71159dd30..f1c8eb60a 100644 --- a/lib/features/thread/presentation/widgets/email_tile_builder.dart +++ b/lib/features/thread/presentation/widgets/email_tile_builder.dart @@ -86,6 +86,7 @@ class EmailTileBuilder with BaseEmailItemTile { mailboxContain, isSearchEmailRunning, _searchQuery)), + buildIconAnsweredOrForwarded(width: 16, height: 16, presentationEmail: _presentationEmail), if (_presentationEmail.hasAttachment == true) Padding( padding: const EdgeInsets.only(left: 8), diff --git a/lib/features/thread/presentation/widgets/email_tile_web_builder.dart b/lib/features/thread/presentation/widgets/email_tile_web_builder.dart index c8d551f9a..beba668a5 100644 --- a/lib/features/thread/presentation/widgets/email_tile_web_builder.dart +++ b/lib/features/thread/presentation/widgets/email_tile_web_builder.dart @@ -153,6 +153,7 @@ class EmailTileBuilder with BaseEmailItemTile { isSearchEmailRunning, _searchQuery )), + buildIconAnsweredOrForwarded(width: 16, height: 16, presentationEmail: _presentationEmail), if (_presentationEmail.hasAttachment == true) Padding( padding: const EdgeInsets.only(left: 8), @@ -345,6 +346,11 @@ class EmailTileBuilder with BaseEmailItemTile { ? EmailActionType.unMarkAsStarred : EmailActionType.markAsStarred, _presentationEmail)), + buildIconWeb( + icon: buildIconAnsweredOrForwarded(presentationEmail: _presentationEmail), + tooltip: messageToolTipForAnsweredOrForwarded(context, _presentationEmail), + iconPadding: const EdgeInsets.only(right: 12), + splashRadius: 1), InkWell( onTap: () { if (isHoverIcon) { @@ -382,7 +388,7 @@ class EmailTileBuilder with BaseEmailItemTile { Transform( transform: Matrix4.translationValues(0.0, 10, 0.0), child: const Padding( - padding: EdgeInsets.only(left: 80), + padding: EdgeInsets.only(left: 120), child: Divider( color: AppColor.lineItemListColor, height: 1, @@ -497,6 +503,7 @@ class EmailTileBuilder with BaseEmailItemTile { Widget _buildDateTimeForMobileTabletScreen() { return Row(children: [ + buildIconAnsweredOrForwarded(width: 16, height: 16, presentationEmail: _presentationEmail), if (_presentationEmail.hasAttachment == true) Padding( padding: const EdgeInsets.only(left: 8), diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 384b9d02f..c67ca4a01 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -2833,4 +2833,22 @@ class AppLocalizations { 'Please input at least one recipient', name: 'emptyListEmailForward'); } + + String get forwardedMessage { + return Intl.message( + 'Forwarded message', + name: 'forwardedMessage'); + } + + String get repliedMessage { + return Intl.message( + 'Replied message', + name: 'repliedMessage'); + } + + String get repliedAndForwardedMessage { + return Intl.message( + 'Replied and Forwarded message', + name: 'repliedAndForwardedMessage'); + } } \ No newline at end of file diff --git a/model/lib/email/presentation_email.dart b/model/lib/email/presentation_email.dart index a455b6d6d..afbf074fb 100644 --- a/model/lib/email/presentation_email.dart +++ b/model/lib/email/presentation_email.dart @@ -78,6 +78,12 @@ class PresentationEmail with EquatableMixin { bool get isDraft => keywords?.containsKey(KeyWordIdentifier.emailDraft) == true; + bool get isAnswered => keywords?.containsKey(KeyWordIdentifier.emailAnswered) == true; + + bool get isForwarded => keywords?.containsKey(KeyWordIdentifier.emailForwarded) == true; + + bool get isAnsweredAndForwarded => isAnswered && isForwarded; + bool get withAttachments => hasAttachment == true; String get mailboxName {