Cherry pick commit fix issue #4292 to master (#4454)

* Add folder info when open mail list from Label

(cherry picked from commit de0bb4ee02030ca90126766a8713a6826d791acd)

* Add unit test for `hasMailboxLabel` function in BaseEmailItemTile mixin

(cherry picked from commit 18f8d1847acccd6f95006b93903f0caa6c0408df)

* TF-4292 Add E2E test for test case `Add folder info when open mail list from Label` on mobile

(cherry picked from commit 1c209e333510db161522e4449ad7fb2e5d28399f)
This commit is contained in:
Dat Vu
2026-04-16 15:45:45 +07:00
committed by GitHub
parent 6fc88f780c
commit c5eb4a011d
13 changed files with 288 additions and 107 deletions
@@ -19,7 +19,7 @@ import 'package:tmail_ui_user/features/labels/presentation/mixin/label_sub_menu_
import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/move_folder_content_state.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/presentation_label_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_ai_needs_action_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_open_context_menu_extension.dart';
@@ -530,6 +530,9 @@ class ThreadView extends GetWidget<ThreadController>
final isAINeedsActionEnabled = dashboardController.isAINeedsActionEnabled;
final isLabelMailboxOpened =
dashboardController.selectedMailbox.value?.isLabelMailbox == true;
return EmailTileBuilder(
key: Key('email_tile_builder_${presentationEmail.id?.asString}'),
presentationEmail: presentationEmail,
@@ -538,6 +541,7 @@ class ThreadView extends GetWidget<ThreadController>
searchQuery: controller.searchQuery,
mailboxContain: presentationEmail.mailboxContain,
isSearchEmailRunning: isSearchEmailRunning,
isLabelMailboxOpened: isLabelMailboxOpened,
isDrag: true,
isSenderImportantFlagEnabled: isSenderImportantFlagEnabled,
isAINeedsActionEnabled: isAINeedsActionEnabled,
@@ -546,70 +550,6 @@ class ThreadView extends GetWidget<ThreadController>
}
Widget _buildEmailItemNotDraggable(BuildContext context, PresentationEmail presentationEmail) {
final backgroundWidget = Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(start: 16),
alignment: AlignmentDirectional.centerStart,
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: !presentationEmail.hasRead
? SvgPicture.asset(
controller.imagePaths.icMarkAsRead,
fit: BoxFit.fill,
)
: SvgPicture.asset(
controller.imagePaths.icUnreadEmail,
fit: BoxFit.fill,
colorFilter: AppColor.primaryColor.asFilter(),
),
),
const SizedBox(width: 11),
Text(
!presentationEmail.hasRead
? AppLocalizations.of(context).mark_as_read
: AppLocalizations.of(context).mark_as_unread,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
);
final isInArchiveMailbox = controller.isInArchiveMailbox(presentationEmail);
final secondaryBackgroundWidget = !isInArchiveMailbox
? Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(end: 16),
alignment: AlignmentDirectional.centerEnd,
child: Row(
children: [
const Spacer(),
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: SvgPicture.asset(
controller.imagePaths.icMailboxArchived,
fit: BoxFit.fill,
),
),
const SizedBox(width: 11),
Text(
AppLocalizations.of(context).archiveMessage,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
)
: null;
final dashboardController = controller.mailboxDashBoardController;
return Obx(() {
@@ -629,14 +569,17 @@ class ThreadView extends GetWidget<ThreadController>
final isLabelAvailable = controller
.mailboxDashBoardController.isLabelAvailable;
final listLabels =
controller.mailboxDashBoardController.labelController.labels;
final listLabels =
controller.mailboxDashBoardController.labelController.labels;
List<Label>? emailLabels;
final isLabelMailboxOpened =
controller.selectedMailbox?.isLabelMailbox == true;
if (isLabelAvailable) {
emailLabels = presentationEmail.getLabelList(listLabels);
}
List<Label>? emailLabels;
if (isLabelAvailable) {
emailLabels = presentationEmail.getLabelList(listLabels);
}
return Dismissible(
key: ValueKey<EmailId?>(presentationEmail.id),
@@ -645,8 +588,10 @@ class ThreadView extends GetWidget<ThreadController>
selectModeAll,
presentationEmail
),
background: backgroundWidget,
secondaryBackground: secondaryBackgroundWidget,
background: _buildEmailSwipeBackground(context, presentationEmail),
secondaryBackground: controller.isInArchiveMailbox(presentationEmail)
? null
: _buildEmailSwipeSecondaryBackground(context),
confirmDismiss: (direction) => controller.swipeEmailAction(
presentationEmail,
direction,
@@ -661,6 +606,7 @@ class ThreadView extends GetWidget<ThreadController>
mailboxContain: presentationEmail.mailboxContain,
isSearchEmailRunning: isSearchEmailRunning,
isAINeedsActionEnabled: isAINeedsActionEnabled,
isLabelMailboxOpened: isLabelMailboxOpened,
labels: emailLabels,
emailActionClick: _handleEmailActionClicked,
onMoreActionClick: (email, position) async {
@@ -695,6 +641,65 @@ class ThreadView extends GetWidget<ThreadController>
});
}
Widget _buildEmailSwipeBackground(BuildContext context, PresentationEmail presentationEmail) {
return Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(start: 16),
alignment: AlignmentDirectional.centerStart,
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: !presentationEmail.hasRead
? SvgPicture.asset(controller.imagePaths.icMarkAsRead, fit: BoxFit.fill)
: SvgPicture.asset(
controller.imagePaths.icUnreadEmail,
fit: BoxFit.fill,
colorFilter: AppColor.primaryColor.asFilter(),
),
),
const SizedBox(width: 11),
Text(
!presentationEmail.hasRead
? AppLocalizations.of(context).mark_as_read
: AppLocalizations.of(context).mark_as_unread,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
);
}
Widget _buildEmailSwipeSecondaryBackground(BuildContext context) {
return Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(end: 16),
alignment: AlignmentDirectional.centerEnd,
child: Row(
children: [
const Spacer(),
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: SvgPicture.asset(controller.imagePaths.icMailboxArchived, fit: BoxFit.fill),
),
const SizedBox(width: 11),
Text(
AppLocalizations.of(context).archiveMessage,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
);
}
void _handleEmailActionClicked(
EmailActionType actionType,
PresentationEmail presentationEmail
@@ -772,8 +777,7 @@ class ThreadView extends GetWidget<ThreadController>
isFilterMessageActive: controller.mailboxDashBoardController.filterMessageOption.value != FilterMessageOption.all,
isFavoriteFolder: controller.selectedMailbox?.isFavorite == true,
isActionRequiredFolder: controller.selectedMailbox?.isActionRequired == true,
isLabelMailbox:
controller.selectedMailbox is PresentationLabelMailbox,
isLabelMailbox: controller.selectedMailbox?.isLabelMailbox == true,
),
);
}