From 1e054cc1e5ce791aca6ee8df8525aca405c2c59d Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 20 Jun 2025 10:42:41 +0700 Subject: [PATCH] TF-3792 Refactor toast manager Signed-off-by: dab246 --- .../widgets/login_message_widget.dart | 7 +- lib/main/utils/toast_manager.dart | 251 +++++++++--------- 2 files changed, 127 insertions(+), 131 deletions(-) diff --git a/lib/features/login/presentation/widgets/login_message_widget.dart b/lib/features/login/presentation/widgets/login_message_widget.dart index be82e3da6..4149df38e 100644 --- a/lib/features/login/presentation/widgets/login_message_widget.dart +++ b/lib/features/login/presentation/widgets/login_message_widget.dart @@ -54,8 +54,11 @@ class LoginMessageWidget extends StatelessWidget { } else if (failure is GetTokenOIDCFailure && failure.exception is NoSuitableBrowserForOIDCException) { return AppLocalizations.of(context).noSuitableBrowserForOIDC; } else if (failure is FeatureFailure) { - return _toastManager?.getMessageByException(context, failure.exception) - ?? AppLocalizations.of(context).unknownError; + return _toastManager?.getMessageByException( + context, + failure.exception, + useDefaultMessage: true, + ) ?? AppLocalizations.of(context).unknownError; } else { return AppLocalizations.of(context).unknownError; } diff --git a/lib/main/utils/toast_manager.dart b/lib/main/utils/toast_manager.dart index 4cbcda191..e7465abdf 100644 --- a/lib/main/utils/toast_manager.dart +++ b/lib/main/utils/toast_manager.dart @@ -14,7 +14,9 @@ import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart'; +import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_exceptions.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_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/home/data/exceptions/session_exceptions.dart'; @@ -32,7 +34,6 @@ import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_ import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/empty_trash_folder_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart'; -import 'package:tmail_ui_user/main/error/error_method_response_exception_extension.dart'; import 'package:tmail_ui_user/main/exceptions/permission_exception.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -43,7 +44,21 @@ class ToastManager { ToastManager(this.appToast); - String? getMessageByException(BuildContext context, dynamic exception) { + String getDefaultMessageByException(BuildContext context, dynamic exception) { + try { + return AppLocalizations.of(context).unexpectedError(exception.message); + } catch (_) { + return AppLocalizations.of(context).unexpectedError( + exception.toString(), + ); + } + } + + String? getMessageByException( + BuildContext context, + dynamic exception, { + bool useDefaultMessage = false, + }) { if (exception is CanNotFoundBaseUrl) { return AppLocalizations.of(context).requiredUrl; } else if (exception is CanNotFoundUserName) { @@ -52,9 +67,11 @@ class ToastManager { return AppLocalizations.of(context).requiredPassword; } else if (exception is CanNotFoundOIDCLinks) { return AppLocalizations.of(context).ssoNotAvailable; - } else if (exception is CanNotFindToken) { + } else if (exception is CanNotFindToken) { return AppLocalizations.of(context).canNotGetToken; - } else if (exception is ConnectionTimeout || exception is BadGateway || exception is SocketError) { + } else if (exception is ConnectionTimeout || + exception is BadGateway || + exception is SocketError) { return AppLocalizations.of(context).wrongUrlMessage; } else if (exception is BadCredentialsException) { return AppLocalizations.of(context).badCredentials; @@ -67,150 +84,123 @@ class ToastManager { } else if (exception is NoNetworkError) { return AppLocalizations.of(context).youAreOffline; } else if (exception is HandshakeException) { - return AppLocalizations.of(context).handshakeException(exception.osError?.message ?? ''); - } else { - try { - return AppLocalizations.of(context).unexpectedError(exception.message); - } catch(_) { - return AppLocalizations.of(context).unexpectedError(exception.toString()); + return AppLocalizations.of(context) + .handshakeException(exception.osError?.message ?? ''); + } else if (exception is SetMethodException && + exception.mapErrors.isNotEmpty) { + final firstError = exception.mapErrors.values.first; + return '[${firstError.type.value}] ${firstError.description}'; + } else if (exception is ErrorMethodResponseException && + exception.errorResponse is ErrorMethodResponse) { + final errorResponse = exception.errorResponse as ErrorMethodResponse; + return '[${errorResponse.type.value}] ${errorResponse.description}'; + } else if (exception is MethodLevelErrors) { + return '[${exception.type.value}] ${exception.message}'; + } else if (exception is SetError) { + return '[${exception.type.value}] ${exception.description}'; + }else if (exception is PlatformException && + exception.message?.isNotEmpty == true) { + return exception.message!; + } else if (exception is NotGrantedPermissionStorageException) { + return AppLocalizations.of(context) + .youNeedToGrantFilesPermissionToExportFile; + } else if (exception is NotFoundFileInFolderException) { + return AppLocalizations.of(context).noLogsHaveBeenRecordedYet; + } else if (exception is CannotOpenNewWindowException) { + return AppLocalizations.of(context).cannotOpenNewWindow; + } else if (exception is CannotReplyCalendarEventException) { + final mapErrors = exception.mapErrors ?? {}; + if (mapErrors.isNotEmpty) { + final firstError = mapErrors.values.first; + return '[${firstError.type.value}] ${firstError.description}'; } } + + if (useDefaultMessage) { + return getDefaultMessageByException(context, exception); + } else { + return null; + } } void showMessageFailure(FeatureFailure failure) { - if (currentContext == null || currentOverlayContext == null) { - logError('ToastManager::showMessageFailure: Context is null'); + final context = currentContext; + final overlayContext = currentOverlayContext; + if (context == null || overlayContext == null) { + logError('ToastManager::showMessageFailure: Context or OverlayContext is null'); return; } - String? message; final exception = failure.exception; + String? message = getMessageByException(context, exception); if (failure is GetSessionFailure) { - message = getMessageByException(currentContext!, failure.exception) - ?? AppLocalizations.of(currentContext!).unknownError; - } else if (failure is EmptySpamFolderFailure || - (failure is ClearMailboxFailure && failure.mailboxRole == PresentationMailbox.roleSpam)) { - if (exception is SetError) { - message = exception.description?.trim().isNotEmpty == true - ? exception.description - : AppLocalizations.of(currentContext!).emptySpamFolderFailed; - } else if (exception is ErrorMethodResponseException) { - message = exception.errorMessage.isNotEmpty - ? exception.errorMessage - : AppLocalizations.of(currentContext!).emptySpamFolderFailed; - } else if (exception is MethodLevelErrors) { - message = exception.message != null - ? exception.message.toString() - : AppLocalizations.of(currentContext!).emptySpamFolderFailed; - } else { - message = AppLocalizations.of(currentContext!).emptySpamFolderFailed; - } - } else if (failure is EmptyTrashFolderFailure || - (failure is ClearMailboxFailure && failure.mailboxRole == PresentationMailbox.roleTrash)) { - if (exception is SetError) { - message = exception.description?.trim().isNotEmpty == true - ? exception.description - : AppLocalizations.of(currentContext!).emptyTrashFolderFailed; - } else if (exception is MethodLevelErrors) { - message = exception.message != null - ? exception.message.toString() - : AppLocalizations.of(currentContext!).emptyTrashFolderFailed; - } else if (exception is ErrorMethodResponseException) { - message = exception.errorMessage.isNotEmpty - ? exception.errorMessage - : AppLocalizations.of(currentContext!).emptyTrashFolderFailed; - } else { - message = AppLocalizations.of(currentContext!).emptyTrashFolderFailed; - } - } else if (failure is MoveMultipleEmailToMailboxFailure - && failure.emailActionType == EmailActionType.moveToSpam - && failure.moveAction == MoveAction.moving) { - message = AppLocalizations.of(currentContext!).markAsSpamFailed; + message = message ?? + getMessageByException( + context, + exception, + useDefaultMessage: true, + ); + } else if (_isEmptySpamFolderFailure(exception)) { + message = message ?? AppLocalizations.of(context).emptySpamFolderFailed; + } else if (_isEmptyTrashFolderFailure(failure)) { + message = message ?? AppLocalizations.of(context).emptyTrashFolderFailed; + } else if (_isMarkAsSpamFailure(failure)) { + message = message ?? AppLocalizations.of(context).markAsSpamFailed; } else if (failure is SignInTwakeWorkplaceFailure) { - final exception = failure.exception; - if (exception is PlatformException && exception.message?.isNotEmpty == true) { - message = exception.message; - } else { - message = AppLocalizations.of(currentContext!).sigInSaasFailed; - } + message = message ?? AppLocalizations.of(context).sigInSaasFailed; } else if (failure is SignUpTwakeWorkplaceFailure) { - final exception = failure.exception; - if (exception is PlatformException && exception.message?.isNotEmpty == true) { - message = exception.message; - } else { - message = AppLocalizations.of(currentContext!).createTwakeIdFailed; - } + message = message ?? AppLocalizations.of(context).createTwakeIdFailed; } else if (failure is ParseEmailByBlobIdFailure) { - message = AppLocalizations.of(currentContext!).parseEmailByBlobIdFailed; + message = + message ?? AppLocalizations.of(context).parseEmailByBlobIdFailed; } else if (failure is PreviewEmailFromEmlFileFailure) { - if (failure.exception is CannotOpenNewWindowException) { - message = AppLocalizations.of(currentContext!).cannotOpenNewWindow; - } else { - message = AppLocalizations.of(currentContext!).previewEmailFromEMLFileFailed; - } + message = + message ?? AppLocalizations.of(context).previewEmailFromEMLFileFailed; } else if (failure is ExportTraceLogFailure) { - if (failure.exception is NotGrantedPermissionStorageException) { - message = AppLocalizations.of(currentContext!).youNeedToGrantFilesPermissionToExportFile; - } else if (failure.exception is NotFoundFileInFolderException) { - message = AppLocalizations.of(currentContext!).noLogsHaveBeenRecordedYet; - } else { - message = AppLocalizations.of(currentContext!).exportTraceLogFailed; - } + message = message ?? AppLocalizations.of(context).exportTraceLogFailed; } else if (failure is AddRecipientsInForwardingFailure) { - final exception = failure.exception; - if (exception is SetMethodException && exception.mapErrors.isNotEmpty) { - final firstError = exception.mapErrors.values.first; - message = '[${firstError.type.value}] ${firstError.description}'; - } else if (exception is ErrorMethodResponseException && - exception.errorResponse is ErrorMethodResponse) { - final errorResponse = exception.errorResponse as ErrorMethodResponse; - message = '[${errorResponse.type.value}] ${errorResponse.description}'; - } else if (exception is MethodLevelErrors) { - message = '[${exception.type.value}] ${exception.message}'; - } else { - message = AppLocalizations.of(currentContext!).addRecipientsFailed; - } + message = message ?? AppLocalizations.of(context).addRecipientsFailed; } else if (failure is EditLocalCopyInForwardingFailure) { - final exception = failure.exception; - if (exception is SetMethodException && exception.mapErrors.isNotEmpty) { - final firstError = exception.mapErrors.values.first; - message = '[${firstError.type.value}] ${firstError.description}'; - } else if (exception is ErrorMethodResponseException && - exception.errorResponse is ErrorMethodResponse) { - final errorResponse = exception.errorResponse as ErrorMethodResponse; - message = '[${errorResponse.type.value}] ${errorResponse.description}'; - } else if (exception is MethodLevelErrors) { - message = '[${exception.type.value}] ${exception.message}'; - } else { - message = AppLocalizations.of(currentContext!).editLocalCopyInForwardFailed; - } + message = + message ?? AppLocalizations.of(context).editLocalCopyInForwardFailed; } else if (failure is DeleteRecipientInForwardingFailure) { - final exception = failure.exception; - if (exception is SetMethodException && exception.mapErrors.isNotEmpty) { - final firstError = exception.mapErrors.values.first; - message = '[${firstError.type.value}] ${firstError.description}'; - } else if (exception is ErrorMethodResponseException && - exception.errorResponse is ErrorMethodResponse) { - final errorResponse = exception.errorResponse as ErrorMethodResponse; - message = '[${errorResponse.type.value}] ${errorResponse.description}'; - } else if (exception is MethodLevelErrors) { - message = '[${exception.type.value}] ${exception.message}'; - } else { - message = AppLocalizations.of(currentContext!).deleteRecipientsFailed; - } + message = message ?? AppLocalizations.of(context).deleteRecipientsFailed; } else if (failure is CreateNewRuleFilterFailure) { - message = AppLocalizations.of(currentContext!).createFilterRuleFailed; + message = message ?? AppLocalizations.of(context).createFilterRuleFailed; + } else if (failure is CalendarEventReplyFailure) { + message = message ?? + AppLocalizations.of(context).eventReplyWasSentUnsuccessfully; } - - if (message?.isNotEmpty == true) { - appToast.showToastErrorMessage(currentOverlayContext!, message!); + log('ToastManager::showMessageFailure: Message: $message'); + if (message?.trim().isNotEmpty == true) { + appToast.showToastErrorMessage(overlayContext, message!); } } + bool _isEmptySpamFolderFailure(FeatureFailure failure) { + return failure is EmptySpamFolderFailure || + (failure is ClearMailboxFailure && + failure.mailboxRole == PresentationMailbox.roleSpam); + } + + bool _isEmptyTrashFolderFailure(FeatureFailure failure) { + return failure is EmptyTrashFolderFailure || + (failure is ClearMailboxFailure && + failure.mailboxRole == PresentationMailbox.roleTrash); + } + + bool _isMarkAsSpamFailure(FeatureFailure failure) { + return failure is MoveMultipleEmailToMailboxFailure && + failure.emailActionType == EmailActionType.moveToSpam && + failure.moveAction == MoveAction.moving; + } + void showMessageSuccess(Success success) { - if (currentContext == null || currentOverlayContext == null) { - logError('ToastManager::showMessageSuccess: Context is null'); + final context = currentContext; + final overlayContext = currentOverlayContext; + if (context == null || overlayContext == null) { + logError('ToastManager::showMessageSuccess: Context or OverlayContext is null'); return; } @@ -219,15 +209,18 @@ class ToastManager { if (success is ClearMailboxSuccess || success is EmptySpamFolderSuccess || success is EmptyTrashFolderSuccess) { - message = AppLocalizations.of(currentContext!).toast_message_empty_trash_folder_success; + message = + AppLocalizations.of(context).toast_message_empty_trash_folder_success; } else if (success is ExportTraceLogSuccess) { - message = AppLocalizations.of(currentContext!).exportTraceLogSuccess(success.savePath); + message = AppLocalizations.of(context).exportTraceLogSuccess( + success.savePath, + ); } else if (success is CreateNewRuleFilterSuccess) { - message = AppLocalizations.of(currentContext!).newFilterWasCreated; + message = AppLocalizations.of(context).newFilterWasCreated; } - - if (message?.isNotEmpty == true) { - appToast.showToastSuccessMessage(currentOverlayContext!, message!); + log('ToastManager::showMessageSuccess: Message: $message'); + if (message?.trim().isNotEmpty == true) { + appToast.showToastSuccessMessage(overlayContext, message!); } } }