TF-119 Filter messages with unread, attachments, starred
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
enum FilterMessageOption {
|
||||
all,
|
||||
unread,
|
||||
attachments,
|
||||
starred,
|
||||
}
|
||||
|
||||
extension FilterMessageOptionExtension on FilterMessageOption {
|
||||
|
||||
bool filterEmail(PresentationEmail email) {
|
||||
switch(this) {
|
||||
case FilterMessageOption.all:
|
||||
return true;
|
||||
case FilterMessageOption.unread:
|
||||
return email.isUnReadEmail();
|
||||
case FilterMessageOption.attachments:
|
||||
return email.withAttachments;
|
||||
case FilterMessageOption.starred:
|
||||
return email.isFlaggedEmail();
|
||||
}
|
||||
}
|
||||
|
||||
String getIconToast(ImagePaths imagePaths) {
|
||||
switch(this) {
|
||||
case FilterMessageOption.all:
|
||||
return imagePaths.icFilterMessageAll;
|
||||
case FilterMessageOption.unread:
|
||||
return imagePaths.icUnreadToast;
|
||||
case FilterMessageOption.attachments:
|
||||
return imagePaths.icFilterMessageAttachments;
|
||||
case FilterMessageOption.starred:
|
||||
return imagePaths.icStar;
|
||||
}
|
||||
}
|
||||
|
||||
String getMessageToast(BuildContext context) {
|
||||
switch(this) {
|
||||
case FilterMessageOption.all:
|
||||
return AppLocalizations.of(context).disable_filter_message_toast;
|
||||
case FilterMessageOption.unread:
|
||||
return AppLocalizations.of(context).filter_message_toast(AppLocalizations.of(context).unread);
|
||||
case FilterMessageOption.attachments:
|
||||
return AppLocalizations.of(context).filter_message_toast(AppLocalizations.of(context).with_attachments);
|
||||
case FilterMessageOption.starred:
|
||||
return AppLocalizations.of(context).filter_message_toast(AppLocalizations.of(context).starred);
|
||||
}
|
||||
}
|
||||
|
||||
String getTitle(BuildContext context) {
|
||||
switch(this) {
|
||||
case FilterMessageOption.all:
|
||||
return '';
|
||||
case FilterMessageOption.unread:
|
||||
return AppLocalizations.of(context).with_unread;
|
||||
case FilterMessageOption.attachments:
|
||||
return AppLocalizations.of(context).with_attachments.capitalizeFirstEach;
|
||||
case FilterMessageOption.starred:
|
||||
return AppLocalizations.of(context).with_starred;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multi
|
||||
import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/usecases/search_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/usecases/search_more_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/model/filter_message_option.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
@@ -63,7 +64,9 @@ class ThreadController extends BaseController {
|
||||
|
||||
final emailList = <PresentationEmail>[].obs;
|
||||
final emailListSearch = <PresentationEmail>[].obs;
|
||||
final emailListFiltered = <PresentationEmail>[].obs;
|
||||
final currentSelectMode = SelectMode.INACTIVE.obs;
|
||||
final filterMessageOption = FilterMessageOption.all.obs;
|
||||
|
||||
final random = Random();
|
||||
|
||||
@@ -204,7 +207,8 @@ class ThreadController extends BaseController {
|
||||
|
||||
void _resetToOriginalValue() {
|
||||
dispatchState(Right(LoadingState()));
|
||||
emailList.value = <PresentationEmail>[];
|
||||
emailList.clear();
|
||||
emailListFiltered.clear();
|
||||
canLoadMore = true;
|
||||
disableSearch();
|
||||
cancelSelectEmail();
|
||||
@@ -216,6 +220,12 @@ class ThreadController extends BaseController {
|
||||
.map((email) => email.asAvatarGradientColor(random))
|
||||
.toList();
|
||||
emailList.value = listEmailHaveAvatarGradientColor;
|
||||
if (isFilterMessagesEnabled) {
|
||||
final emailsFiltered = listEmailHaveAvatarGradientColor
|
||||
.where((email) => filterMessageOption.value.filterEmail(email))
|
||||
.toList();
|
||||
emailListFiltered.addAll(emailsFiltered);
|
||||
}
|
||||
}
|
||||
|
||||
void _getAllEmailAction(AccountId accountId, {MailboxId? mailboxId}) {
|
||||
@@ -283,6 +293,13 @@ class ThreadController extends BaseController {
|
||||
.map((email) => email.asAvatarGradientColor(random))
|
||||
.toList();
|
||||
emailList.addAll(listEmailHaveAvatarGradientColor);
|
||||
|
||||
if (isFilterMessagesEnabled) {
|
||||
final emailsFilteredMore = listEmailHaveAvatarGradientColor
|
||||
.where((email) => filterMessageOption.value.filterEmail(email))
|
||||
.toList();
|
||||
emailListFiltered.addAll(emailsFilteredMore);
|
||||
}
|
||||
} else {
|
||||
canLoadMore = false;
|
||||
}
|
||||
@@ -307,9 +324,15 @@ class ThreadController extends BaseController {
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
} else {
|
||||
emailList.value = emailList
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
if (isFilterMessagesEnabled) {
|
||||
emailListFiltered.value = emailListFiltered
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
} else {
|
||||
emailList.value = emailList
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
if (_isUnSelectedAll()) {
|
||||
@@ -329,7 +352,11 @@ class ThreadController extends BaseController {
|
||||
if (isSearchActive()) {
|
||||
return emailListSearch.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
|
||||
} else {
|
||||
return emailList.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
|
||||
if (isFilterMessagesEnabled) {
|
||||
return emailListFiltered.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
|
||||
} else {
|
||||
return emailList.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +364,11 @@ class ThreadController extends BaseController {
|
||||
if (isSearchActive()) {
|
||||
return emailListSearch.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
} else {
|
||||
return emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
if (isFilterMessagesEnabled) {
|
||||
return emailListFiltered.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
} else {
|
||||
return emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +380,11 @@ class ThreadController extends BaseController {
|
||||
if (isSearchActive()) {
|
||||
emailListSearch.value = emailListSearch.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
|
||||
} else {
|
||||
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
|
||||
if (isFilterMessagesEnabled) {
|
||||
emailListFiltered.value = emailListFiltered.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
|
||||
} else {
|
||||
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
|
||||
}
|
||||
}
|
||||
currentSelectMode.value = SelectMode.INACTIVE;
|
||||
}
|
||||
@@ -397,6 +432,35 @@ class ThreadController extends BaseController {
|
||||
_appToast.showErrorToast(AppLocalizations.of(Get.context!).an_error_occurred);
|
||||
}
|
||||
|
||||
void openFilterMessagesCupertinoActionSheet(BuildContext context, List<Widget> actionTiles, {Widget? cancelButton}) {
|
||||
(CupertinoActionSheetBuilder(context)
|
||||
..addTiles(actionTiles)
|
||||
..addCancelButton(cancelButton))
|
||||
.build();
|
||||
}
|
||||
|
||||
void closeFilterMessageActionSheet() {
|
||||
popBack();
|
||||
}
|
||||
|
||||
bool get isFilterMessagesEnabled => filterMessageOption != FilterMessageOption.all;
|
||||
|
||||
void filterMessagesAction(BuildContext context, FilterMessageOption filterOption) {
|
||||
popBack();
|
||||
|
||||
final newFilterOption = filterMessageOption.value == filterOption ? FilterMessageOption.all : filterOption;
|
||||
|
||||
final emailsFiltered = emailList.where((email) => newFilterOption.filterEmail(email)).toList();
|
||||
emailListFiltered.value = emailsFiltered;
|
||||
|
||||
filterMessageOption.value = newFilterOption;
|
||||
|
||||
_appToast.showToastWithIcon(
|
||||
Get.overlayContext!,
|
||||
message: newFilterOption.getMessageToast(context),
|
||||
icon: newFilterOption.getIconToast(_imagePaths));
|
||||
}
|
||||
|
||||
void openContextMenuSelectedEmail(BuildContext context, List<Widget> actionTiles) {
|
||||
(ContextMenuBuilder(context)
|
||||
..addTiles(actionTiles))
|
||||
@@ -573,7 +637,7 @@ class ThreadController extends BaseController {
|
||||
|
||||
void _searchEmailsSuccess(SearchEmailSuccess success) {
|
||||
final resultEmailSearchList = success.emailList
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailbox))
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailbox, random))
|
||||
.toList();
|
||||
|
||||
emailListSearch.value = resultEmailSearchList;
|
||||
@@ -597,7 +661,7 @@ class ThreadController extends BaseController {
|
||||
void _searchMoreEmailsSuccess(SearchMoreEmailSuccess success) {
|
||||
if (success.emailList.isNotEmpty) {
|
||||
final resultEmailSearchList = success.emailList
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailbox))
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailbox, random))
|
||||
.where((email) => !emailListSearch.contains(email))
|
||||
.toList();
|
||||
emailListSearch.addAll(resultEmailSearchList);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
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/model/filter_message_option.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';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/filter_message_cupertino_action_sheet_action_builder.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_bar_thread_view_widget.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/suggestion_box_widget.dart';
|
||||
@@ -146,13 +149,72 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
responsiveUtils,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
controller.getListEmailSelected(),
|
||||
controller.currentSelectMode.value)
|
||||
controller.currentSelectMode.value,
|
||||
controller.filterMessageOption.value)
|
||||
..addOpenListMailboxActionClick(() => controller.openMailboxLeftMenu())
|
||||
..addOnEditThreadAction(() => controller.enableSelectionEmail())
|
||||
..addOnFilterEmailAction((filterMessageOption) =>
|
||||
controller.openFilterMessagesCupertinoActionSheet(
|
||||
context,
|
||||
_filterMessagesCupertinoActionTile(context, filterMessageOption),
|
||||
cancelButton: _buildCupertinoActionCancelButton(context)))
|
||||
..addOnCancelEditThread(() => controller.cancelSelectEmail()))
|
||||
.build();
|
||||
}
|
||||
|
||||
List<Widget> _filterMessagesCupertinoActionTile(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return <Widget>[
|
||||
_filterMessageWithAttachmentsAction(context, optionCurrent),
|
||||
_filterMessagesUnreadAction(context, optionCurrent),
|
||||
_filterMessageStarredAction(context, optionCurrent),
|
||||
];
|
||||
}
|
||||
|
||||
Widget _buildCupertinoActionCancelButton(BuildContext context) {
|
||||
return CupertinoActionSheetAction(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).cancel,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorTextButton)),
|
||||
onPressed: () => controller.closeFilterMessageActionSheet(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _filterMessageWithAttachmentsAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_attachment_action'),
|
||||
SvgPicture.asset(imagePaths.icAttachment, width: 28, height: 28, fit: BoxFit.fill, color: AppColor.colorTextButton),
|
||||
AppLocalizations.of(context).with_attachments,
|
||||
FilterMessageOption.attachments,
|
||||
optionCurrent: optionCurrent,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
|
||||
Widget _filterMessagesUnreadAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_unread_action'),
|
||||
SvgPicture.asset(imagePaths.icUnreadV2, width: 28, height: 28, fit: BoxFit.fill),
|
||||
AppLocalizations.of(context).unread,
|
||||
FilterMessageOption.unread,
|
||||
optionCurrent: optionCurrent,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
|
||||
Widget _filterMessageStarredAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_starred_action'),
|
||||
SvgPicture.asset(imagePaths.icStar, width: 28, height: 28, fit: BoxFit.fill),
|
||||
AppLocalizations.of(context).starred,
|
||||
FilterMessageOption.starred,
|
||||
optionCurrent: optionCurrent,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
|
||||
// Widget _buildAppBarSelectModeActive(BuildContext context) {
|
||||
// return (AppBarThreadSelectModeActiveBuilder(
|
||||
// context,
|
||||
@@ -318,7 +380,9 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
return _buildResultSearchEmails(context, controller.emailListSearch);
|
||||
}
|
||||
} else {
|
||||
return _buildResultListEmail(context, controller.emailList);
|
||||
return _buildResultListEmail(
|
||||
context,
|
||||
controller.isFilterMessagesEnabled ? controller.emailListFiltered : controller.emailList);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -4,9 +4,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/model/filter_message_option.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnFilterEmailAction = void Function();
|
||||
typedef OnFilterEmailAction = void Function(FilterMessageOption);
|
||||
typedef OnEditThreadAction = void Function();
|
||||
typedef OnOpenListMailboxActionClick = void Function();
|
||||
typedef OnCancelEditThread = void Function();
|
||||
@@ -23,6 +24,7 @@ class AppBarThreadWidgetBuilder {
|
||||
final PresentationMailbox? _presentationMailbox;
|
||||
final List<PresentationEmail> _listSelectionEmail;
|
||||
final SelectMode _selectMode;
|
||||
final FilterMessageOption _filterMessageOption;
|
||||
|
||||
AppBarThreadWidgetBuilder(
|
||||
this._context,
|
||||
@@ -31,6 +33,7 @@ class AppBarThreadWidgetBuilder {
|
||||
this._presentationMailbox,
|
||||
this._listSelectionEmail,
|
||||
this._selectMode,
|
||||
this._filterMessageOption,
|
||||
);
|
||||
|
||||
void addOnFilterEmailAction(OnFilterEmailAction onFilterEmailAction) {
|
||||
@@ -69,9 +72,20 @@ class AppBarThreadWidgetBuilder {
|
||||
if (_selectMode == SelectMode.ACTIVE)
|
||||
Positioned(left: 40, child: _buildCountItemSelected()),
|
||||
Positioned(right: 0, child: _buildFilterButton()),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 60, right: 40),
|
||||
child: _buildContentCenterAppBar()),
|
||||
_filterMessageOption.getTitle(_context).isNotEmpty
|
||||
? Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 60, right: 40),
|
||||
child: _buildContentCenterAppBar()),
|
||||
Transform(
|
||||
transform: Matrix4.translationValues(-2.0, -8.0, 0.0),
|
||||
child: Text(
|
||||
_filterMessageOption.getTitle(_context),
|
||||
style: TextStyle(fontSize: 11, color: AppColor.colorContentEmail)))
|
||||
])
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(left: 60, right: 40),
|
||||
child: _buildContentCenterAppBar()),
|
||||
]
|
||||
))
|
||||
])
|
||||
@@ -103,9 +117,13 @@ class AppBarThreadWidgetBuilder {
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
child: IconButton(
|
||||
color: AppColor.baseTextColor,
|
||||
icon: SvgPicture.asset(_imagePaths.icFilter, fit: BoxFit.fill),
|
||||
onPressed: () => _onFilterEmailAction?.call()
|
||||
icon: SvgPicture.asset(
|
||||
_imagePaths.icFilter,
|
||||
color: _filterMessageOption == FilterMessageOption.all
|
||||
? AppColor.colorFilterMessageDisabled
|
||||
: AppColor.colorFilterMessageEnabled,
|
||||
fit: BoxFit.fill),
|
||||
onPressed: () => _onFilterEmailAction?.call(_filterMessageOption)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/model/filter_message_option.dart';
|
||||
|
||||
class FilterMessageCupertinoActionSheetActionBuilder extends CupertinoActionSheetActionBuilder<FilterMessageOption> {
|
||||
|
||||
final FilterMessageOption option;
|
||||
final FilterMessageOption? optionCurrent;
|
||||
final SvgPicture? actionSelected;
|
||||
final Color? bgColor;
|
||||
|
||||
FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key key,
|
||||
SvgPicture actionIcon,
|
||||
String actionName,
|
||||
this.option,
|
||||
{
|
||||
this.optionCurrent,
|
||||
this.actionSelected,
|
||||
this.bgColor,
|
||||
}
|
||||
) : super(key, actionIcon, actionName);
|
||||
|
||||
@override
|
||||
Widget build() {
|
||||
return Container(
|
||||
color: bgColor ?? Colors.white,
|
||||
child: CupertinoActionSheetAction(
|
||||
key: key,
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12, right: 16),
|
||||
child: actionIcon),
|
||||
Expanded(child: Text(actionName, textAlign: TextAlign.left, style: actionTextStyle())),
|
||||
if (optionCurrent == option && actionSelected != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 12),
|
||||
child: actionSelected!),
|
||||
]),
|
||||
onPressed: () {
|
||||
if (onCupertinoActionSheetActionClick != null) {
|
||||
onCupertinoActionSheetActionClick!(option);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user