TF-4053 Add interactor/datasource/repository for move folder content action

This commit is contained in:
dab246
2025-10-29 13:19:25 +07:00
committed by Dat H. Pham
parent ccdbd798d9
commit 369316f50d
19 changed files with 695 additions and 188 deletions
@@ -1,6 +1,9 @@
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' hide State;
import 'package:flutter/material.dart' hide State;
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
@@ -32,6 +35,7 @@ import 'package:model/error_type_handler/set_method_error_handler_mixin.dart';
import 'package:model/mailbox/mailbox_constants.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/mail_api_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart';
@@ -41,17 +45,18 @@ import 'package:tmail_ui_user/features/mailbox/domain/extensions/role_extension.
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/get_mailbox_by_role_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_subaddressing_action.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_subscribe_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_folder_content_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
import 'package:uuid/uuid.dart';
class MailboxAPI with HandleSetErrorMixin {
class MailboxAPI with HandleSetErrorMixin, MailAPIMixin {
final HttpClient httpClient;
final Uuid _uuid;
@@ -636,4 +641,23 @@ class MailboxAPI with HandleSetErrorMixin {
throw NotFoundClearMailboxResponseException();
}
}
Future<void> moveFolderContent({
required Session session,
required AccountId accountId,
required MoveFolderContentRequest request,
StreamController<Either<Failure, Success>>? onProgressController,
}) async {
return await moveAllEmailsBetweenFolders(
httpClient: httpClient,
accountId: accountId,
session: session,
moveAction: request.moveAction,
currentMailboxId: request.mailboxId,
destinationMailboxId: request.destinationMailboxId,
totalEmails: request.totalEmails,
markAsRead: request.markAsRead,
onProgressController: onProgressController,
);
}
}
@@ -23,8 +23,13 @@ import 'package:model/extensions/list_email_extension.dart';
import 'package:tmail_ui_user/features/base/isolate/background_isolate_binary_messenger/background_isolate_binary_messenger.dart';
import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/move_folder_content_isolate_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_folder_content_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/move_folder_content_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:tmail_ui_user/main/exceptions/isolate_exception.dart';
@@ -213,4 +218,101 @@ class MailboxIsolateWorker {
log('MailboxIsolateWorker::_handleMarkAsMailboxReadActionOnWeb(): TOTAL_READ: ${emailIdsCompleted.length}');
return emailIdsCompleted;
}
Future<void> moveFolderContent({
required Session session,
required AccountId accountId,
required MoveFolderContentRequest request,
StreamController<Either<Failure, Success>>? onProgressController,
}) async {
final rootIsolateToken = RootIsolateToken.instance;
if (rootIsolateToken == null) {
throw CanNotGetRootIsolateToken();
}
final countEmailsCompleted = await _isolateExecutor.execute(
arg1: MoveFolderContentIsolateArguments(
session: session,
accountId: accountId,
threadAPI: _threadApi,
emailAPI: _emailApi,
currentMailboxId: request.mailboxId,
destinationMailboxId: request.destinationMailboxId,
isolateToken: rootIsolateToken,
markAsRead: request.markAsRead,
),
fun1: _moveFolderContentIsolateMethod,
notification: (value) {
if (value is int) {
log('$runtimeType::moveFolderContent(): Progress percent is ${value / request.totalEmails}');
onProgressController?.add(
Right<Failure, Success>(MoveFolderContentProgressState(
request.mailboxId,
value,
request.totalEmails,
)),
);
}
},
);
if (request.moveAction == MoveAction.moving &&
countEmailsCompleted < request.totalEmails &&
request.totalEmails > 0) {
throw CannotMoveAllEmailException();
}
}
static Future<int> _moveFolderContentIsolateMethod(
MoveFolderContentIsolateArguments args,
TypeSendPort sendPort,
) async {
final rootIsolateToken = args.isolateToken;
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
await HiveCacheConfig.instance.setUp();
int countEmailsCompleted = 0;
bool hasEmails = true;
Email? lastEmail;
final threadAPI = args.threadAPI;
final httpClient = threadAPI.httpClient;
final session = args.session;
final accountId = args.accountId;
final currentMailboxId = args.currentMailboxId;
final destinationMailboxId = args.destinationMailboxId;
final markAsRead = args.markAsRead;
while (hasEmails) {
final listEmails = await threadAPI.getLatestEmails(
httpClient: httpClient,
session: session,
accountId: accountId,
mailboxId: currentMailboxId,
lastEmail: lastEmail,
);
log('MailboxIsolateWorker::_moveFolderContentIsolateMethod(): Length of emails = ${listEmails.length}');
if (listEmails.isEmpty) {
hasEmails = false;
} else {
hasEmails = true;
lastEmail = listEmails.last;
final movedEmails = await threadAPI.moveEmailsBetweenMailboxes(
httpClient: httpClient,
session: session,
accountId: accountId,
emailIds: listEmails.listEmailIds,
currentMailboxId: currentMailboxId,
destinationMailboxId: destinationMailboxId,
markAsRead: markAsRead,
);
countEmailsCompleted += movedEmails.emailIdsSuccess.length;
sendPort.send(countEmailsCompleted);
}
}
log('MailboxIsolateWorker::_moveFolderContentIsolateMethod(): Total emails moved = $countEmailsCompleted');
return countEmailsCompleted;
}
}