TF-616 Add MailboxIsolateWorker to handle MarkAsRead in isolate
This commit is contained in:
@@ -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];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user