From b3ce1f076c8cc98367fe9bac4ba2ccde62c02050 Mon Sep 17 00:00:00 2001 From: DatDang Date: Fri, 18 Jul 2025 10:34:08 +0700 Subject: [PATCH] TF-3881 Thread Detail Bottom sheet close when action TF-3881 Thread Detail Unsubscribe context menu TF-3881 Thread Detail Update date time format TF-3881 Thread Detail Update sender receiver spacing TF-3881 Thread Detail Add messageId and references to presentation email TF-3881 Thread Detail Filter created email on refresh TF-3881 Thread Detail Fix CI TF-3881 Thread Detail Fix previous action throws out of index TF-3881 Thread Detail Update sender receiver spacing TF-3881 Thread Detail Adjust email actions when expanded TF-3881 Thread Detail Adjust days ago received time TF-3881 Thread Detail Fix debouncer when update setting TF-3881 Thread Detail Adjust days ago received time TF-3881 Thread Detail Adjust email actions when expanded TF-3881 Thread Detail Hide next previous if not in range TF-3881 Thread Detail Arrange more action according to text direction TF-3881 Thread Detail Hide next previous if not in range TF-3881 Thread Detail Fix move email on tablet --- .../domain/extensions/datetime_extension.dart | 6 ++++- .../email/presentation/email_view.dart | 1 + .../email_action_reactor.dart | 1 + .../widgets/email_view_app_bar_widget.dart | 8 +++---- ...formation_sender_and_receiver_builder.dart | 14 +++++------ .../widgets/received_time_builder.dart | 2 ++ .../extensions/email_cache_extension.dart | 7 ++++++ .../data/extensions/email_extension.dart | 3 +++ .../thread/data/model/email_cache.dart | 15 ++++++++++++ .../domain/constants/thread_constants.dart | 1 + .../handle_refresh_thread_detail_action.dart | 18 ++++++++++++++- .../thread_detail_next_previous_actions.dart | 12 ++++++---- .../thread_detail_on_email_action_click.dart | 23 +++++++++---------- .../thread_detail_controller.dart | 4 +++- .../presentation/thread_detail_manager.dart | 9 -------- .../widgets/thread_detail_app_bar.dart | 6 ++++- model/lib/email/presentation_email.dart | 10 ++++++++ model/lib/extensions/email_extension.dart | 4 ++++ .../presentation_email_extension.dart | 2 ++ ...dle_refresh_thread_detail_action_test.dart | 5 ++++ 20 files changed, 108 insertions(+), 43 deletions(-) diff --git a/core/lib/domain/extensions/datetime_extension.dart b/core/lib/domain/extensions/datetime_extension.dart index 9dd32888a..ad709e8d2 100644 --- a/core/lib/domain/extensions/datetime_extension.dart +++ b/core/lib/domain/extensions/datetime_extension.dart @@ -50,7 +50,11 @@ extension DateTimeNullableExtension on DateTime? { } String toPatternForEmailView() { - return 'dd MMM yyyy, HH:mm a'; + if (this?.isThisYear() == true) { + return 'dd MMM, HH:mm a'; + } else { + return 'dd MMM yyyy, HH:mm a'; + } } String toPatternForPrinting(String locale) { diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index a234d48c2..7419f9365 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -316,6 +316,7 @@ class EmailView extends GetWidget { ), isOnlyEmailInThread: controller.isOnlyEmailInThread, )), + const SizedBox(height: 24), Obx(() => MailUnsubscribedBanner( presentationEmail: controller.currentEmail, emailUnsubscribe: controller.emailUnsubscribe.value diff --git a/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart b/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart index c8831d5b4..e6b5e39d3 100644 --- a/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart +++ b/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart @@ -597,6 +597,7 @@ class EmailActionReactor with MessageDialogActionMixin { ) .toList(), onContextMenuActionClick: (action) { + popBack(); handleEmailAction(presentationEmail, action.action); }, ); diff --git a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart index facf928d8..aa9be010a 100644 --- a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart +++ b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart @@ -264,15 +264,13 @@ class EmailViewAppBarWidget extends StatelessWidget { } return [ - if (!isOnlyEmailInThread) - _getReplyButton(appLocalizations), - if (!isResponsiveMobile) - _getMoveEmailButton(appLocalizations), + _getReplyButton(appLocalizations), if (isResponsiveDesktop) ...[ + _getMoveEmailButton(appLocalizations), _getMarkStarButton(appLocalizations), _getDeleteButton(appLocalizations), ], - if (onMoreActionClick != null) + if (!isOnlyEmailInThread) _getMoreButton(appLocalizations, isScreenWithShortestSide), ]; } diff --git a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart index 73d93dc9c..d645ba70a 100644 --- a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart +++ b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart @@ -68,7 +68,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsetsDirectional.symmetric(horizontal: 16), + padding: const EdgeInsetsDirectional.symmetric(horizontal: 16, vertical: 4), child: Row( crossAxisAlignment: emailSelected.countRecipients > 0 && (showRecipients || responsiveUtils.isMobile(context)) ? CrossAxisAlignment.start @@ -151,7 +151,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { ReceivedTimeBuilder( emailSelected: emailSelected, padding: const EdgeInsetsDirectional.only(start: 8, top: 2), - showDaysAgo: _showDaysAgo(responsiveUtils.isMobile(context)), + showDaysAgo: _showDaysAgo(responsiveUtils.isDesktop(context)), ), if (showUnreadVisualization && !emailSelected.hasRead && @@ -173,7 +173,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { ReceivedTimeBuilder( emailSelected: emailSelected, padding: const EdgeInsetsDirectional.only(start: 16, top: 2), - showDaysAgo: _showDaysAgo(responsiveUtils.isMobile(context)), + showDaysAgo: _showDaysAgo(responsiveUtils.isDesktop(context)), ), if (isInsideThreadDetailView) SizedBox( @@ -218,7 +218,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { ReceivedTimeBuilder( emailSelected: emailSelected, padding: const EdgeInsetsDirectional.symmetric(vertical: 5), - showDaysAgo: _showDaysAgo(responsiveUtils.isMobile(context)), + showDaysAgo: _showDaysAgo(responsiveUtils.isDesktop(context)), ), ], ), @@ -249,9 +249,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget { emailSelected.emailInThreadStatus == EmailInThreadStatus.collapsed; } - bool _showDaysAgo(bool isResponsiveMobile) { - return isInsideThreadDetailView && - emailSelected.emailInThreadStatus == EmailInThreadStatus.collapsed && - !isResponsiveMobile; + bool _showDaysAgo(bool isResponsiveDesktop) { + return isInsideThreadDetailView && isResponsiveDesktop; } } \ No newline at end of file diff --git a/lib/features/email/presentation/widgets/received_time_builder.dart b/lib/features/email/presentation/widgets/received_time_builder.dart index ca78edcf0..398d73da2 100644 --- a/lib/features/email/presentation/widgets/received_time_builder.dart +++ b/lib/features/email/presentation/widgets/received_time_builder.dart @@ -53,6 +53,8 @@ class ReceivedTimeBuilder extends StatelessWidget { if (from.isAfter(to)) return ''; final days = to.difference(from).inDays; + if (days >=7) return ''; + return appLocalizations.daysAgo(days); } } \ No newline at end of file diff --git a/lib/features/thread/data/extensions/email_cache_extension.dart b/lib/features/thread/data/extensions/email_cache_extension.dart index 3eca22cc3..136b6166f 100644 --- a/lib/features/thread/data/extensions/email_cache_extension.dart +++ b/lib/features/thread/data/extensions/email_cache_extension.dart @@ -52,6 +52,13 @@ extension EmailCacheExtension on EmailCache { priorityHeader!.keys.map((value) => IndividualHeaderIdentifier(value)), priorityHeader!.values) : null, + listUnsubscribeHeader: unsubscribeHeader != null + ? Map.fromIterables( + unsubscribeHeader!.keys.map((value) => IndividualHeaderIdentifier(value)), + unsubscribeHeader!.values) + : null, + messageId: messageId != null ? MessageIdsHeaderValue(messageId!.toSet()) : null, + references: references != null ? MessageIdsHeaderValue(references!.toSet()) : null, ); } diff --git a/lib/features/thread/data/extensions/email_extension.dart b/lib/features/thread/data/extensions/email_extension.dart index ba5b2181e..dba937394 100644 --- a/lib/features/thread/data/extensions/email_extension.dart +++ b/lib/features/thread/data/extensions/email_extension.dart @@ -30,6 +30,9 @@ extension EmailExtension on Email { xPriorityHeader: xPriorityHeader?.toMapString(), importanceHeader: importanceHeader?.toMapString(), priorityHeader: priorityHeader?.toMapString(), + unsubscribeHeader: listUnsubscribeHeader?.toMapString(), + messageId: messageId?.ids.toList(), + references: references?.ids.toList(), ); } diff --git a/lib/features/thread/data/model/email_cache.dart b/lib/features/thread/data/model/email_cache.dart index 5e903e353..82db7f29b 100644 --- a/lib/features/thread/data/model/email_cache.dart +++ b/lib/features/thread/data/model/email_cache.dart @@ -69,6 +69,15 @@ class EmailCache extends HiveObject with EquatableMixin { @HiveField(19) String? threadId; + @HiveField(20) + Map? unsubscribeHeader; + + @HiveField(21) + final List? messageId; + + @HiveField(22) + final List? references; + EmailCache( this.id, { @@ -91,6 +100,9 @@ class EmailCache extends HiveObject with EquatableMixin { this.importanceHeader, this.priorityHeader, this.threadId, + this.unsubscribeHeader, + this.messageId, + this.references, } ); @@ -116,5 +128,8 @@ class EmailCache extends HiveObject with EquatableMixin { importanceHeader, priorityHeader, threadId, + unsubscribeHeader, + messageId, + references, ]; } \ No newline at end of file diff --git a/lib/features/thread/domain/constants/thread_constants.dart b/lib/features/thread/domain/constants/thread_constants.dart index a001e4c3a..539d18425 100644 --- a/lib/features/thread/domain/constants/thread_constants.dart +++ b/lib/features/thread/domain/constants/thread_constants.dart @@ -26,6 +26,7 @@ class ThreadConstants { IndividualHeaderIdentifier.xPriorityHeader.value, IndividualHeaderIdentifier.importanceHeader.value, IndividualHeaderIdentifier.priorityHeader.value, + IndividualHeaderIdentifier.listUnsubscribeHeader.value, }); static final propertiesUpdatedDefault = propertiesDefault; diff --git a/lib/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart b/lib/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart index a652068ec..0a716d9fd 100644 --- a/lib/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart +++ b/lib/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart @@ -6,6 +6,7 @@ import 'package:model/extensions/email_extension.dart'; import 'package:model/extensions/keyword_identifier_extension.dart'; import 'package:model/extensions/list_email_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; +import 'package:tmail_ui_user/features/email/presentation/extensions/email_extension.dart'; import 'package:tmail_ui_user/features/thread_detail/domain/state/get_emails_by_ids_state.dart'; import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart'; import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.dart'; @@ -45,7 +46,10 @@ extension HandleRefreshThreadDetailAction on ThreadDetailController { action.emailChangeResponse.destroyed ?? const []); final emailsCreated = action.emailChangeResponse.created - ?.where((email) => email.threadId == currentThreadId) + ?.where((email) => validateNewCreatedEmailForCurrentThread( + email, + currentThreadId, + )) .map((email) => email.toPresentationEmail().copyWith( emailInThreadStatus: EmailInThreadStatus.collapsed, )) @@ -95,4 +99,16 @@ extension HandleRefreshThreadDetailAction on ThreadDetailController { ); } } + + bool validateNewCreatedEmailForCurrentThread( + Email email, + ThreadId currentThreadId, + ) { + return email.threadId == currentThreadId && + sentMailboxId != null && + !email.inSentMailbox(sentMailboxId!) && + ownEmailAddress != null && + !email.fromMe(ownEmailAddress!) && + !email.recipientsHasMe(ownEmailAddress!); + } } \ No newline at end of file diff --git a/lib/features/thread_detail/presentation/extension/thread_detail_next_previous_actions.dart b/lib/features/thread_detail/presentation/extension/thread_detail_next_previous_actions.dart index b91867bca..0fea9110f 100644 --- a/lib/features/thread_detail/presentation/extension/thread_detail_next_previous_actions.dart +++ b/lib/features/thread_detail/presentation/extension/thread_detail_next_previous_actions.dart @@ -7,8 +7,8 @@ import 'package:tmail_ui_user/main/routes/route_utils.dart'; extension ThreadDetailNextPreviousActions on ThreadDetailManager { bool get nextAvailable => isThreadDetailEnabled - ? currentThreadId != availableThreadIds.lastOrNull - : currentEmailId != currentDisplayedEmails.lastOrNull?.id; + ? currentThreadId != availableThreadIds.lastOrNull && availableThreadIds.contains(currentThreadId) + : currentEmailId != currentDisplayedEmails.lastOrNull?.id && currentDisplayedEmails.map((email) => email.id).contains(currentEmailId); void onNext() { if (!nextAvailable) return; @@ -23,8 +23,8 @@ extension ThreadDetailNextPreviousActions on ThreadDetailManager { } bool get previousAvailable => isThreadDetailEnabled - ? currentThreadId != availableThreadIds.firstOrNull - : currentEmailId != currentDisplayedEmails.firstOrNull?.id; + ? currentThreadId != availableThreadIds.firstOrNull && availableThreadIds.contains(currentThreadId) + : currentEmailId != currentDisplayedEmails.firstOrNull?.id && currentDisplayedEmails.map((email) => email.id).contains(currentEmailId); void onPrevious() { if (!previousAvailable) return; @@ -32,7 +32,9 @@ extension ThreadDetailNextPreviousActions on ThreadDetailManager { final currentIndex = isThreadDetailEnabled ? availableThreadIds.indexOf(currentThreadId!) : currentDisplayedEmails - .indexOf(mailboxDashBoardController.selectedEmail.value!); + .map((email) => email.id) + .toList() + .indexOf(mailboxDashBoardController.selectedEmail.value?.id); _navigate(currentIndex - 1, isThreadDetailEnabled); } diff --git a/lib/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart b/lib/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart index a26ab15c5..7787f4101 100644 --- a/lib/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart +++ b/lib/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart @@ -5,7 +5,6 @@ import 'package:model/email/email_action_type.dart'; import 'package:model/email/mark_star_action.dart'; import 'package:model/email/presentation_email.dart'; import 'package:model/email/read_actions.dart'; -import 'package:model/extensions/email_extension.dart'; import 'package:model/extensions/presentation_email_extension.dart'; import 'package:model/extensions/session_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; @@ -308,9 +307,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController { content: emailLoaded?.htmlContent, inlineImages: emailLoaded?.inlineImages, mailboxRole: presentationEmail.mailboxContain?.role, - messageId: emailLoaded?.emailCurrent?.messageId, - references: emailLoaded?.emailCurrent?.references, - listPost: emailLoaded?.emailCurrent?.listPost, + messageId: presentationEmail.messageId, + references: presentationEmail.references, + listPost: presentationEmail.listPost, ) ); }, @@ -328,9 +327,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController { content: emailLoaded?.htmlContent, inlineImages: emailLoaded?.inlineImages, mailboxRole: presentationEmail.mailboxContain?.role, - messageId: emailLoaded?.emailCurrent?.messageId, - references: emailLoaded?.emailCurrent?.references, - listPost: emailLoaded?.emailCurrent?.listPost, + messageId: presentationEmail.messageId, + references: presentationEmail.references, + listPost: presentationEmail.listPost, ) ); }, @@ -347,9 +346,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController { content: emailLoaded?.htmlContent, inlineImages: emailLoaded?.inlineImages, mailboxRole: presentationEmail.mailboxContain?.role, - messageId: emailLoaded?.emailCurrent?.messageId, - references: emailLoaded?.emailCurrent?.references, - listPost: emailLoaded?.emailCurrent?.listPost, + messageId: presentationEmail.messageId, + references: presentationEmail.references, + listPost: presentationEmail.listPost, ) ); }, @@ -366,8 +365,8 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController { content: emailLoaded?.htmlContent, attachments: emailLoaded?.attachments, inlineImages: emailLoaded?.inlineImages, - messageId: emailLoaded?.emailCurrent?.messageId, - references: emailLoaded?.emailCurrent?.references, + messageId: presentationEmail.messageId, + references: presentationEmail.references, ) ); }, diff --git a/lib/features/thread_detail/presentation/thread_detail_controller.dart b/lib/features/thread_detail/presentation/thread_detail_controller.dart index fcf09baa9..20f534af8 100644 --- a/lib/features/thread_detail/presentation/thread_detail_controller.dart +++ b/lib/features/thread_detail/presentation/thread_detail_controller.dart @@ -84,12 +84,14 @@ class ThreadDetailController extends BaseController { final additionalProperties = Properties({ IndividualHeaderIdentifier.listPostHeader.value, IndividualHeaderIdentifier.listUnsubscribeHeader.value, + EmailProperty.references, + EmailProperty.messageId, }); final cachedEmailLoaded = {}; late final _threadGetDebouncer = Debouncer( const Duration(milliseconds: 500), initialValue: null, - checkEquality: true, + checkEquality: false, onChanged: (threadId) { if (_validateLoadThread(threadId)) { consumeState(_getEmailIdsByThreadIdInteractor.execute( diff --git a/lib/features/thread_detail/presentation/thread_detail_manager.dart b/lib/features/thread_detail/presentation/thread_detail_manager.dart index 6b0a3393f..99221f533 100644 --- a/lib/features/thread_detail/presentation/thread_detail_manager.dart +++ b/lib/features/thread_detail/presentation/thread_detail_manager.dart @@ -69,15 +69,6 @@ class ThreadDetailManager extends BaseController { ThreadDetailUIAction(), ); }); - ever( - currentDisplayedEmails, - (emails) { - if (mailboxDashBoardController.dashboardRoute.value != DashboardRoutes.threadDetailed) { - return; - } - initializeThreadDetailManager(emails); - }, - ); ever( mailboxDashBoardController.dashboardRoute, (route) { diff --git a/lib/features/thread_detail/presentation/widgets/thread_detail_app_bar.dart b/lib/features/thread_detail/presentation/widgets/thread_detail_app_bar.dart index 3b334be37..fa2a4faa3 100644 --- a/lib/features/thread_detail/presentation/widgets/thread_detail_app_bar.dart +++ b/lib/features/thread_detail/presentation/widgets/thread_detail_app_bar.dart @@ -12,6 +12,7 @@ import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_app_bar_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_back_button.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +import 'package:tmail_ui_user/main/utils/app_utils.dart'; class ThreadDetailAppBar extends StatelessWidget { const ThreadDetailAppBar({ @@ -140,7 +141,10 @@ class ThreadDetailAppBar extends StatelessWidget { ], if (!responsiveUtils.isMobile(context)) const Spacer(), ] else const Spacer(), - ...optionWidgets, + if (AppUtils.getCurrentDirection(context) == TextDirection.rtl) + ...optionWidgets.reversed + else + ...optionWidgets, if (lastEmailOfThread != null) TMailButtonWidget.fromIcon( icon: imagePaths.icMoreVertical, diff --git a/model/lib/email/presentation_email.dart b/model/lib/email/presentation_email.dart index 312cf504e..89a55d296 100644 --- a/model/lib/email/presentation_email.dart +++ b/model/lib/email/presentation_email.dart @@ -54,6 +54,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { final Map? listPostHeader; final Map? listUnsubscribeHeader; final EmailInThreadStatus? emailInThreadStatus; + final MessageIdsHeaderValue? messageId; + final MessageIdsHeaderValue? references; PresentationEmail({ this.id, @@ -85,6 +87,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { this.listPostHeader, this.listUnsubscribeHeader, this.emailInThreadStatus, + this.messageId, + this.references, }); String getSenderName() { @@ -215,6 +219,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { listPostHeader, listUnsubscribeHeader, emailInThreadStatus, + messageId, + references, ]; PresentationEmail copyWith({ @@ -247,6 +253,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { Map? listPostHeader, Map? listUnsubscribeHeader, EmailInThreadStatus? emailInThreadStatus, + MessageIdsHeaderValue? messageId, + MessageIdsHeaderValue? references, }) { return PresentationEmail( id: id ?? this.id, @@ -278,6 +286,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin { listPostHeader: listPostHeader ?? this.listPostHeader, listUnsubscribeHeader: listUnsubscribeHeader ?? this.listUnsubscribeHeader, emailInThreadStatus: emailInThreadStatus ?? this.emailInThreadStatus, + messageId: messageId ?? this.messageId, + references: references ?? this.references, ); } } \ No newline at end of file diff --git a/model/lib/extensions/email_extension.dart b/model/lib/extensions/email_extension.dart index a993d43ab..6d4bb319a 100644 --- a/model/lib/extensions/email_extension.dart +++ b/model/lib/extensions/email_extension.dart @@ -131,6 +131,8 @@ extension EmailExtension on Email { priorityHeader: priorityHeader, listPostHeader: listPostHeader, listUnsubscribeHeader: listUnsubscribeHeader, + messageId: messageId, + references: references, ) ..searchSnippetSubject = searchSnippetSubject ..searchSnippetPreview = searchSnippetPreview; @@ -170,6 +172,8 @@ extension EmailExtension on Email { listUnsubscribeHeader: updatedProperties.contain(IndividualHeaderIdentifier.listUnsubscribeHeader.value) ? newEmail.listUnsubscribeHeader : listUnsubscribeHeader, + messageId: updatedProperties.contain(EmailProperty.messageId) ? newEmail.messageId : messageId, + references: updatedProperties.contain(EmailProperty.references) ? newEmail.references : references, ); } diff --git a/model/lib/extensions/presentation_email_extension.dart b/model/lib/extensions/presentation_email_extension.dart index f68a2818c..76d9c470c 100644 --- a/model/lib/extensions/presentation_email_extension.dart +++ b/model/lib/extensions/presentation_email_extension.dart @@ -114,6 +114,8 @@ extension PresentationEmailExtension on PresentationEmail { listPostHeader: listPostHeader, listUnsubscribeHeader: listUnsubscribeHeader, threadId: threadId, + messageId: messageId, + references: references, ); } diff --git a/test/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action_test.dart b/test/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action_test.dart index 7f3239858..760563b91 100644 --- a/test/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action_test.dart +++ b/test/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action_test.dart @@ -3,6 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:model/email/presentation_email.dart'; @@ -92,6 +93,10 @@ void main() { })); when(threadDetailController.isThreadDetailEnabled).thenReturn(true); when(threadDetailController.currentExpandedEmailId).thenReturn(Rxn()); + when(threadDetailController.sentMailboxId) + .thenReturn(MailboxId(Id('sent-mailbox-id'))); + when(threadDetailController.ownEmailAddress) + .thenReturn('9jEYK@example.com'); // act threadDetailController.handleRefreshThreadDetailAction(