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
@@ -31,4 +31,9 @@ abstract class EmailDataSource {
Future<List<EmailId>> moveToMailbox(AccountId accountId, MoveRequest moveRequest);
Future<bool> markAsImportant(AccountId accountId, EmailId emailId, ImportantAction importantAction);
Future<List<Email>> markAsStar(
AccountId accountId,
List<Email> emails,
MarkStarAction markStarAction
);
}
@@ -79,9 +79,9 @@ class EmailDataSourceImpl extends EmailDataSource {
}
@override
Future<bool> markAsImportant(AccountId accountId, EmailId emailId, ImportantAction importantAction) {
Future<List<Email>> markAsStar(AccountId accountId, List<Email> emails, MarkStarAction markStarAction) {
return Future.sync(() async {
return await emailAPI.markAsImportant(accountId, emailId, importantAction);
return await emailAPI.markAsStar(accountId, emails, markStarAction);
}).catchError((error) {
throw error;
});
+18 -12
View File
@@ -221,27 +221,33 @@ class EmailAPI {
}
Future<bool> markAsImportant(AccountId accountId, EmailId emailId, ImportantAction importantAction) async {
Future<List<Email>> markAsStar(AccountId accountId, List<Email> emails, MarkStarAction markStarAction) async {
final emailIds = emails.map((email) => email.id).toList();
final setEmailMethod = SetEmailMethod(accountId)
..addUpdates({
emailId.id: KeyWordIdentifier.emailFlagged.generateImportantActionPath(importantAction)
});
..addUpdates(emailIds.generateMapUpdateObjectMarkAsStar(markStarAction));
final getEmailMethod = GetEmailMethod(accountId)
..addIds(emailIds.toIds().toSet())
..addProperties(Properties({'keywords'}));
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
final setEmailInvocation = requestBuilder.invocation(setEmailMethod);
requestBuilder.invocation(setEmailMethod);
final getEmailInvocation = requestBuilder.invocation(getEmailMethod);
final response = await (requestBuilder
..usings(setEmailMethod.requiredCapabilities))
.build()
.execute();
..usings(setEmailMethod.requiredCapabilities))
.build()
.execute();
final setEmailResponse = response.parse<SetEmailResponse>(
setEmailInvocation.methodCallId,
SetEmailResponse.deserialize);
final getEmailResponse = response.parse<GetEmailResponse>(
getEmailInvocation.methodCallId,
GetEmailResponse.deserialize);
return Future.sync(() async {
final emailUpdated = setEmailResponse!.updated![emailId.id];
return emailUpdated == null;
return getEmailResponse!.list;
}).catchError((error) {
throw error;
});
@@ -61,7 +61,11 @@ class EmailRepositoryImpl extends EmailRepository {
}
@override
Future<bool> markAsImportant(AccountId accountId, EmailId emailId, ImportantAction importantAction) {
return emailDataSource.markAsImportant(accountId, emailId, importantAction);
Future<List<Email>> markAsStar(
AccountId accountId,
List<Email> emails,
MarkStarAction markStarAction
) {
return emailDataSource.markAsStar(accountId, emails, markStarAction);
}
}
@@ -30,4 +30,9 @@ abstract class EmailRepository {
Future<List<EmailId>> moveToMailbox(AccountId accountId, MoveRequest moveRequest);
Future<bool> markAsImportant(AccountId accountId, EmailId emailId, ImportantAction importantAction);
Future<List<Email>> markAsStar(
AccountId accountId,
List<Email> emails,
MarkStarAction markStarAction
);
}
@@ -1,23 +0,0 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
class MarkAsEmailImportantSuccess extends UIState {
final EmailId emailId;
final ImportantAction importantAction;
MarkAsEmailImportantSuccess(this.emailId, this.importantAction);
@override
List<Object?> get props => [emailId, importantAction];
}
class MarkAsEmailImportantFailure extends FeatureFailure {
final exception;
final ImportantAction importantAction;
MarkAsEmailImportantFailure(this.exception, this.importantAction);
@override
List<Object> get props => [exception, importantAction];
}
@@ -0,0 +1,23 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
class MarkAsStarEmailSuccess extends UIState {
final Email updatedEmail;
final MarkStarAction markStarAction;
MarkAsStarEmailSuccess(this.updatedEmail, this.markStarAction);
@override
List<Object?> get props => [updatedEmail, markStarAction];
}
class MarkAsStarEmailFailure extends FeatureFailure {
final exception;
final MarkStarAction markStarAction;
MarkAsStarEmailFailure(this.exception, this.markStarAction);
@override
List<Object> get props => [exception, markStarAction];
}
@@ -1,22 +0,0 @@
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/email/domain/state/mark_as_email_important_state.dart';
class MarkAsEmailImportantInteractor {
final EmailRepository emailRepository;
MarkAsEmailImportantInteractor(this.emailRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId, EmailId emailId, ImportantAction importantAction) async* {
try {
final result = await emailRepository.markAsImportant(accountId, emailId, importantAction);
yield result ? Right(MarkAsEmailImportantSuccess(emailId, importantAction)) : Left(MarkAsEmailImportantFailure(null, importantAction));
} catch (e) {
yield Left(MarkAsEmailImportantFailure(e, importantAction));
}
}
}
@@ -0,0 +1,27 @@
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/email/domain/state/mark_as_email_star_state.dart';
class MarkAsStarEmailInteractor {
final EmailRepository emailRepository;
MarkAsStarEmailInteractor(this.emailRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId, Email email, MarkStarAction markStarAction) async* {
try {
final result = await emailRepository.markAsStar(accountId, [email], markStarAction);
if (result.isNotEmpty) {
final updatedEmail = email.updatedEmail(newKeywords: result.first.keywords);
yield Right(MarkAsStarEmailSuccess(updatedEmail, markStarAction));
} else {
yield Left(MarkAsStarEmailFailure(null, markStarAction));
}
} catch (e) {
yield Left(MarkAsStarEmailFailure(e, markStarAction));
}
}
}
@@ -10,9 +10,9 @@ import 'package:tmail_ui_user/features/email/domain/repository/email_repository.
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.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_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_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/email_controller.dart';
import 'package:tmail_ui_user/features/login/data/repository/credential_repository_impl.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
@@ -37,6 +37,7 @@ class EmailBindings extends Bindings {
Get.find<CredentialRepository>()));
Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsEmailImportantInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>()));
Get.put(EmailController(
Get.find<GetEmailContentInteractor>(),
Get.find<MarkAsEmailReadInteractor>(),
@@ -46,6 +47,6 @@ class EmailBindings extends Bindings {
Get.find<ExportAttachmentInteractor>(),
Get.find<MoveToMailboxInteractor>()));
Get.find<ExportAttachmentInteractor>(),
Get.find<MarkAsEmailImportantInteractor>()));
Get.find<MarkAsStarEmailInteractor>()));
}
}
@@ -18,11 +18,12 @@ import 'package:tmail_ui_user/features/email/domain/state/export_attachment_stat
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.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/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.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/email/presentation/model/composer_arguments.dart';
@@ -45,6 +46,7 @@ class EmailController extends BaseController {
final ExportAttachmentInteractor _exportAttachmentInteractor;
final MoveToMailboxInteractor _moveToMailboxInteractor;
final MarkAsEmailImportantInteractor _markAsEmailImportantInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
final attachmentsExpandMode = ExpandMode.COLLAPSE.obs;
@@ -60,6 +62,7 @@ class EmailController extends BaseController {
this._exportAttachmentInteractor,
this._moveToMailboxInteractor,
this._markAsEmailImportantInteractor,
this._markAsStarEmailInteractor,
);
@override
@@ -118,6 +121,8 @@ class EmailController extends BaseController {
_moveToMailboxSuccess(success);
} else if (success is MarkAsEmailImportantSuccess) {
_markAsEmailImportantSuccess(success);
} else if (success is MarkAsStarEmailSuccess) {
_markAsEmailStarSuccess(success);
}
});
}
@@ -309,15 +314,19 @@ class EmailController extends BaseController {
}
void markAsEmailImportant(PresentationEmail presentationEmail) async {
void markAsStarEmail(PresentationEmail presentationEmail) async {
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 markStarAction = presentationEmail.isFlaggedEmail() ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
consumeState(_markAsStarEmailInteractor.execute(accountId, presentationEmail.toEmail(), markStarAction));
}
}
void _markAsEmailImportantSuccess(Success success) {
void _markAsEmailStarSuccess(Success success) {
if (success is MarkAsStarEmailSuccess) {
mailboxDashBoardController.setSelectedEmail(success.updatedEmail.toPresentationEmail(selectMode: SelectMode.ACTIVE));
}
mailboxDashBoardController.dispatchState(Right(success));
}
@@ -62,6 +62,8 @@ class EmailView extends GetView {
emailController.markAsEmailRead(presentationEmail, ReadActions.markAsUnread))
..addOnMarkAsImportantActionClick((presentationEmail) =>
emailController.markAsEmailImportant(presentationEmail)))
..addOnMarkAsStarActionClick((presentationEmail) =>
emailController.markAsStarEmail(presentationEmail)))
.build()));
}
@@ -10,12 +10,14 @@ typedef OnBackActionClick = void Function();
typedef OnUnreadEmailActionClick = void Function(PresentationEmail presentationEmail);
typedef OnMoveToMailboxActionClick = void Function(PresentationEmail presentationEmail);
typedef OnMarkAsImportantActionClick = void Function(PresentationEmail presentationEmail);
typedef OnMarkAsStarActionClick = void Function(PresentationEmail presentationEmail);
class AppBarMailWidgetBuilder {
OnBackActionClick? _onBackActionClick;
OnUnreadEmailActionClick? _onUnreadEmailActionClick;
OnMoveToMailboxActionClick? _onMoveToMailboxActionClick;
OnMarkAsImportantActionClick? _onMarkAsImportantActionClick;
OnMarkAsStarActionClick? _markAsStarActionClick;
final BuildContext _context;
final ImagePaths _imagePaths;
@@ -43,6 +45,8 @@ class AppBarMailWidgetBuilder {
void addOnMarkAsImportantActionClick(OnMarkAsImportantActionClick onMarkAsImportantActionClick) {
_onMarkAsImportantActionClick = onMarkAsImportantActionClick;
void addOnMarkAsStarActionClick(OnMarkAsStarActionClick onMarkAsStarActionClick) {
_markAsStarActionClick = onMarkAsStarActionClick;
}
Widget build() {
@@ -99,8 +103,8 @@ class AppBarMailWidgetBuilder {
: _imagePaths.icFlag)
.key(Key('button_mark_as_email_important'))
.onPressActionClick(() {
if (_onMarkAsImportantActionClick != null && _presentationEmail != null) {
_onMarkAsImportantActionClick!(_presentationEmail!);
if (_markAsStarActionClick != null && _presentationEmail != null) {
_markAsStarActionClick!(_presentationEmail!);
}})
.build(),
SizedBox(width: 10),
@@ -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(),
+42
View File
@@ -371,5 +371,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"you_need_to_grant_files_permission_to_download_attachments": "You need to grant files permission to download attachments",
"@you_need_to_grant_files_permission_to_download_attachments": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"count_attachment": "{count} attachments",
"@count_attachment": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"mark_as_unstar": "Unstar",
"@mark_as_unstar": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"marked_star_multiple_item": "Marked star {count} item",
"@marked_star_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"marked_unstar_multiple_item": "Marked unstar {count} item",
"@marked_unstar_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
}
}
+42
View File
@@ -371,5 +371,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"you_need_to_grant_files_permission_to_download_attachments": "You need to grant files permission to download attachments",
"@you_need_to_grant_files_permission_to_download_attachments": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"count_attachment": "{count} attachments",
"@count_attachment": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"mark_as_unstar": "Unstar",
"@mark_as_unstar": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"marked_star_multiple_item": "Marked star {count} item",
"@marked_star_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"marked_unstar_multiple_item": "Marked unstar {count} item",
"@marked_unstar_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
}
}
+45 -3
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2021-09-21T12:00:21.345356",
"@@last_modified": "2021-09-17T17:37:57.805293",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -232,8 +232,8 @@
"placeholders_order": [],
"placeholders": {}
},
"mark_as_flag": "Star",
"@mark_as_flag": {
"mark_as_star": "Star",
"@mark_as_star": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
@@ -371,5 +371,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"you_need_to_grant_files_permission_to_download_attachments": "You need to grant files permission to download attachments",
"@you_need_to_grant_files_permission_to_download_attachments": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"count_attachment": "{count} attachments",
"@count_attachment": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"mark_as_unstar": "Unstar",
"@mark_as_unstar": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"marked_star_multiple_item": "Marked star {count} item",
"@marked_star_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"marked_unstar_multiple_item": "Marked unstar {count} item",
"@marked_unstar_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
}
}
+42
View File
@@ -371,5 +371,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"you_need_to_grant_files_permission_to_download_attachments": "You need to grant files permission to download attachments",
"@you_need_to_grant_files_permission_to_download_attachments": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"count_attachment": "{count} attachments",
"@count_attachment": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"mark_as_unstar": "Unstar",
"@mark_as_unstar": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"marked_star_multiple_item": "Marked star {count} item",
"@marked_star_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"marked_unstar_multiple_item": "Marked unstar {count} item",
"@marked_unstar_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
}
}
+42
View File
@@ -371,5 +371,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"you_need_to_grant_files_permission_to_download_attachments": "You need to grant files permission to download attachments",
"@you_need_to_grant_files_permission_to_download_attachments": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"count_attachment": "{count} attachments",
"@count_attachment": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"mark_as_unstar": "Unstar",
"@mark_as_unstar": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"marked_star_multiple_item": "Marked star {count} item",
"@marked_star_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
},
"marked_unstar_multiple_item": "Marked unstar {count} item",
"@marked_unstar_multiple_item": {
"type": "text",
"placeholders_order": [
"count"
],
"placeholders": {
"count": {}
}
}
}
+25 -2
View File
@@ -264,10 +264,10 @@ class AppLocalizations {
);
}
String get mark_as_flag {
String get mark_as_star {
return Intl.message(
'Star',
name: 'mark_as_flag',
name: 'mark_as_star',
);
}
@@ -408,5 +408,28 @@ class AppLocalizations {
name: 'undo_action'
);
}
String get mark_as_unstar {
return Intl.message(
'Unstar',
name: 'mark_as_unstar',
);
}
String marked_star_multiple_item(int count) {
return Intl.message(
'Marked star $count item',
name: 'marked_star_multiple_item',
args: [count]
);
}
String marked_unstar_multiple_item(int count) {
return Intl.message(
'Marked unstar $count item',
name: 'marked_unstar_multiple_item',
args: [count]
);
}
}
@@ -1,5 +1,5 @@
enum ImportantAction {
enum MarkStarAction {
markStar,
unMarkStar
}
@@ -1,6 +1,6 @@
import 'package:jmap_dart_client/jmap/core/patch_object.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:model/email/important_action.dart';
import 'package:model/email/mark_star_action.dart';
import 'package:model/email/read_actions.dart';
extension KeyWordIdentifierExtension on KeyWordIdentifier {
@@ -14,9 +14,9 @@ extension KeyWordIdentifierExtension on KeyWordIdentifier {
});
}
PatchObject generateImportantActionPath(ImportantAction importantAction) {
PatchObject generateMarkStarActionPath(MarkStarAction markStarAction) {
return PatchObject({
_generatePath(): importantAction == ImportantAction.markStar ? true : null
_generatePath(): markStarAction == MarkStarAction.markStar ? true : null
});
}
}
@@ -21,6 +21,10 @@ extension ListEmailIdExtension on List<EmailId> {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = currentMailboxId.generateMoveToMailboxActionPath(destinationMailboxId);
Map<Id, PatchObject> generateMapUpdateObjectMarkAsStar(MarkStarAction markStarAction) {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = KeyWordIdentifier.emailFlagged.generateMarkStarActionPath(markStarAction);
});
return maps;
}
@@ -1,5 +1,7 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
extension PresentationEmailExtension on PresentationEmail {
@@ -15,9 +17,11 @@ extension PresentationEmailExtension on PresentationEmail {
}
PresentationEmail toggleSelect() {
PresentationEmail toUpdatedPresentationEmail({Map<KeyWordIdentifier, bool>? newKeywords}) {
return PresentationEmail(
id,
keywords: keywords,
keywords: newKeywords ?? keywords,
size: size,
receivedAt: receivedAt,
hasAttachment: hasAttachment,
@@ -69,4 +73,22 @@ extension PresentationEmailExtension on PresentationEmail {
replyTo: replyTo
);
}
Email toEmail() {
return Email(
id,
keywords: keywords,
size: size,
receivedAt: receivedAt,
hasAttachment: hasAttachment,
preview: preview,
subject: subject,
sentAt: sentAt,
from: from,
to: to,
cc: cc,
bcc: bcc,
replyTo: replyTo
);
}
}
+2
View File
@@ -26,6 +26,7 @@ export 'email/read_actions.dart';
export 'email/attachment.dart';
export 'email/move_action.dart';
export 'email/important_action.dart';
export 'email/mark_star_action.dart';
// Extensions
export 'extensions/email_address_extension.dart';
@@ -41,6 +42,7 @@ export 'extensions/email_body_part_extension.dart';
export 'extensions/attachment_extension.dart';
export 'extensions/list_email_id_extension.dart';
export 'extensions/mailbox_id_extension.dart';
export 'extensions/list_email_id_extension.dart';
// Download
export 'download/download_task_id.dart';