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
This commit is contained in:
DatDang
2025-07-18 10:34:08 +07:00
committed by Dat H. Pham
parent 51c5c7e13a
commit b3ce1f076c
20 changed files with 108 additions and 43 deletions
@@ -50,7 +50,11 @@ extension DateTimeNullableExtension on DateTime? {
} }
String toPatternForEmailView() { 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) { String toPatternForPrinting(String locale) {
@@ -316,6 +316,7 @@ class EmailView extends GetWidget<SingleEmailController> {
), ),
isOnlyEmailInThread: controller.isOnlyEmailInThread, isOnlyEmailInThread: controller.isOnlyEmailInThread,
)), )),
const SizedBox(height: 24),
Obx(() => MailUnsubscribedBanner( Obx(() => MailUnsubscribedBanner(
presentationEmail: controller.currentEmail, presentationEmail: controller.currentEmail,
emailUnsubscribe: controller.emailUnsubscribe.value emailUnsubscribe: controller.emailUnsubscribe.value
@@ -597,6 +597,7 @@ class EmailActionReactor with MessageDialogActionMixin {
) )
.toList(), .toList(),
onContextMenuActionClick: (action) { onContextMenuActionClick: (action) {
popBack();
handleEmailAction(presentationEmail, action.action); handleEmailAction(presentationEmail, action.action);
}, },
); );
@@ -264,15 +264,13 @@ class EmailViewAppBarWidget extends StatelessWidget {
} }
return [ return [
if (!isOnlyEmailInThread) _getReplyButton(appLocalizations),
_getReplyButton(appLocalizations),
if (!isResponsiveMobile)
_getMoveEmailButton(appLocalizations),
if (isResponsiveDesktop) ...[ if (isResponsiveDesktop) ...[
_getMoveEmailButton(appLocalizations),
_getMarkStarButton(appLocalizations), _getMarkStarButton(appLocalizations),
_getDeleteButton(appLocalizations), _getDeleteButton(appLocalizations),
], ],
if (onMoreActionClick != null) if (!isOnlyEmailInThread)
_getMoreButton(appLocalizations, isScreenWithShortestSide), _getMoreButton(appLocalizations, isScreenWithShortestSide),
]; ];
} }
@@ -68,7 +68,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 16), padding: const EdgeInsetsDirectional.symmetric(horizontal: 16, vertical: 4),
child: Row( child: Row(
crossAxisAlignment: emailSelected.countRecipients > 0 && (showRecipients || responsiveUtils.isMobile(context)) crossAxisAlignment: emailSelected.countRecipients > 0 && (showRecipients || responsiveUtils.isMobile(context))
? CrossAxisAlignment.start ? CrossAxisAlignment.start
@@ -151,7 +151,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
ReceivedTimeBuilder( ReceivedTimeBuilder(
emailSelected: emailSelected, emailSelected: emailSelected,
padding: const EdgeInsetsDirectional.only(start: 8, top: 2), padding: const EdgeInsetsDirectional.only(start: 8, top: 2),
showDaysAgo: _showDaysAgo(responsiveUtils.isMobile(context)), showDaysAgo: _showDaysAgo(responsiveUtils.isDesktop(context)),
), ),
if (showUnreadVisualization && if (showUnreadVisualization &&
!emailSelected.hasRead && !emailSelected.hasRead &&
@@ -173,7 +173,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
ReceivedTimeBuilder( ReceivedTimeBuilder(
emailSelected: emailSelected, emailSelected: emailSelected,
padding: const EdgeInsetsDirectional.only(start: 16, top: 2), padding: const EdgeInsetsDirectional.only(start: 16, top: 2),
showDaysAgo: _showDaysAgo(responsiveUtils.isMobile(context)), showDaysAgo: _showDaysAgo(responsiveUtils.isDesktop(context)),
), ),
if (isInsideThreadDetailView) if (isInsideThreadDetailView)
SizedBox( SizedBox(
@@ -218,7 +218,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
ReceivedTimeBuilder( ReceivedTimeBuilder(
emailSelected: emailSelected, emailSelected: emailSelected,
padding: const EdgeInsetsDirectional.symmetric(vertical: 5), 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; emailSelected.emailInThreadStatus == EmailInThreadStatus.collapsed;
} }
bool _showDaysAgo(bool isResponsiveMobile) { bool _showDaysAgo(bool isResponsiveDesktop) {
return isInsideThreadDetailView && return isInsideThreadDetailView && isResponsiveDesktop;
emailSelected.emailInThreadStatus == EmailInThreadStatus.collapsed &&
!isResponsiveMobile;
} }
} }
@@ -53,6 +53,8 @@ class ReceivedTimeBuilder extends StatelessWidget {
if (from.isAfter(to)) return ''; if (from.isAfter(to)) return '';
final days = to.difference(from).inDays; final days = to.difference(from).inDays;
if (days >=7) return '';
return appLocalizations.daysAgo(days); return appLocalizations.daysAgo(days);
} }
} }
@@ -52,6 +52,13 @@ extension EmailCacheExtension on EmailCache {
priorityHeader!.keys.map((value) => IndividualHeaderIdentifier(value)), priorityHeader!.keys.map((value) => IndividualHeaderIdentifier(value)),
priorityHeader!.values) priorityHeader!.values)
: null, : 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,
); );
} }
@@ -30,6 +30,9 @@ extension EmailExtension on Email {
xPriorityHeader: xPriorityHeader?.toMapString(), xPriorityHeader: xPriorityHeader?.toMapString(),
importanceHeader: importanceHeader?.toMapString(), importanceHeader: importanceHeader?.toMapString(),
priorityHeader: priorityHeader?.toMapString(), priorityHeader: priorityHeader?.toMapString(),
unsubscribeHeader: listUnsubscribeHeader?.toMapString(),
messageId: messageId?.ids.toList(),
references: references?.ids.toList(),
); );
} }
@@ -69,6 +69,15 @@ class EmailCache extends HiveObject with EquatableMixin {
@HiveField(19) @HiveField(19)
String? threadId; String? threadId;
@HiveField(20)
Map<String, String?>? unsubscribeHeader;
@HiveField(21)
final List<String>? messageId;
@HiveField(22)
final List<String>? references;
EmailCache( EmailCache(
this.id, this.id,
{ {
@@ -91,6 +100,9 @@ class EmailCache extends HiveObject with EquatableMixin {
this.importanceHeader, this.importanceHeader,
this.priorityHeader, this.priorityHeader,
this.threadId, this.threadId,
this.unsubscribeHeader,
this.messageId,
this.references,
} }
); );
@@ -116,5 +128,8 @@ class EmailCache extends HiveObject with EquatableMixin {
importanceHeader, importanceHeader,
priorityHeader, priorityHeader,
threadId, threadId,
unsubscribeHeader,
messageId,
references,
]; ];
} }
@@ -26,6 +26,7 @@ class ThreadConstants {
IndividualHeaderIdentifier.xPriorityHeader.value, IndividualHeaderIdentifier.xPriorityHeader.value,
IndividualHeaderIdentifier.importanceHeader.value, IndividualHeaderIdentifier.importanceHeader.value,
IndividualHeaderIdentifier.priorityHeader.value, IndividualHeaderIdentifier.priorityHeader.value,
IndividualHeaderIdentifier.listUnsubscribeHeader.value,
}); });
static final propertiesUpdatedDefault = propertiesDefault; static final propertiesUpdatedDefault = propertiesDefault;
@@ -6,6 +6,7 @@ import 'package:model/extensions/email_extension.dart';
import 'package:model/extensions/keyword_identifier_extension.dart'; import 'package:model/extensions/keyword_identifier_extension.dart';
import 'package:model/extensions/list_email_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/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_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/state/get_thread_by_id_state.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.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 []); action.emailChangeResponse.destroyed ?? const []);
final emailsCreated = action.emailChangeResponse.created final emailsCreated = action.emailChangeResponse.created
?.where((email) => email.threadId == currentThreadId) ?.where((email) => validateNewCreatedEmailForCurrentThread(
email,
currentThreadId,
))
.map((email) => email.toPresentationEmail().copyWith( .map((email) => email.toPresentationEmail().copyWith(
emailInThreadStatus: EmailInThreadStatus.collapsed, 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!);
}
} }
@@ -7,8 +7,8 @@ import 'package:tmail_ui_user/main/routes/route_utils.dart';
extension ThreadDetailNextPreviousActions on ThreadDetailManager { extension ThreadDetailNextPreviousActions on ThreadDetailManager {
bool get nextAvailable => isThreadDetailEnabled bool get nextAvailable => isThreadDetailEnabled
? currentThreadId != availableThreadIds.lastOrNull ? currentThreadId != availableThreadIds.lastOrNull && availableThreadIds.contains(currentThreadId)
: currentEmailId != currentDisplayedEmails.lastOrNull?.id; : currentEmailId != currentDisplayedEmails.lastOrNull?.id && currentDisplayedEmails.map((email) => email.id).contains(currentEmailId);
void onNext() { void onNext() {
if (!nextAvailable) return; if (!nextAvailable) return;
@@ -23,8 +23,8 @@ extension ThreadDetailNextPreviousActions on ThreadDetailManager {
} }
bool get previousAvailable => isThreadDetailEnabled bool get previousAvailable => isThreadDetailEnabled
? currentThreadId != availableThreadIds.firstOrNull ? currentThreadId != availableThreadIds.firstOrNull && availableThreadIds.contains(currentThreadId)
: currentEmailId != currentDisplayedEmails.firstOrNull?.id; : currentEmailId != currentDisplayedEmails.firstOrNull?.id && currentDisplayedEmails.map((email) => email.id).contains(currentEmailId);
void onPrevious() { void onPrevious() {
if (!previousAvailable) return; if (!previousAvailable) return;
@@ -32,7 +32,9 @@ extension ThreadDetailNextPreviousActions on ThreadDetailManager {
final currentIndex = isThreadDetailEnabled final currentIndex = isThreadDetailEnabled
? availableThreadIds.indexOf(currentThreadId!) ? availableThreadIds.indexOf(currentThreadId!)
: currentDisplayedEmails : currentDisplayedEmails
.indexOf(mailboxDashBoardController.selectedEmail.value!); .map((email) => email.id)
.toList()
.indexOf(mailboxDashBoardController.selectedEmail.value?.id);
_navigate(currentIndex - 1, isThreadDetailEnabled); _navigate(currentIndex - 1, isThreadDetailEnabled);
} }
@@ -5,7 +5,6 @@ import 'package:model/email/email_action_type.dart';
import 'package:model/email/mark_star_action.dart'; import 'package:model/email/mark_star_action.dart';
import 'package:model/email/presentation_email.dart'; import 'package:model/email/presentation_email.dart';
import 'package:model/email/read_actions.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/presentation_email_extension.dart';
import 'package:model/extensions/session_extension.dart'; import 'package:model/extensions/session_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
@@ -308,9 +307,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController {
content: emailLoaded?.htmlContent, content: emailLoaded?.htmlContent,
inlineImages: emailLoaded?.inlineImages, inlineImages: emailLoaded?.inlineImages,
mailboxRole: presentationEmail.mailboxContain?.role, mailboxRole: presentationEmail.mailboxContain?.role,
messageId: emailLoaded?.emailCurrent?.messageId, messageId: presentationEmail.messageId,
references: emailLoaded?.emailCurrent?.references, references: presentationEmail.references,
listPost: emailLoaded?.emailCurrent?.listPost, listPost: presentationEmail.listPost,
) )
); );
}, },
@@ -328,9 +327,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController {
content: emailLoaded?.htmlContent, content: emailLoaded?.htmlContent,
inlineImages: emailLoaded?.inlineImages, inlineImages: emailLoaded?.inlineImages,
mailboxRole: presentationEmail.mailboxContain?.role, mailboxRole: presentationEmail.mailboxContain?.role,
messageId: emailLoaded?.emailCurrent?.messageId, messageId: presentationEmail.messageId,
references: emailLoaded?.emailCurrent?.references, references: presentationEmail.references,
listPost: emailLoaded?.emailCurrent?.listPost, listPost: presentationEmail.listPost,
) )
); );
}, },
@@ -347,9 +346,9 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController {
content: emailLoaded?.htmlContent, content: emailLoaded?.htmlContent,
inlineImages: emailLoaded?.inlineImages, inlineImages: emailLoaded?.inlineImages,
mailboxRole: presentationEmail.mailboxContain?.role, mailboxRole: presentationEmail.mailboxContain?.role,
messageId: emailLoaded?.emailCurrent?.messageId, messageId: presentationEmail.messageId,
references: emailLoaded?.emailCurrent?.references, references: presentationEmail.references,
listPost: emailLoaded?.emailCurrent?.listPost, listPost: presentationEmail.listPost,
) )
); );
}, },
@@ -366,8 +365,8 @@ extension ThreadDetailOnEmailActionClick on ThreadDetailController {
content: emailLoaded?.htmlContent, content: emailLoaded?.htmlContent,
attachments: emailLoaded?.attachments, attachments: emailLoaded?.attachments,
inlineImages: emailLoaded?.inlineImages, inlineImages: emailLoaded?.inlineImages,
messageId: emailLoaded?.emailCurrent?.messageId, messageId: presentationEmail.messageId,
references: emailLoaded?.emailCurrent?.references, references: presentationEmail.references,
) )
); );
}, },
@@ -84,12 +84,14 @@ class ThreadDetailController extends BaseController {
final additionalProperties = Properties({ final additionalProperties = Properties({
IndividualHeaderIdentifier.listPostHeader.value, IndividualHeaderIdentifier.listPostHeader.value,
IndividualHeaderIdentifier.listUnsubscribeHeader.value, IndividualHeaderIdentifier.listUnsubscribeHeader.value,
EmailProperty.references,
EmailProperty.messageId,
}); });
final cachedEmailLoaded = <EmailId, EmailLoaded>{}; final cachedEmailLoaded = <EmailId, EmailLoaded>{};
late final _threadGetDebouncer = Debouncer<ThreadId?>( late final _threadGetDebouncer = Debouncer<ThreadId?>(
const Duration(milliseconds: 500), const Duration(milliseconds: 500),
initialValue: null, initialValue: null,
checkEquality: true, checkEquality: false,
onChanged: (threadId) { onChanged: (threadId) {
if (_validateLoadThread(threadId)) { if (_validateLoadThread(threadId)) {
consumeState(_getEmailIdsByThreadIdInteractor.execute( consumeState(_getEmailIdsByThreadIdInteractor.execute(
@@ -69,15 +69,6 @@ class ThreadDetailManager extends BaseController {
ThreadDetailUIAction(), ThreadDetailUIAction(),
); );
}); });
ever(
currentDisplayedEmails,
(emails) {
if (mailboxDashBoardController.dashboardRoute.value != DashboardRoutes.threadDetailed) {
return;
}
initializeThreadDetailManager(emails);
},
);
ever( ever(
mailboxDashBoardController.dashboardRoute, mailboxDashBoardController.dashboardRoute,
(route) { (route) {
@@ -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_app_bar_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_back_button.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/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/utils/app_utils.dart';
class ThreadDetailAppBar extends StatelessWidget { class ThreadDetailAppBar extends StatelessWidget {
const ThreadDetailAppBar({ const ThreadDetailAppBar({
@@ -140,7 +141,10 @@ class ThreadDetailAppBar extends StatelessWidget {
], ],
if (!responsiveUtils.isMobile(context)) const Spacer(), if (!responsiveUtils.isMobile(context)) const Spacer(),
] else const Spacer(), ] else const Spacer(),
...optionWidgets, if (AppUtils.getCurrentDirection(context) == TextDirection.rtl)
...optionWidgets.reversed
else
...optionWidgets,
if (lastEmailOfThread != null) if (lastEmailOfThread != null)
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: imagePaths.icMoreVertical, icon: imagePaths.icMoreVertical,
+10
View File
@@ -54,6 +54,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin {
final Map<IndividualHeaderIdentifier, String?>? listPostHeader; final Map<IndividualHeaderIdentifier, String?>? listPostHeader;
final Map<IndividualHeaderIdentifier, String?>? listUnsubscribeHeader; final Map<IndividualHeaderIdentifier, String?>? listUnsubscribeHeader;
final EmailInThreadStatus? emailInThreadStatus; final EmailInThreadStatus? emailInThreadStatus;
final MessageIdsHeaderValue? messageId;
final MessageIdsHeaderValue? references;
PresentationEmail({ PresentationEmail({
this.id, this.id,
@@ -85,6 +87,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin {
this.listPostHeader, this.listPostHeader,
this.listUnsubscribeHeader, this.listUnsubscribeHeader,
this.emailInThreadStatus, this.emailInThreadStatus,
this.messageId,
this.references,
}); });
String getSenderName() { String getSenderName() {
@@ -215,6 +219,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin {
listPostHeader, listPostHeader,
listUnsubscribeHeader, listUnsubscribeHeader,
emailInThreadStatus, emailInThreadStatus,
messageId,
references,
]; ];
PresentationEmail copyWith({ PresentationEmail copyWith({
@@ -247,6 +253,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin {
Map<IndividualHeaderIdentifier, String?>? listPostHeader, Map<IndividualHeaderIdentifier, String?>? listPostHeader,
Map<IndividualHeaderIdentifier, String?>? listUnsubscribeHeader, Map<IndividualHeaderIdentifier, String?>? listUnsubscribeHeader,
EmailInThreadStatus? emailInThreadStatus, EmailInThreadStatus? emailInThreadStatus,
MessageIdsHeaderValue? messageId,
MessageIdsHeaderValue? references,
}) { }) {
return PresentationEmail( return PresentationEmail(
id: id ?? this.id, id: id ?? this.id,
@@ -278,6 +286,8 @@ class PresentationEmail with EquatableMixin, SearchSnippetMixin {
listPostHeader: listPostHeader ?? this.listPostHeader, listPostHeader: listPostHeader ?? this.listPostHeader,
listUnsubscribeHeader: listUnsubscribeHeader ?? this.listUnsubscribeHeader, listUnsubscribeHeader: listUnsubscribeHeader ?? this.listUnsubscribeHeader,
emailInThreadStatus: emailInThreadStatus ?? this.emailInThreadStatus, emailInThreadStatus: emailInThreadStatus ?? this.emailInThreadStatus,
messageId: messageId ?? this.messageId,
references: references ?? this.references,
); );
} }
} }
@@ -131,6 +131,8 @@ extension EmailExtension on Email {
priorityHeader: priorityHeader, priorityHeader: priorityHeader,
listPostHeader: listPostHeader, listPostHeader: listPostHeader,
listUnsubscribeHeader: listUnsubscribeHeader, listUnsubscribeHeader: listUnsubscribeHeader,
messageId: messageId,
references: references,
) )
..searchSnippetSubject = searchSnippetSubject ..searchSnippetSubject = searchSnippetSubject
..searchSnippetPreview = searchSnippetPreview; ..searchSnippetPreview = searchSnippetPreview;
@@ -170,6 +172,8 @@ extension EmailExtension on Email {
listUnsubscribeHeader: updatedProperties.contain(IndividualHeaderIdentifier.listUnsubscribeHeader.value) listUnsubscribeHeader: updatedProperties.contain(IndividualHeaderIdentifier.listUnsubscribeHeader.value)
? newEmail.listUnsubscribeHeader ? newEmail.listUnsubscribeHeader
: listUnsubscribeHeader, : listUnsubscribeHeader,
messageId: updatedProperties.contain(EmailProperty.messageId) ? newEmail.messageId : messageId,
references: updatedProperties.contain(EmailProperty.references) ? newEmail.references : references,
); );
} }
@@ -114,6 +114,8 @@ extension PresentationEmailExtension on PresentationEmail {
listPostHeader: listPostHeader, listPostHeader: listPostHeader,
listUnsubscribeHeader: listUnsubscribeHeader, listUnsubscribeHeader: listUnsubscribeHeader,
threadId: threadId, threadId: threadId,
messageId: messageId,
references: references,
); );
} }
@@ -3,6 +3,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/core/id.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/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:mockito/annotations.dart'; import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:model/email/presentation_email.dart'; import 'package:model/email/presentation_email.dart';
@@ -92,6 +93,10 @@ void main() {
})); }));
when(threadDetailController.isThreadDetailEnabled).thenReturn(true); when(threadDetailController.isThreadDetailEnabled).thenReturn(true);
when(threadDetailController.currentExpandedEmailId).thenReturn(Rxn()); when(threadDetailController.currentExpandedEmailId).thenReturn(Rxn());
when(threadDetailController.sentMailboxId)
.thenReturn(MailboxId(Id('sent-mailbox-id')));
when(threadDetailController.ownEmailAddress)
.thenReturn('9jEYK@example.com');
// act // act
threadDetailController.handleRefreshThreadDetailAction( threadDetailController.handleRefreshThreadDetailAction(