TF-381 Apply new UI for emails selection active

This commit is contained in:
dab246
2022-03-22 00:57:24 +07:00
committed by Dat H. Pham
parent 61f3f0d00f
commit 7dc8672b82
7 changed files with 138 additions and 54 deletions
@@ -102,6 +102,7 @@ extension AppColor on Color {
static const colorButtonHeaderThread = Color(0x99EBEDF0);
static const colorBorderBodyThread = Color(0x5CB8C1CC);
static const colorBgDesktop = Color(0xFFF6F6F6);
static const colorItemEmailSelectedDesktop = Color(0x0F007AFF);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -41,6 +41,7 @@ class IconBuilder {
child: IconButton(
padding: EdgeInsets.zero,
iconSize: _size ?? 40,
splashRadius: 20,
icon: SvgPicture.asset(_icon!, width: _size ?? 40, height: _size ?? 40, fit: BoxFit.fill),
onPressed: () => {
if (_onPressIconActionClick != null) {
@@ -131,7 +131,6 @@ class ThreadController extends BaseController {
|| success is MarkAsStarEmailSuccess) {
cancelSelectEmail();
_refreshEmailChanges();
mailboxDashBoardController.clearState();
} else if (success is SearchEmailNewQuery){
_searchEmail();
mailboxDashBoardController.clearState();
@@ -225,6 +224,7 @@ class ThreadController extends BaseController {
canLoadMore = true;
disableSearch();
cancelSelectEmail();
mailboxDashBoardController.dispatchRoute(AppRoutes.THREAD);
}
void _getAllEmailSuccess(GetAllEmailSuccess success) {
@@ -388,7 +388,7 @@ class ThreadController extends BaseController {
currentSelectMode.value = SelectMode.ACTIVE;
}
List<PresentationEmail> getListEmailSelected() {
List<PresentationEmail> get listEmailSelected {
if (isSearchActive()) {
return emailListSearch.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
} else {
@@ -404,10 +404,6 @@ class ThreadController extends BaseController {
}
}
bool isAllEmailRead(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isReadEmail());
bool isAllEmailMarkAsStar(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isFlaggedEmail());
void cancelSelectEmail() {
if (isSearchActive()) {
emailListSearch.value = emailListSearch.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
@@ -422,7 +418,7 @@ class ThreadController extends BaseController {
popBack();
}
final readAction = isAllEmailRead(listPresentationEmail) ? ReadActions.markAsUnread : ReadActions.markAsRead;
final readAction = listPresentationEmail.isAllEmailRead ? ReadActions.markAsUnread : ReadActions.markAsRead;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (_accountId != null && mailboxCurrent != null) {
@@ -589,13 +585,20 @@ class ThreadController extends BaseController {
_refreshEmailChanges();
}
void markAsStarSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail, MarkStarAction markStarAction) {
popBack();
void markAsStarSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail,
{bool fromContextMenuAction = false, MarkStarAction? markStarAction}) {
if (fromContextMenuAction) {
popBack();
}
final starAction = markStarAction != null
? markStarAction
: listPresentationEmail.isAllEmailStarred ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (_accountId != null && mailboxCurrent != null) {
final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList();
consumeState(_markAsStarMultipleEmailInteractor.execute(_accountId!, listEmail, markStarAction));
consumeState(_markAsStarMultipleEmailInteractor.execute(_accountId!, listEmail, starAction));
}
}
@@ -697,6 +700,10 @@ class ThreadController extends BaseController {
case EmailActionType.markAsUnread:
markAsSelectedEmailRead(selectionEmail);
break;
case EmailActionType.markAsStar:
case EmailActionType.markAsUnStar:
markAsStarSelectedMultipleEmail(selectionEmail);
break;
case EmailActionType.move:
moveSelectedMultipleEmailToMailboxAction(selectionEmail);
break;
@@ -6,6 +6,7 @@ import 'package:get/get.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_more_email_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/extensions/filter_message_option_extension.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/bottom_bar_thread_selection_widget.dart';
@@ -74,7 +75,7 @@ class ThreadView extends GetWidget<ThreadController> {
],
))
),
Obx(() => controller.isSelectionEnabled()
Obx(() => controller.isSelectionEnabled() && !_responsiveUtils.isDesktop(context)
? Column(children: [
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
_buildOptionSelectionBottomBar(context)
@@ -110,6 +111,37 @@ class ThreadView extends GetWidget<ThreadController> {
}
Widget _buildHeader(BuildContext context) {
return Row(children: [
Obx(() => !controller.isSelectionEnabled() && _responsiveUtils.isDesktop(context)
? _buildOptionTopBar(context)
: SizedBox.shrink()),
Obx(() => controller.isSelectionEnabled() && _responsiveUtils.isDesktop(context)
? _buildOptionSelectionTopBar(context)
: SizedBox.shrink()),
SizedBox(width: 16),
Spacer(),
Padding(
padding: EdgeInsets.only(right: 16),
child: (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).search_emails)
..maxSizeWidth(240)
..addOnOpenSearchViewAction(() => controller.enableSearch(context)))
.build()),
Padding(
padding: EdgeInsets.only(right: 16),
child: (AvatarBuilder()
..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
..backgroundColor(Colors.white)
..textColor(Colors.black)
..addBoxShadows([BoxShadow(
color: AppColor.colorShadowBgContentEmail,
spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))])
..size(48))
.build()),
]);
}
Widget _buildOptionTopBar(BuildContext context) {
return Row(children: [
(ButtonBuilder(_imagePaths.icRefresh)
..key(Key('button_reload_thread'))
@@ -141,7 +173,15 @@ class ThreadView extends GetWidget<ThreadController> {
..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8))
..radiusSplash(10)
..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread))
..onPressActionClick(() => {})
..onPressActionClick(() {
final listEmail = controller.isSearchActive()
? controller.emailListSearch.allEmailUnread
: controller.emailList.allEmailUnread;
if (listEmail.isNotEmpty) {
controller.markAsSelectedEmailRead(listEmail);
}
})
..text(AppLocalizations.of(context).mark_all_as_read, isVertical: false))
.build(),
SizedBox(width: 16),
@@ -153,37 +193,53 @@ class ThreadView extends GetWidget<ThreadController> {
..size(16)
..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8))
..radiusSplash(10)
..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread))
..textStyle(TextStyle(
fontSize: 12,
color: controller.filterMessageOption.value == FilterMessageOption.all ? AppColor.colorTextButtonHeaderThread : AppColor.colorNameEmail,
fontWeight: controller.filterMessageOption.value == FilterMessageOption.all ? FontWeight.normal : FontWeight.w500))
..addIconAction(Padding(
padding: EdgeInsets.only(left: 8),
child: SvgPicture.asset(_imagePaths.icArrowDown, fit: BoxFit.fill)))
..addOnPressActionWithPositionClick((position) =>
controller.openFilterMessagesForTablet(
context,
position,
_popupMenuEmailActionTile(context, controller.filterMessageOption.value)))
..text(AppLocalizations.of(context).filter_messages, isVertical: false))
context,
position,
_popupMenuEmailActionTile(context, controller.filterMessageOption.value)))
..text(controller.filterMessageOption.value == FilterMessageOption.all
? AppLocalizations.of(context).filter_messages
: controller.filterMessageOption.value.getTitle(context), isVertical: false))
.build(),
SizedBox(width: 16),
Spacer(),
Padding(
padding: EdgeInsets.only(right: 16),
child: (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).search_emails)
..maxSizeWidth(240)
..addOnOpenSearchViewAction(() => controller.enableSearch(context)))
.build()),
Padding(
padding: EdgeInsets.only(right: 16),
child: (AvatarBuilder()
..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
..backgroundColor(Colors.white)
..textColor(Colors.black)
..addBoxShadows([BoxShadow(
color: AppColor.colorShadowBgContentEmail,
spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))])
..size(48))
.build()),
]);
}
Widget _buildOptionSelectionTopBar(BuildContext context) {
return Row(children: [
buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icCloseComposer, color: AppColor.colorTextButton, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).cancel,
onTap: () => controller.cancelSelectEmail()),
Text(
AppLocalizations.of(context).count_email_selected(controller.listEmailSelected.length),
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton),),
SizedBox(width: 30),
buildIconWeb(
icon: SvgPicture.asset(controller.listEmailSelected.isAllEmailRead ? _imagePaths.icUnread : _imagePaths.icRead, fit: BoxFit.fill),
tooltip: controller.listEmailSelected.isAllEmailRead ? AppLocalizations.of(context).unread : AppLocalizations.of(context).read,
onTap: () => controller.pressEmailSelectionAction(
context,
controller.listEmailSelected.isAllEmailRead ? EmailActionType.markAsUnread : EmailActionType.markAsRead,
controller.listEmailSelected)),
buildIconWeb(
icon: SvgPicture.asset(controller.listEmailSelected.isAllEmailStarred ? _imagePaths.icUnStar : _imagePaths.icStar, fit: BoxFit.fill),
tooltip: controller.listEmailSelected.isAllEmailStarred ? AppLocalizations.of(context).not_starred : AppLocalizations.of(context).starred,
onTap: () => controller.pressEmailSelectionAction(
context,
controller.listEmailSelected.isAllEmailStarred ? EmailActionType.markAsUnStar : EmailActionType.markAsStar,
controller.listEmailSelected)),
buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icMove, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).move,
onTap: () => controller.pressEmailSelectionAction(context, EmailActionType.move, controller.listEmailSelected)),
]);
}
@@ -194,7 +250,7 @@ class ThreadView extends GetWidget<ThreadController> {
context,
_imagePaths,
_responsiveUtils,
controller.getListEmailSelected())
controller.listEmailSelected)
..addOnPressEmailSelectionActionClick((actionType, selectionEmail) =>
controller.pressEmailSelectionAction(context, actionType, selectionEmail)))
.build());
@@ -223,7 +279,7 @@ class ThreadView extends GetWidget<ThreadController> {
_imagePaths,
_responsiveUtils,
controller.mailboxDashBoardController.selectedMailbox.value,
controller.getListEmailSelected(),
controller.listEmailSelected,
controller.currentSelectMode.value,
controller.filterMessageOption.value)
..addOpenListMailboxActionClick(() => controller.openMailboxLeftMenu())
@@ -59,7 +59,16 @@ class EmailTileBuilder {
child: ResponsiveWidget(
responsiveUtils: _responsiveUtils,
mobile: _buildListTile(),
desktop: _buildListTileForDesktop(),
desktop: Container(
margin: _selectModeAll == SelectMode.ACTIVE ? EdgeInsets.only(top: 3, left: 8, right: 8) : EdgeInsets.zero,
padding: _selectModeAll == SelectMode.ACTIVE ? EdgeInsets.symmetric(vertical: 10) : EdgeInsets.zero,
decoration: _selectModeAll == SelectMode.ACTIVE && _presentationEmail.selectMode == SelectMode.ACTIVE
? BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.colorItemEmailSelectedDesktop)
: null,
child: _buildListTileForDesktop(),
),
)
);
}
@@ -212,13 +221,12 @@ class EmailTileBuilder {
fit: BoxFit.fill),
tooltip: _presentationEmail.isFlaggedEmail() ? AppLocalizations.of(_context).starred : AppLocalizations.of(_context).not_starred,
onTap: () => _onMarkAsStarActionClick?.call(_presentationEmail)),
SizedBox(width: 8),
if (_selectModeAll == SelectMode.INACTIVE) SizedBox(width: 8),
_buildAvatarIcon(
iconSize: 32,
iconSizeSelect: 32,
textStyle: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white),
paddingIconSelect: EdgeInsets.all(5)),
SizedBox(width: 10),
if (_selectModeAll == SelectMode.INACTIVE) SizedBox(width: 10),
Container(width: 180, child: _isSearchEnabled
? RichTextBuilder(
_getInformationSender(),
@@ -277,18 +285,18 @@ class EmailTileBuilder {
child: Text('${_presentationEmail.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}',
maxLines: 1,
overflow: kIsWeb ? null: TextOverflow.ellipsis,
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))),
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal))),
]),
Padding(
padding: EdgeInsets.only(top: 10, bottom: 10, left: 70),
child: Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2)),
if (_selectModeAll == SelectMode.INACTIVE)
Padding(
padding: EdgeInsets.only(top: 10, bottom: 10, left: 70),
child: Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2)),
]),
);
}
Widget _buildAvatarIcon({
double? iconSize,
double? iconSizeSelect,
EdgeInsets? paddingIconSelect,
TextStyle? textStyle
}) {
@@ -296,14 +304,14 @@ class EmailTileBuilder {
return AnimatedSwitcher(
duration: Duration(milliseconds: 600),
transitionBuilder: _transitionBuilder,
child: (IconBuilder(_presentationEmail.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected)
..padding(paddingIconSelect ?? EdgeInsets.all(14))
..size(iconSize ?? (GetPlatform.isWeb ? 48 : 56))
..addOnTapActionClick(() {
child: buildIconWeb(
icon: SvgPicture.asset(_presentationEmail.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected, fit: BoxFit.fill),
iconPadding: paddingIconSelect ?? EdgeInsets.all(12),
tooltip: AppLocalizations.of(_context).select,
onTap: () {
if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) {
_onSelectEmailActionClick!(_presentationEmail);
}}))
.build()
}}),
);
} else {
return (AvatarBuilder()
@@ -855,4 +855,11 @@ class AppLocalizations {
name: 'not_starred'
);
}
String get select {
return Intl.message(
'Select',
name: 'select',
);
}
}
@@ -3,4 +3,8 @@ import 'package:model/email/presentation_email.dart';
extension ListPresentationEmailExtension on List<PresentationEmail> {
bool get isAllEmailRead => every((email) => email.isReadEmail());
bool get isAllEmailStarred => every((email) => email.isFlaggedEmail());
List<PresentationEmail> get allEmailUnread => where((email) => email.isUnReadEmail()).toList();
}