TF-79 Mark as star/unstar selected multiple email

This commit is contained in:
dab246
2021-09-20 14:29:02 +07:00
committed by Dat H. Pham
parent 1b061d4af9
commit c7a3e90a68
30 changed files with 565 additions and 98 deletions
@@ -0,0 +1,41 @@
import 'package:core/core.dart';
import 'package:model/model.dart';
class MarkAsStarMultipleEmailAllSuccess extends UIState {
final int countMarkStarSuccess;
final MarkStarAction markStarAction;
MarkAsStarMultipleEmailAllSuccess(this.countMarkStarSuccess, this.markStarAction);
@override
List<Object?> get props => [countMarkStarSuccess, markStarAction];
}
class MarkAsStarMultipleEmailAllFailure extends FeatureFailure {
final MarkStarAction markStarAction;
MarkAsStarMultipleEmailAllFailure(this.markStarAction);
@override
List<Object> get props => [markStarAction];
}
class MarkAsStarMultipleEmailHasSomeEmailFailure extends UIState {
final int countMarkStarSuccess;
final MarkStarAction markStarAction;
MarkAsStarMultipleEmailHasSomeEmailFailure(this.countMarkStarSuccess, this.markStarAction);
@override
List<Object> get props => [countMarkStarSuccess, markStarAction];
}
class MarkAsStarMultipleEmailFailure extends FeatureFailure {
final exception;
final MarkStarAction markStarAction;
MarkAsStarMultipleEmailFailure(this.exception, this.markStarAction);
@override
List<Object> get props => [exception, markStarAction];
}
@@ -0,0 +1,41 @@
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart';
class MarkAsStarMultipleEmailInteractor {
final EmailRepository _emailRepository;
MarkAsStarMultipleEmailInteractor(this._emailRepository);
Stream<Either<Failure, Success>> execute(
AccountId accountId,
List<Email> emails,
MarkStarAction markStarAction
) async* {
try {
yield Right<Failure, Success>(LoadingState());
final listEmailNeedMarkStar = emails
.where((email) => markStarAction == MarkStarAction.unMarkStar ? email.isFlaggedEmail() : !email.isFlaggedEmail())
.toList();
final result = await _emailRepository.markAsStar(accountId, listEmailNeedMarkStar, markStarAction);
if (listEmailNeedMarkStar.length == result.length) {
final countMarkStarSuccess = emails.length;
yield Right(MarkAsStarMultipleEmailAllSuccess(countMarkStarSuccess, markStarAction));
} else if (result.isEmpty) {
yield Left(MarkAsStarMultipleEmailAllFailure(markStarAction));
} else {
final countMarkStarSuccess = emails.length - (listEmailNeedMarkStar.length - result.length);
yield Right(MarkAsStarMultipleEmailHasSomeEmailFailure(countMarkStarSuccess, markStarAction));
}
} catch (e) {
yield Left(MarkAsStarMultipleEmailFailure(e, markStarAction));
}
}
}
@@ -7,7 +7,7 @@ import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasour
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_important_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
@@ -18,6 +18,7 @@ import 'package:tmail_ui_user/features/thread/domain/repository/thread_repositor
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
class ThreadBindings extends Bindings {
@@ -38,7 +39,8 @@ class ThreadBindings extends Bindings {
Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MoveMultipleEmailToMailboxInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsMultipleEmailReadInteractor(Get.find<MarkAsEmailReadInteractor>()));
Get.lazyPut(() => MarkAsEmailImportantInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsStarMultipleEmailInteractor(Get.find<EmailRepository>()));
Get.put(ThreadController(
Get.find<ResponsiveUtils>(),
Get.find<GetEmailsInMailboxInteractor>(),
@@ -47,6 +49,8 @@ class ThreadBindings extends Bindings {
Get.find<AppToast>(),
Get.find<MoveMultipleEmailToMailboxInteractor>(),
Get.find<MarkAsEmailImportantInteractor>(),
Get.find<MarkAsStarEmailInteractor>(),
Get.find<MarkAsStarMultipleEmailInteractor>(),
));
}
}
@@ -8,7 +8,6 @@ import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
@@ -18,18 +17,22 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_request.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_important_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_important_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
@@ -45,6 +48,8 @@ class ThreadController extends BaseController {
final ScrollController listEmailController;
final MoveMultipleEmailToMailboxInteractor _moveMultipleEmailToMailboxInteractor;
final MarkAsEmailImportantInteractor _markAsEmailImportantInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final MarkAsStarMultipleEmailInteractor _markAsStarMultipleEmailInteractor;
final _properties = Properties({
'id', 'subject', 'from', 'to', 'cc', 'bcc', 'keywords', 'receivedAt',
@@ -67,6 +72,8 @@ class ThreadController extends BaseController {
this._appToast,
this._moveMultipleEmailToMailboxInteractor,
this._markAsEmailImportantInteractor,
this._markAsStarEmailInteractor,
this._markAsStarMultipleEmailInteractor,
);
@override
@@ -110,7 +117,7 @@ class ThreadController extends BaseController {
mailboxDashBoardController.viewState.listen((state) {
state.map((success) {
if (success is MarkAsEmailImportantSuccess) {
if (success is MarkAsStarEmailSuccess) {
_refreshListEmail();
}
});
@@ -134,6 +141,9 @@ class ThreadController extends BaseController {
} else if (failure is MarkAsMultipleEmailReadAllFailure
|| failure is MarkAsMultipleEmailReadFailure) {
_markAsSelectedEmailReadFailure(failure);
} else if (failure is MarkAsStarMultipleEmailAllFailure
|| failure is MarkAsStarMultipleEmailFailure) {
_markAsStarMultipleEmailFailure(failure);
}
},
(success) {
@@ -147,6 +157,11 @@ class ThreadController extends BaseController {
_moveSelectedMultipleEmailToMailboxSuccess(success);
} else if (success is MarkAsEmailImportantSuccess) {
_markAsEmailImportantSuccess(success);
} else if (success is MarkAsStarEmailSuccess) {
_markAsStarEmailSuccess(success);
} else if (success is MarkAsStarMultipleEmailAllSuccess
|| success is MarkAsStarMultipleEmailHasSomeEmailFailure) {
_markAsStarMultipleEmailSuccess(success);
}
}
);
@@ -163,7 +178,7 @@ class ThreadController extends BaseController {
loadMoreState.value = success.emailList.isEmpty ? LoadMoreState.COMPLETED : LoadMoreState.IDLE;
mailboxDashBoardController.viewState.value.map((success) {
if (success is MarkAsEmailImportantSuccess) {
if (success is MarkAsStarEmailSuccess) {
_updateValueCurrentEmail();
mailboxDashBoardController.clearState();
}
@@ -282,7 +297,9 @@ class ThreadController extends BaseController {
bool _isUnSelectedAll() => emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
bool isEmailAllRead(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isReadEmail());
bool isAllEmailRead(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isReadEmail());
bool isAllEmailMarkAsStar(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isFlaggedEmail());
void cancelSelectEmail() {
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
@@ -443,18 +460,60 @@ class ThreadController extends BaseController {
}
void markAsEmailImportant(PresentationEmail presentationEmail) {
void markAsStarEmail(PresentationEmail presentationEmail) {
final accountId = mailboxDashBoardController.accountId.value;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (accountId != null && mailboxCurrent != null) {
final importantAction = presentationEmail.isFlaggedEmail() ? ImportantAction.unMarkStar : ImportantAction.markStar;
consumeState(_markAsEmailImportantInteractor.execute(accountId, presentationEmail.id, importantAction));
final importantAction = presentationEmail.isFlaggedEmail() ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
consumeState(_markAsStarEmailInteractor.execute(accountId, presentationEmail.toEmail(), importantAction));
}
}
void _markAsEmailImportantSuccess(Success success) {
void _markAsStarEmailSuccess(Success success) {
_refreshListEmail();
}
void markAsStarSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail, MarkStarAction markStarAction) {
popBack();
final accountId = mailboxDashBoardController.accountId.value;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (accountId != null && mailboxCurrent != null) {
final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList();
consumeState(_markAsStarMultipleEmailInteractor.execute(accountId, listEmail, markStarAction));
}
}
void _markAsStarMultipleEmailSuccess(Success success) {
cancelSelectEmail();
MarkStarAction? markStarAction;
int countMarkStarSuccess = 0;
if (success is MarkAsStarMultipleEmailAllSuccess) {
markStarAction = success.markStarAction;
countMarkStarSuccess = success.countMarkStarSuccess;
} else if (success is MarkAsStarMultipleEmailHasSomeEmailFailure) {
markStarAction = success.markStarAction;
countMarkStarSuccess = success.countMarkStarSuccess;
}
if (Get.context != null && markStarAction != null) {
_appToast.showSuccessToast(markStarAction == MarkStarAction.unMarkStar
? AppLocalizations.of(Get.context!).marked_unstar_multiple_item(countMarkStarSuccess)
: AppLocalizations.of(Get.context!).marked_star_multiple_item(countMarkStarSuccess));
}
_refreshListEmail();
}
void _markAsStarMultipleEmailFailure(Failure failure) {
cancelSelectEmail();
if (Get.context != null) {
_appToast.showErrorToast(AppLocalizations.of(Get.context!).an_error_occurred);
}
}
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
&& mailboxDashBoardController.userProfile.value != null
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox);
@@ -88,7 +88,7 @@ class ThreadView extends GetWidget<ThreadController> {
_moveToTrashAction(context, listEmail),
_moveToMailboxAction(context, listEmail),
_markAsReadAction(context, listEmail),
_markAsFlagAction(context, listEmail),
_markAsStarAction(context, listEmail),
_moveToSpamAction(context, listEmail),
SizedBox(height: 30),
];
@@ -98,12 +98,12 @@ class ThreadView extends GetWidget<ThreadController> {
return (EmailContextMenuActionBuilder(
Key('mark_as_read_context_menu_action'),
SvgPicture.asset(imagePaths.icEyeDisable, width: 24, height: 24, fit: BoxFit.fill),
controller.isEmailAllRead(listEmail)
controller.isAllEmailRead(listEmail)
? AppLocalizations.of(context).mark_as_unread
: AppLocalizations.of(context).mark_as_read,
listEmail)
..onActionClick((data) => controller.markAsSelectedEmailRead(data, fromContextMenuAction: true)))
.build();
..onActionClick((data) => controller.markAsSelectedEmailRead(data, fromContextMenuAction: true)))
.build();
}
Widget _moveToTrashAction(BuildContext context, List<PresentationEmail> listEmail) {
@@ -114,6 +114,9 @@ class ThreadView extends GetWidget<ThreadController> {
listEmail)
..onActionClick((data) => {}))
.build();
AppLocalizations.of(context).move_to_trash, listEmail)
..onActionClick((data) => {}))
.build();
}
Widget _moveToMailboxAction(BuildContext context, List<PresentationEmail> listEmail) {
@@ -126,7 +129,9 @@ class ThreadView extends GetWidget<ThreadController> {
.build();
}
Widget _markAsFlagAction(BuildContext context, List<PresentationEmail> listEmail) {
Widget _markAsStarAction(BuildContext context, List<PresentationEmail> listEmail) {
final markStarAction = controller.isAllEmailMarkAsStar(listEmail) ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
return (EmailContextMenuActionBuilder(
Key('mark_as_flag_context_menu_action'),
SvgPicture.asset(imagePaths.icFlag, width: 24, height: 24, fit: BoxFit.fill),
@@ -134,6 +139,18 @@ class ThreadView extends GetWidget<ThreadController> {
listEmail)
..onActionClick((data) => {}))
.build();
Key('mark_as_star_context_menu_action'),
SvgPicture.asset(
markStarAction == MarkStarAction.markStar ? imagePaths.icFlag : imagePaths.icFlagged,
width: 24,
height: 24,
fit: BoxFit.fill),
markStarAction == MarkStarAction.markStar
? AppLocalizations.of(context).mark_as_star
: AppLocalizations.of(context).mark_as_unstar,
listEmail)
..onActionClick((data) => controller.markAsStarSelectedMultipleEmail(data, markStarAction)))
.build();
}
Widget _moveToSpamAction(BuildContext context, List<PresentationEmail> listEmail) {
@@ -144,6 +161,9 @@ class ThreadView extends GetWidget<ThreadController> {
listEmail)
..onActionClick((data) => {}))
.build();
AppLocalizations.of(context).move_to_spam, listEmail)
..onActionClick((data) => {}))
.build();
}
Widget _buildLoadingView() {
@@ -8,7 +8,7 @@ import 'package:model/model.dart';
typedef OnOpenEmailActionClick = void Function(PresentationEmail selectedEmail);
typedef OnSelectEmailActionClick = void Function(PresentationEmail selectedEmail);
typedef OnMarkAsImportantActionClick = void Function(PresentationEmail selectedEmail);
typedef OnMarkAsStarEmailActionClick = void Function(PresentationEmail selectedEmail);
class EmailTileBuilder {
@@ -21,7 +21,7 @@ class EmailTileBuilder {
OnOpenEmailActionClick? _onOpenEmailActionClick;
OnSelectEmailActionClick? _onSelectEmailActionClick;
OnMarkAsImportantActionClick? _onMarkAsImportantActionClick;
OnMarkAsStarEmailActionClick? _onMarkAsStarEmailActionClick;
EmailTileBuilder(
this._context,
@@ -40,8 +40,8 @@ class EmailTileBuilder {
_onSelectEmailActionClick = onSelectEmailActionClick;
}
void addOnMarkAsImportantActionClick(OnMarkAsImportantActionClick onMarkAsImportantActionClick) {
_onMarkAsImportantActionClick = onMarkAsImportantActionClick;
void addOnMarkAsStarEmailActionClick(OnMarkAsStarEmailActionClick onMarkAsStarEmailActionClick) {
_onMarkAsStarEmailActionClick = onMarkAsStarEmailActionClick;
}
Widget build() {
@@ -132,8 +132,8 @@ class EmailTileBuilder {
ButtonBuilder(_presentationEmail.isFlaggedEmail() ? _imagePaths.icFlagged : _imagePaths.icFlag)
.padding(2)
.onPressActionClick(() {
if (_onMarkAsImportantActionClick != null) {
_onMarkAsImportantActionClick!(_presentationEmail);
if (_onMarkAsStarEmailActionClick != null) {
_onMarkAsStarEmailActionClick!(_presentationEmail);
}
})
.build(),