TF-3707 Handle empty spam folder with clear mailbox method

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-05-06 17:47:57 +07:00
committed by Dat H. Pham
parent 322c449d49
commit afbebb7eb7
6 changed files with 94 additions and 39 deletions
@@ -8,14 +8,16 @@ class ClearingMailbox extends LoadingState {}
class ClearMailboxSuccess extends UIState { class ClearMailboxSuccess extends UIState {
final UnsignedInt totalDeletedMessages; final UnsignedInt totalDeletedMessages;
final MailboxId mailboxId; final MailboxId mailboxId;
final Role mailboxRole;
ClearMailboxSuccess(this.mailboxId, this.totalDeletedMessages); ClearMailboxSuccess(this.mailboxId, this.mailboxRole, this.totalDeletedMessages);
@override @override
List<Object> get props => [mailboxId, totalDeletedMessages]; List<Object> get props => [mailboxId, mailboxRole, totalDeletedMessages];
} }
class ClearMailboxFailure extends FeatureFailure { class ClearMailboxFailure extends FeatureFailure {
final Role mailboxRole;
ClearMailboxFailure(dynamic exception) : super(exception: exception); ClearMailboxFailure(this.mailboxRole, {dynamic exception}) : super(exception: exception);
} }
@@ -16,6 +16,7 @@ class ClearMailboxInteractor {
Session session, Session session,
AccountId accountId, AccountId accountId,
MailboxId mailboxId, MailboxId mailboxId,
Role mailboxRole,
) async* { ) async* {
try { try {
yield Right<Failure, Success>(ClearingMailbox()); yield Right<Failure, Success>(ClearingMailbox());
@@ -24,9 +25,13 @@ class ClearMailboxInteractor {
accountId, accountId,
mailboxId, mailboxId,
); );
yield Right<Failure, Success>(ClearMailboxSuccess(mailboxId, totalDeletedMessages)); yield Right<Failure, Success>(ClearMailboxSuccess(
mailboxId,
mailboxRole,
totalDeletedMessages,
));
} catch (e) { } catch (e) {
yield Left<Failure, Success>(ClearMailboxFailure(e)); yield Left<Failure, Success>(ClearMailboxFailure(mailboxRole, exception: e));
} }
} }
} }
@@ -492,6 +492,8 @@ class MailboxDashBoardController extends ReloadableController
isSenderImportantFlagEnabled.value = true; isSenderImportantFlagEnabled.value = true;
} else if (failure is GetAllIdentitiesFailure) { } else if (failure is GetAllIdentitiesFailure) {
_handleGetAllIdentitiesFailure(); _handleGetAllIdentitiesFailure();
} else if (failure is ClearMailboxFailure) {
clearMailboxFailure(failure);
} }
} }
@@ -1617,14 +1619,24 @@ class MailboxDashBoardController extends ReloadableController
final trashMailboxId = trashFolderId ?? mapDefaultMailboxIdByRole[PresentationMailbox.roleTrash]; final trashMailboxId = trashFolderId ?? mapDefaultMailboxIdByRole[PresentationMailbox.roleTrash];
final accountId = this.accountId.value; final accountId = this.accountId.value;
if (sessionCurrent == null ||
accountId == null || if (accountId == null || sessionCurrent == null) {
trashMailboxId == null) { consumeState(Stream.value(Left(EmptyTrashFolderFailure(NotFoundSessionException()))));
return;
}
if (trashMailboxId == null) {
consumeState(Stream.value(Left(EmptyTrashFolderFailure(NotFoundMailboxException()))));
return; return;
} }
if (CapabilityIdentifier.jmapMailboxClear.isSupported(sessionCurrent!, accountId)) { if (CapabilityIdentifier.jmapMailboxClear.isSupported(sessionCurrent!, accountId)) {
clearMailbox(sessionCurrent!, accountId, trashMailboxId); clearMailbox(
sessionCurrent!,
accountId,
trashMailboxId,
PresentationMailbox.roleTrash,
);
} else { } else {
final totalEmailsInTrash = totalEmails == 0 final totalEmailsInTrash = totalEmails == 0
? mapMailboxById[trashMailboxId]?.countTotalEmails ?? 0 ? mapMailboxById[trashMailboxId]?.countTotalEmails ?? 0
@@ -1647,11 +1659,8 @@ class MailboxDashBoardController extends ReloadableController
emailIds: success.emailIds, emailIds: success.emailIds,
affectedMailboxId: success.mailboxId, affectedMailboxId: success.mailboxId,
); );
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastSuccessMessage( toastManager.showMessageSuccess(success);
currentOverlayContext!,
AppLocalizations.of(currentContext!).toast_message_empty_trash_folder_success);
}
} }
void _deleteMultipleEmailsPermanently(List<PresentationEmail> listEmails, {Function? onCancelSelectionEmail}) { void _deleteMultipleEmailsPermanently(List<PresentationEmail> listEmails, {Function? onCancelSelectionEmail}) {
@@ -2563,8 +2572,9 @@ class MailboxDashBoardController extends ReloadableController
onCancelSelectionEmail?.call(); onCancelSelectionEmail?.call();
spamFolderId ??= spamMailboxId; spamFolderId ??= spamMailboxId;
final accountId = this.accountId.value;
if (accountId.value == null || sessionCurrent == null) { if (accountId == null || sessionCurrent == null) {
consumeState(Stream.value(Left(EmptySpamFolderFailure(NotFoundSessionException())))); consumeState(Stream.value(Left(EmptySpamFolderFailure(NotFoundSessionException()))));
return; return;
} }
@@ -2574,13 +2584,22 @@ class MailboxDashBoardController extends ReloadableController
return; return;
} }
consumeState(_emptySpamFolderInteractor.execute( if (CapabilityIdentifier.jmapMailboxClear.isSupported(sessionCurrent!, accountId)) {
sessionCurrent!, clearMailbox(
accountId.value!, sessionCurrent!,
spamFolderId, accountId,
totalEmails, spamFolderId,
_progressStateController PresentationMailbox.roleSpam,
)); );
} else {
consumeState(_emptySpamFolderInteractor.execute(
sessionCurrent!,
accountId,
spamFolderId,
totalEmails,
_progressStateController,
));
}
} }
void _emptySpamFolderSuccess(EmptySpamFolderSuccess success) { void _emptySpamFolderSuccess(EmptySpamFolderSuccess success) {
@@ -2590,11 +2609,8 @@ class MailboxDashBoardController extends ReloadableController
emailIds: success.emailIds, emailIds: success.emailIds,
affectedMailboxId: success.mailboxId, affectedMailboxId: success.mailboxId,
); );
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastSuccessMessage( toastManager.showMessageSuccess(success);
currentOverlayContext!,
AppLocalizations.of(currentContext!).toast_message_empty_trash_folder_success);
}
} }
bool isEmptySpamBannerEnabledOnWeb( bool isEmptySpamBannerEnabledOnWeb(
@@ -6,31 +6,38 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
extension HandleClearMailboxExtension on MailboxDashBoardController { extension HandleClearMailboxExtension on MailboxDashBoardController {
void clearMailbox(Session session, AccountId accountId, MailboxId mailboxId) { void clearMailbox(
Session session,
AccountId accountId,
MailboxId mailboxId,
Role mailboxRole,
) {
viewStateMailboxActionProgress.value = Right(ClearingMailbox());
consumeState(clearMailboxInteractor.execute( consumeState(clearMailboxInteractor.execute(
session, session,
accountId, accountId,
mailboxId, mailboxId,
mailboxRole,
)); ));
} }
void clearMailboxSuccess(ClearMailboxSuccess success) { void clearMailboxSuccess(ClearMailboxSuccess success) {
viewStateMailboxActionProgress.value = Right(UIState.idle); viewStateMailboxActionProgress.value = Right(UIState.idle);
if (currentOverlayContext != null && currentContext != null) { toastManager.showMessageSuccess(success);
appToast.showToastSuccessMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).toast_message_empty_trash_folder_success,
);
}
if (selectedMailbox.value?.id == success.mailboxId) { if (selectedMailbox.value?.id == success.mailboxId) {
emailsInCurrentMailbox.clear(); emailsInCurrentMailbox.clear();
} }
} }
void clearMailboxFailure(ClearMailboxFailure failure) {
viewStateMailboxActionProgress.value = Right(UIState.idle);
toastManager.showMessageFailure(failure);
}
} }
@@ -3,6 +3,7 @@ import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.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/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/mark_mailbox_as_read_loading_banner_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/mark_mailbox_as_read_loading_banner_style.dart';
import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart';
@@ -20,7 +21,7 @@ class MarkMailboxAsReadLoadingBanner extends StatelessWidget with AppLoaderMixin
return viewState.fold( return viewState.fold(
(failure) => const SizedBox.shrink(), (failure) => const SizedBox.shrink(),
(success) { (success) {
if (success is MarkAsMailboxReadLoading) { if (success is MarkAsMailboxReadLoading || success is ClearingMailbox) {
return Padding( return Padding(
padding: MarkMailboxAsReadLoadingBannerStyle.bannerMargin, padding: MarkMailboxAsReadLoadingBannerStyle.bannerMargin,
child: horizontalLoadingWidget); child: horizontalLoadingWidget);
+26 -2
View File
@@ -2,11 +2,13 @@ import 'dart:io';
import 'package:core/domain/exceptions/web_session_exception.dart'; import 'package:core/domain/exceptions/web_session_exception.dart';
import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/app_toast.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:model/email/email_action_type.dart'; import 'package:model/email/email_action_type.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/parse_email_by_blob_id_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/preview_email_from_eml_file_state.dart';
@@ -14,6 +16,7 @@ import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.d
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart';
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart'; import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart';
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart'; import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart';
@@ -73,9 +76,11 @@ class ToastManager {
if (failure is GetSessionFailure) { if (failure is GetSessionFailure) {
message = getMessageByException(currentContext!, failure.exception) message = getMessageByException(currentContext!, failure.exception)
?? AppLocalizations.of(currentContext!).unknownError; ?? AppLocalizations.of(currentContext!).unknownError;
} else if (failure is EmptySpamFolderFailure) { } else if (failure is EmptySpamFolderFailure ||
(failure is ClearMailboxFailure && failure.mailboxRole == PresentationMailbox.roleSpam)) {
message = AppLocalizations.of(currentContext!).emptySpamFolderFailed; message = AppLocalizations.of(currentContext!).emptySpamFolderFailed;
} else if (failure is EmptyTrashFolderFailure) { } else if (failure is EmptyTrashFolderFailure ||
(failure is ClearMailboxFailure && failure.mailboxRole == PresentationMailbox.roleTrash)) {
message = AppLocalizations.of(currentContext!).emptyTrashFolderFailed; message = AppLocalizations.of(currentContext!).emptyTrashFolderFailed;
} else if (failure is MoveMultipleEmailToMailboxFailure } else if (failure is MoveMultipleEmailToMailboxFailure
&& failure.emailActionType == EmailActionType.moveToSpam && failure.emailActionType == EmailActionType.moveToSpam
@@ -109,4 +114,23 @@ class ToastManager {
appToast.showToastErrorMessage(currentOverlayContext!, message!); appToast.showToastErrorMessage(currentOverlayContext!, message!);
} }
} }
void showMessageSuccess(Success success) {
if (currentContext == null || currentOverlayContext == null) {
logError('ToastManager::showMessageSuccess: Context is null');
return;
}
String? message;
if (success is ClearMailboxSuccess ||
success is EmptySpamFolderSuccess ||
success is EmptyTrashFolderSuccess) {
message = AppLocalizations.of(currentContext!).toast_message_empty_trash_folder_success;
}
if (message?.isNotEmpty == true) {
appToast.showToastSuccessMessage(currentOverlayContext!, message!);
}
}
} }