import 'dart:io'; import 'package:core/domain/exceptions/file_exception.dart'; import 'package:core/domain/exceptions/web_session_exception.dart'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.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/utils/app_logger.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_appauth_web/authorization_exception.dart'; import 'package:flutter_svg/svg.dart'; import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart'; import 'package:jmap_dart_client/jmap/core/error/method/exception/error_method_response_exception.dart'; import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; import 'package:labels/extensions/label_extension.dart'; import 'package:model/email/email_action_type.dart'; import 'package:model/email/mark_star_action.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/download/domain/state/parse_email_by_blob_id_state.dart'; import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.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/add_a_label_to_a_thread_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/add_a_label_to_an_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/remove_a_label_from_an_email_state.dart'; import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/labels/domain/state/create_new_label_state.dart'; import 'package:tmail_ui_user/features/labels/domain/state/delete_a_label_state.dart'; import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.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/oauth_authorization_error.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/move_folder_content_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_rule_filter_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/delete_recipient_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/edit_identity_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/edit_local_copy_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/export_trace_log_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/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/exceptions/permission_exception.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class ToastManager { final AppToast appToast; final ImagePaths imagePaths; ToastManager(this.appToast, this.imagePaths); String getDefaultMessageByException( AppLocalizations appLocalizations, dynamic exception, ) { try { return appLocalizations.unexpectedError(exception.message); } catch (_) { return appLocalizations.unexpectedError(exception.toString()); } } String? getMessageByException( AppLocalizations appLocalizations, dynamic exception, { bool useDefaultMessage = false, }) { if (exception is CanNotFoundBaseUrl) { return appLocalizations.requiredUrl; } else if (exception is CanNotFoundUserName) { return appLocalizations.requiredEmail; } else if (exception is CanNotFoundPassword) { return appLocalizations.requiredPassword; } else if (exception is CanNotFoundOIDCLinks) { return appLocalizations.ssoNotAvailable; } else if (exception is CanNotFindToken) { return appLocalizations.canNotGetToken; } else if (exception is ConnectionTimeout || exception is BadGateway || exception is SocketError) { return appLocalizations.wrongUrlMessage; } else if (exception is BadCredentialsException) { return appLocalizations.badCredentials; } else if (exception is ConnectionError) { return appLocalizations.connectionError; } else if (exception is UnknownError && exception.message != null) { return '[${exception.code ?? ''}] ${exception.message}'; } else if (exception is NotFoundSessionException) { return appLocalizations.notFoundSession; } else if (exception is NoNetworkError) { return appLocalizations.youAreOffline; } else if (exception is HandshakeException) { return appLocalizations .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.youNeedToGrantFilesPermissionToExportFile; } else if (exception is NotFoundFileInFolderException) { return appLocalizations.noLogsHaveBeenRecordedYet; } else if (exception is CannotOpenNewWindowException) { return appLocalizations.cannotOpenNewWindow; } else if (exception is CannotReplyCalendarEventException) { final mapErrors = exception.mapErrors ?? {}; if (mapErrors.isNotEmpty) { final firstError = mapErrors.values.first; return '[${firstError.type.value}] ${firstError.description}'; } } else if (exception is ServerError) { return '[${exception.error}] ${exception.message}'; } else if (exception is TemporarilyUnavailable) { return '[${exception.error}] ${exception.message}'; } else if (exception is AutoRedirectToAppAfterStoreAuthorizeDestinationUrlException) { return ''; } if (useDefaultMessage) { return getDefaultMessageByException(appLocalizations, exception); } else { return null; } } void showMessageFailure(FeatureFailure failure) { final context = currentContext; final overlayContext = currentOverlayContext; if (context == null || overlayContext == null) { logWarning('ToastManager::showMessageFailure: Context or OverlayContext is null'); return; } final exception = failure.exception; final appLocalizations = AppLocalizations.of(context); String? message = getMessageByException(appLocalizations, exception); if (failure is GetSessionFailure) { message = message ?? getMessageByException( appLocalizations, exception, useDefaultMessage: true, ); } else if (_isEmptySpamFolderFailure(failure)) { message = message ?? appLocalizations.emptySpamFolderFailed; } else if (_isEmptyTrashFolderFailure(failure)) { message = message ?? appLocalizations.emptyTrashFolderFailed; } else if (_isMarkAsSpamFailure(failure)) { message = message ??appLocalizations.markAsSpamFailed; } else if (_isArchiveMessagesFailure(failure)) { message = message ?? appLocalizations.archiveMessagesFailed; } else if (failure is SignInTwakeWorkplaceFailure) { message = message ?? appLocalizations.sigInSaasFailed; } else if (failure is SignUpTwakeWorkplaceFailure) { message = message ?? appLocalizations.createTwakeIdFailed; } else if (failure is ParseEmailByBlobIdFailure) { message = message ?? appLocalizations.parseEmailByBlobIdFailed; } else if (failure is PreviewEmailFromEmlFileFailure) { message = message ?? appLocalizations.previewEmailFromEMLFileFailed; } else if (failure is ExportTraceLogFailure) { message = message ?? appLocalizations.exportTraceLogFailed; } else if (failure is AddRecipientsInForwardingFailure || failure is AddRecipientsInForwardingSuccessWithSomeCaseFailure) { message = message ?? appLocalizations.addRecipientsFailed; } else if (failure is EditLocalCopyInForwardingFailure || failure is EditLocalCopyInForwardingSuccessWithSomeCaseFailure) { message = message ?? appLocalizations.editLocalCopyInForwardFailed; } else if (failure is DeleteRecipientInForwardingFailure || failure is DeleteRecipientInForwardingSuccessWithSomeCaseFailure) { message = message ?? appLocalizations.deleteRecipientsFailed; } else if (failure is CreateNewRuleFilterFailure) { message = message ?? appLocalizations.createFilterRuleFailed; } else if (failure is CalendarEventReplyFailure) { message = message ?? appLocalizations.eventReplyWasSentUnsuccessfully; } else if (failure is MoveFolderContentFailure) { message = message ?? appLocalizations.moveFolderContentToastMessage; } else if (failure is CreateNewLabelFailure) { message = message ?? appLocalizations.createNewLabelFailure; } else if (failure is AddALabelToAnEmailFailure) { message = message ?? appLocalizations.addLabelToEmailFailureMessage(failure.labelDisplay); } else if (failure is AddALabelToAThreadFailure) { message = message ?? appLocalizations.addLabelToThreadFailureMessage(failure.labelDisplay); } else if (failure is EditLabelFailure) { message = message ?? appLocalizations.editLabelFailure; } else if (failure is RemoveALabelFromAnEmailFailure) { message = message ?? appLocalizations.removeLabelFromEmailFailureMessage( failure.labelDisplay, ); } else if (failure is RemoveALabelFromAThreadFailure) { message = message ?? appLocalizations.removeLabelFromThreadFailureMessage( failure.labelDisplay, ); } else if (failure is DeleteALabelFailure) { message = message ?? appLocalizations.deleteALabelFailure; } 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; } bool _isArchiveMessagesFailure(FeatureFailure failure) { return failure is MoveMultipleEmailToMailboxFailure && failure.emailActionType == EmailActionType.archiveMessage && failure.moveAction == MoveAction.moving; } void showMessageSuccess(Success success) { final context = currentContext; final overlayContext = currentOverlayContext; if (context == null || overlayContext == null) { logWarning('ToastManager::showMessageSuccess: Context or OverlayContext is null'); return; } String? message; final appLocalizations = AppLocalizations.of(context); if (success is ClearMailboxSuccess || success is EmptySpamFolderSuccess || success is EmptyTrashFolderSuccess) { message = appLocalizations.toast_message_empty_trash_folder_success; } else if (success is ExportTraceLogSuccess) { message = appLocalizations.exportTraceLogSuccess( success.savePath, ); } else if (success is CreateNewRuleFilterSuccess) { message = appLocalizations.newFilterWasCreated; } else if (success is EditIdentitySuccess) { if (success.isSetAsDefault) { message = appLocalizations.defaultIdentitySetupSuccessful; } else { message = appLocalizations.you_are_changed_your_identity_successfully; } } else if (success is MarkAsStarEmailSuccess) { message = success.markStarAction == MarkStarAction.markStar ? appLocalizations.mailHasBeenStarred : appLocalizations.mailHasBeenUnstarred; } else if (success is CreateNewLabelSuccess) { message = appLocalizations.createLabelSuccessfullyMessage( success.newLabel.safeDisplayName, ); } else if (success is EditLabelSuccess) { message = appLocalizations.editLabelSuccessfullyMessage( success.newLabel.safeDisplayName, ); } else if (success is AddALabelToAnEmailSuccess) { message = appLocalizations.addLabelToEmailSuccessfullyMessage( success.labelDisplay, ); } else if (success is AddALabelToAThreadSuccess) { message = appLocalizations.addLabelToThreadSuccessfullyMessage( success.labelDisplay, ); } else if (success is RemoveALabelFromAnEmailSuccess) { message = appLocalizations.removeLabelFromEmailSuccessfullyMessage( success.labelDisplay, ); } else if (success is RemoveALabelFromAThreadSuccess) { message = appLocalizations.removeLabelFromThreadSuccessfullyMessage( success.labelDisplay, ); } else if (success is DeleteALabelSuccess) { message = appLocalizations.deleteLabelSuccessfullyMessage( success.deletedLabel.safeDisplayName, ); } log('ToastManager::showMessageSuccess: Message: $message'); if (message?.trim().isNotEmpty == true) { appToast.showToastSuccessMessage(overlayContext, message!); } } void showMessageSuccessWithAction({ required Success success, required VoidCallback onActionCallback, }) { final context = currentContext; final overlayContext = currentOverlayContext; if (context == null || overlayContext == null) { logWarning('$runtimeType::showMessageSuccessWithAction: Context or OverlayContext is null'); return; } String? message; final appLocalizations = AppLocalizations.of(context); if (success is MoveFolderContentSuccess) { message = appLocalizations.movedToFolder( success.request.destinationMailboxDisplayName, ); } log('$runtimeType::showMessageSuccessWithAction: Message: $message'); if (message?.trim().isNotEmpty == true) { appToast.showToastMessage( overlayContext, message!, actionName: appLocalizations.undo, onActionClick: onActionCallback, leadingSVGIcon: imagePaths.icFolderMailbox, leadingSVGIconColor: Colors.white, backgroundColor: AppColor.toastSuccessBackgroundColor, textColor: Colors.white, actionIcon: SvgPicture.asset(imagePaths.icUndo), ); } } }