TF-616 Add MailboxIsolateWorker to handle MarkAsRead in isolate

This commit is contained in:
dab246
2022-06-30 11:13:47 +07:00
committed by Dat H. Pham
parent 9be95178b7
commit 51a76beddf
3 changed files with 224 additions and 0 deletions
@@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
class MailboxMarkAsReadArguments with EquatableMixin {
final AccountId accountId;
final MailboxId mailboxId;
final ThreadAPI threadAPI;
final EmailAPI emailAPI;
MailboxMarkAsReadArguments(
this.threadAPI,
this.emailAPI,
this.accountId,
this.mailboxId);
@override
List<Object?> get props => [accountId, mailboxId];
}
@@ -0,0 +1,138 @@
import 'dart:async';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.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';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/email_property.dart';
import 'package:model/email/read_actions.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
import 'package:worker_manager/worker_manager.dart';
class MailboxIsolateWorker {
final ThreadAPI _threadApi;
final EmailAPI _emailApi;
final Executor _isolateExecutor;
MailboxIsolateWorker(this._threadApi, this._emailApi, this._isolateExecutor);
Future<List<Email>> markAsMailboxRead(
AccountId accountId,
MailboxId mailboxId,
int totalEmailUnread,
StreamController<Either<Failure, Success>> onProgressController
) async {
final result = await _isolateExecutor.execute(
arg1: ArgumentsSendPort(MailboxMarkAsReadArguments(
_threadApi,
_emailApi,
accountId,
mailboxId)),
fun1: (arguments) => _handleMarkAsMailboxReadAction(arguments),
onUpdateProgress: (value) {
if (value is List<Email>) {
log('MailboxIsolateWorker::markAsMailboxRead(): onUpdateProgress: COUNT ${value.length}');
log('MailboxIsolateWorker::markAsMailboxRead(): onUpdateProgress: TOTAL $totalEmailUnread');
log('MailboxIsolateWorker::markAsMailboxRead(): onUpdateProgress: PERCENT ${value.length / totalEmailUnread}');
log('MailboxIsolateWorker::markAsMailboxRead(): onUpdateProgress: ${((value.length / totalEmailUnread) * 100).toInt()}%');
onProgressController.add(Right(UpdatingMarkAsMailboxReadState(
mailboxId: mailboxId,
totalUnread: totalEmailUnread,
countRead: value.length)));
}
});
return result;
}
static Future<List<Email>> _handleMarkAsMailboxReadAction(dynamic argumentsAction) async {
if (argumentsAction is! ArgumentsSendPort) {
log('MailboxIsolateWorker::_handleMarkAsMailboxReadAction(): argumentsAction NOT ArgumentsSendPort');
return List.empty();
}
final args = argumentsAction.argument as MailboxMarkAsReadArguments;
final sendPort = argumentsAction.sendPort;
if (sendPort != null) {
log('MailboxIsolateWorker::_handleMarkAsMailboxReadAction(): SEND_PORT NOT NULL');
} else {
log('MailboxIsolateWorker::_handleMarkAsMailboxReadAction(): SEND_PORT NULL');
}
List<Email> emailListCompleted = List.empty(growable: true);
try {
bool mailboxHasEmails = true;
UTCDate? lastReceivedDate;
EmailId? lastEmailId;
while (mailboxHasEmails) {
final emailResponse = await args.threadAPI
.getAllEmail(args.accountId,
limit: UnsignedInt(30),
filter: EmailFilterCondition(
inMailbox: args.mailboxId,
notKeyword: KeyWordIdentifier.emailSeen.value,
before: lastReceivedDate),
sort: <Comparator>{}..add(
EmailComparator(EmailComparatorProperty.receivedAt)
..setIsAscending(false)),
properties: Properties({
EmailProperty.id,
EmailProperty.keywords,
EmailProperty.receivedAt,
}))
.then((response) {
var listEmails = response.emailList;
if (listEmails != null && listEmails.isNotEmpty && lastEmailId != null) {
listEmails = listEmails
.where((email) => email.id != lastEmailId)
.toList();
}
return EmailsResponse(emailList: listEmails, state: response.state);
});
final listEmailUnread = emailResponse.emailList;
log('MailboxIsolateWorker::_handleMarkAsMailboxRead(): listEmailUnread: ${listEmailUnread?.length}');
if (listEmailUnread == null || listEmailUnread.isEmpty) {
mailboxHasEmails = false;
} else {
lastEmailId = listEmailUnread.last.id;
lastReceivedDate = listEmailUnread.last.receivedAt;
final result = await args.emailAPI.markAsRead(
args.accountId,
listEmailUnread,
ReadActions.markAsRead);
log('MailboxIsolateWorker::_handleMarkAsMailboxRead(): MARK_READ: ${result.length}');
emailListCompleted.addAll(result);
if (sendPort != null) {
sendPort.send(ValueUpdate(emailListCompleted));
}
}
}
} catch (e) {
log('MailboxIsolateWorker::_handleMarkAsMailboxRead(): ERROR: $e');
}
log('MailboxIsolateWorker::_handleMarkAsMailboxRead(): TOTAL_READ: ${emailListCompleted.length}');
return emailListCompleted;
}
}
@@ -0,0 +1,63 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
class MarkAsMailboxReadLoading extends UIState {
MarkAsMailboxReadLoading();
@override
List<Object?> get props => [];
}
class UpdatingMarkAsMailboxReadState extends UIState {
final MailboxId mailboxId;
final int totalUnread;
final int countRead;
UpdatingMarkAsMailboxReadState({
required this.mailboxId,
required this.totalUnread,
required this.countRead});
@override
List<Object?> get props => [mailboxId, countRead, totalUnread];
}
class MarkAsMailboxReadAllSuccess extends UIState {
final MailboxName mailboxName;
MarkAsMailboxReadAllSuccess(this.mailboxName);
@override
List<Object?> get props => [mailboxName];
}
class MarkAsMailboxReadHasSomeEmailFailure extends UIState {
final MailboxName mailboxName;
final int countEmailsRead;
MarkAsMailboxReadHasSomeEmailFailure(this.mailboxName, this.countEmailsRead);
@override
List<Object?> get props => [mailboxName, countEmailsRead];
}
class MarkAsMailboxReadAllFailure extends FeatureFailure {
MarkAsMailboxReadAllFailure();
@override
List<Object?> get props => [];
}
class MarkAsMailboxReadFailure extends FeatureFailure {
final dynamic exception;
MarkAsMailboxReadFailure(this.exception);
@override
List<Object> get props => [exception];
}