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 {