TF-78 Implement mark as read & unread for multiple selected email in threads

This commit is contained in:
dab246
2021-09-15 11:02:56 +07:00
committed by Dat H. Pham
parent 161eed5d72
commit e7bf7f782e
11 changed files with 262 additions and 5 deletions
@@ -0,0 +1,38 @@
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
class MarkAsMultipleEmailReadAllSuccess extends UIState {
final List<Either<Failure, Success>> resultList;
MarkAsMultipleEmailReadAllSuccess(this.resultList);
@override
List<Object?> get props => [resultList];
}
class MarkAsMultipleEmailReadAllFailure extends FeatureFailure {
final List<Either<Failure, Success>> resultList;
MarkAsMultipleEmailReadAllFailure(this.resultList);
@override
List<Object> get props => [resultList];
}
class MarkAsMultipleEmailReadHasSomeEmailFailure extends UIState {
final List<Either<Failure, Success>> resultList;
MarkAsMultipleEmailReadHasSomeEmailFailure(this.resultList);
@override
List<Object> get props => [resultList];
}
class MarkAsMultipleEmailReadFailure extends FeatureFailure {
final exception;
MarkAsMultipleEmailReadFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,37 @@
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:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
class MarkAsMultipleEmailReadInteractor {
final MarkAsEmailReadInteractor markAsEmailReadInteractor;
MarkAsMultipleEmailReadInteractor(this.markAsEmailReadInteractor);
Future<Either<Failure, Success>> execute(AccountId accountId, List<EmailId> listEmailId, bool unread) async {
try {
final listResult = await Future.wait(listEmailId.map((emailId) =>
markAsEmailReadInteractor.execute(accountId, emailId, unread)));
if (listResult.length == 1) {
return listResult.first;
} else {
var failedFileCount = 0;
listResult.forEach((element) {
if (element is Left) {
failedFileCount++;
}
});
if (failedFileCount == 0) {
return Right(MarkAsMultipleEmailReadAllSuccess(listResult));
} else if (failedFileCount == listResult.length) {
return Left(MarkAsMultipleEmailReadAllFailure(listResult));
}
return Right(MarkAsMultipleEmailReadHasSomeEmailFailure(listResult));
}
} catch (e) {
return Left(MarkAsMultipleEmailReadFailure(e));
}
}
}
@@ -1,12 +1,20 @@
import 'package:core/core.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
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_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.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/presentation/thread_controller.dart';
class ThreadBindings extends Bindings {
@@ -18,10 +26,18 @@ class ThreadBindings extends Bindings {
Get.lazyPut<ThreadRepository>(() => Get.find<ThreadRepositoryImpl>());
Get.lazyPut(() => GetEmailsInMailboxInteractor(Get.find<ThreadRepository>()));
Get.lazyPut(() => ScrollController());
Get.lazyPut(() => EmailDataSourceImpl(Get.find<EmailAPI>()));
Get.lazyPut<EmailDataSource>(() => Get.find<EmailDataSourceImpl>());
Get.lazyPut(() => EmailRepositoryImpl(Get.find<EmailDataSource>()));
Get.lazyPut<EmailRepository>(() => Get.find<EmailRepositoryImpl>());
Get.lazyPut(() => MarkAsEmailReadInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsMultipleEmailReadInteractor(Get.find<MarkAsEmailReadInteractor>()));
Get.put(ThreadController(
Get.find<ResponsiveUtils>(),
Get.find<GetEmailsInMailboxInteractor>(),
Get.find<ScrollController>(),
Get.find<MarkAsMultipleEmailReadInteractor>(),
Get.find<AppToast>(),
));
}
}
@@ -16,11 +16,14 @@ import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.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/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/presentation/model/load_more_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_context_menu_action_builder.dart';
import 'package:tmail_ui_user/main/actions/email_action.dart';
@@ -32,6 +35,8 @@ class ThreadController extends BaseController {
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final GetEmailsInMailboxInteractor _getEmailsInMailboxInteractor;
final MarkAsMultipleEmailReadInteractor _markAsMultipleEmailReadInteractor;
final AppToast _appToast;
final ResponsiveUtils responsiveUtils;
final ScrollController listEmailController;
@@ -52,6 +57,8 @@ class ThreadController extends BaseController {
this.responsiveUtils,
this._getEmailsInMailboxInteractor,
this.listEmailController,
this._markAsMultipleEmailReadInteractor,
this._appToast,
);
@override
@@ -204,7 +211,7 @@ class ThreadController extends BaseController {
bool _isUnSelectedAll() => emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
bool _isEmailAllRead(List<PresentationEmail> listEmail) => listEmail.every((email) => !email.isUnReadEmail());
bool _isEmailAllRead(List<PresentationEmail> listEmail) => listEmail.every((email) => email.isReadEmail());
void cancelSelectEmail() {
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
@@ -218,8 +225,47 @@ class ThreadController extends BaseController {
emailList.value = newEmailList;
}
void unreadSelectedEmail(List<PresentationEmail> listEmail) {
popBack();
void unreadSelectedEmail(List<PresentationEmail> listEmail, {bool fromContextMenuAction = false}) {
if (fromContextMenuAction) {
popBack();
}
final isUnread = _isEmailAllRead(listEmail);
final listEmailId = listEmail
.where((email) => isUnread ? email.isReadEmail() : email.isUnReadEmail())
.map((email) => email.id)
.toList();
final accountId = mailboxDashBoardController.accountId.value;
if (accountId != null) {
_markAsMultipleEmailReadInteractor
.execute(accountId, listEmailId, isUnread)
.then((result) => result.fold(
(failure) {
cancelSelectEmail();
if (failure is MarkAsEmailReadFailure
|| failure is MarkAsMultipleEmailReadAllFailure
|| failure is MarkAsMultipleEmailReadFailure) {
_appToast.showErrorToast(AppLocalizations.of(Get.context!).an_error_occurred);
}
},
(success) {
cancelSelectEmail();
if (success is MarkAsEmailReadSuccess
|| success is MarkAsMultipleEmailReadAllSuccess
|| success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
if (Get.context != null) {
_appToast.showSuccessToast(isUnread
? AppLocalizations.of(Get.context!).marked_multiple_item_as_unread(listEmail.length)
: AppLocalizations.of(Get.context!).marked_multiple_item_as_read(listEmail.length));
}
}
}));
}
}
void openContextMenuSelectedEmail(BuildContext context, ImagePaths imagePaths, List<PresentationEmail> listEmail) {
@@ -245,7 +291,7 @@ class ThreadController extends BaseController {
SvgPicture.asset(imagePaths.icEyeDisable, width: 24, height: 24, fit: BoxFit.fill),
_isEmailAllRead(listEmail) ? AppLocalizations.of(context).mark_as_unread : AppLocalizations.of(context).mark_as_read,
listEmail)
..onActionClick((data) => unreadSelectedEmail(data)))
..onActionClick((data) => unreadSelectedEmail(data, fromContextMenuAction: true)))
.build();
}
+19
View File
@@ -199,5 +199,24 @@
"@move_to_spam": {
"type": "text",
"placeholders": {}
},
"marked_multiple_item_as_read": "Marked {count} item as read",
"@marked_multiple_item_as_read": {
"type": "text",
"placeholders": {
"count": {}
}
},
"marked_multiple_item_as_unread": "Marked {count} item as unread",
"@marked_multiple_item_as_unread": {
"type": "text",
"placeholders": {
"count": {}
}
},
"an_error_occurred": "Error! An error occurred. Please try again later.",
"@an_error_occurred": {
"type": "text",
"placeholders": {}
}
}
+19
View File
@@ -199,5 +199,24 @@
"@move_to_spam": {
"type": "text",
"placeholders": {}
},
"marked_multiple_item_as_read": "Marked {count} item as read",
"@marked_multiple_item_as_read": {
"type": "text",
"placeholders": {
"count": {}
}
},
"marked_multiple_item_as_unread": "Marked {count} item as unread",
"@marked_multiple_item_as_unread": {
"type": "text",
"placeholders": {
"count": {}
}
},
"an_error_occurred": "Error! An error occurred. Please try again later.",
"@an_error_occurred": {
"type": "text",
"placeholders": {}
}
}
+20 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2021-09-15T10:03:14.927099",
"@@last_modified": "2021-09-15T11:00:57.061103",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -254,5 +254,24 @@
"@move_to_spam": {
"type": "text",
"placeholders": {}
},
"marked_multiple_item_as_read": "Marked {count} item as read",
"@marked_multiple_item_as_read": {
"type": "text",
"placeholders": {
"count": {}
}
},
"marked_multiple_item_as_unread": "Marked {count} item as unread",
"@marked_multiple_item_as_unread": {
"type": "text",
"placeholders": {
"count": {}
}
},
"an_error_occurred": "Error! An error occurred. Please try again later.",
"@an_error_occurred": {
"type": "text",
"placeholders": {}
}
}
+19
View File
@@ -199,5 +199,24 @@
"@move_to_spam": {
"type": "text",
"placeholders": {}
},
"marked_multiple_item_as_read": "Marked {count} item as read",
"@marked_multiple_item_as_read": {
"type": "text",
"placeholders": {
"count": {}
}
},
"marked_multiple_item_as_unread": "Marked {count} item as unread",
"@marked_multiple_item_as_unread": {
"type": "text",
"placeholders": {
"count": {}
}
},
"an_error_occurred": "Error! An error occurred. Please try again later.",
"@an_error_occurred": {
"type": "text",
"placeholders": {}
}
}
+19
View File
@@ -199,5 +199,24 @@
"@move_to_spam": {
"type": "text",
"placeholders": {}
},
"marked_multiple_item_as_read": "Marked {count} item as read",
"@marked_multiple_item_as_read": {
"type": "text",
"placeholders": {
"count": {}
}
},
"marked_multiple_item_as_unread": "Marked {count} item as unread",
"@marked_multiple_item_as_unread": {
"type": "text",
"placeholders": {
"count": {}
}
},
"an_error_occurred": "Error! An error occurred. Please try again later.",
"@an_error_occurred": {
"type": "text",
"placeholders": {}
}
}
@@ -277,5 +277,28 @@ class AppLocalizations {
name: 'move_to_spam',
);
}
String marked_multiple_item_as_read(int count) {
return Intl.message(
'Marked $count item as read',
name: 'marked_multiple_item_as_read',
args: [count]
);
}
String marked_multiple_item_as_unread(int count) {
return Intl.message(
'Marked $count item as unread',
name: 'marked_multiple_item_as_unread',
args: [count]
);
}
String get an_error_occurred {
return Intl.message(
'Error! An error occurred. Please try again later.',
name: 'an_error_occurred',
);
}
}
+2
View File
@@ -64,6 +64,8 @@ class PresentationEmail with EquatableMixin {
bool isUnReadEmail() => !(keywords?.containsKey(KeyWordIdentifier.emailSeen) == true);
bool isReadEmail() => keywords?.containsKey(KeyWordIdentifier.emailSeen) == true;
bool isFlaggedEmail() => keywords?.containsKey(KeyWordIdentifier.emailFlagged) == true;
@override