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:
@@ -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),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -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;
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -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
-5
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-12
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user