TF-2667 Add cancel button in progress send message dialog

This commit is contained in:
dab246
2024-03-12 12:53:41 +07:00
committed by Dat H. Pham
parent ae6341532c
commit f2b70aec48
16 changed files with 215 additions and 46 deletions
@@ -0,0 +1 @@
class SendingEmailCanceledException implements Exception {}
@@ -53,4 +53,6 @@ class SendEmailFailure extends FeatureFailure {
mailboxRequest, mailboxRequest,
sendingEmailActionType, sendingEmailActionType,
]; ];
} }
class CancelSendingEmail extends LoadingState {}
@@ -2,10 +2,12 @@ import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart' as dartz; import 'package:dartz/dartz.dart' as dartz;
import 'package:dio/dio.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart';
import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart';
import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
@@ -15,6 +17,7 @@ import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
class CreateNewAndSendEmailInteractor { class CreateNewAndSendEmailInteractor {
final EmailRepository _emailRepository; final EmailRepository _emailRepository;
@@ -27,7 +30,10 @@ class CreateNewAndSendEmailInteractor {
this._composerRepository, this._composerRepository,
); );
Stream<dartz.Either<Failure, Success>> execute(CreateEmailRequest createEmailRequest) async* { Stream<dartz.Either<Failure, Success>> execute({
required CreateEmailRequest createEmailRequest,
CancelToken? cancelToken
}) async* {
SendingEmailArguments? sendingEmailArguments; SendingEmailArguments? sendingEmailArguments;
try { try {
yield dartz.Right<Failure, Success>(GenerateEmailLoading()); yield dartz.Right<Failure, Success>(GenerateEmailLoading());
@@ -46,14 +52,16 @@ class CreateNewAndSendEmailInteractor {
sendingEmailArguments.session, sendingEmailArguments.session,
sendingEmailArguments.accountId, sendingEmailArguments.accountId,
sendingEmailArguments.emailRequest, sendingEmailArguments.emailRequest,
mailboxRequest: sendingEmailArguments.mailboxRequest mailboxRequest: sendingEmailArguments.mailboxRequest,
cancelToken: cancelToken
); );
if (sendingEmailArguments.emailRequest.emailIdDestroyed != null) { if (sendingEmailArguments.emailRequest.emailIdDestroyed != null) {
await _deleteOldDraftsEmail( await _deleteOldDraftsEmail(
session: sendingEmailArguments.session, session: sendingEmailArguments.session,
accountId: sendingEmailArguments.accountId, accountId: sendingEmailArguments.accountId,
draftEmailId: sendingEmailArguments.emailRequest.emailIdDestroyed! draftEmailId: sendingEmailArguments.emailRequest.emailIdDestroyed!,
cancelToken: cancelToken
); );
} }
@@ -69,13 +77,23 @@ class CreateNewAndSendEmailInteractor {
} }
} catch (e) { } catch (e) {
logError('CreateNewAndSendEmailInteractor::execute: Exception: $e'); logError('CreateNewAndSendEmailInteractor::execute: Exception: $e');
yield dartz.Left<Failure, Success>(SendEmailFailure( if (e is UnknownError && e.message is List<SendingEmailCanceledException>) {
exception: e, yield dartz.Left<Failure, Success>(SendEmailFailure(
session: sendingEmailArguments?.session, exception: SendingEmailCanceledException(),
accountId: sendingEmailArguments?.accountId, session: sendingEmailArguments?.session,
emailRequest: sendingEmailArguments?.emailRequest, accountId: sendingEmailArguments?.accountId,
mailboxRequest: sendingEmailArguments?.mailboxRequest, emailRequest: sendingEmailArguments?.emailRequest,
)); mailboxRequest: sendingEmailArguments?.mailboxRequest,
));
} else {
yield dartz.Left<Failure, Success>(SendEmailFailure(
exception: e,
session: sendingEmailArguments?.session,
accountId: sendingEmailArguments?.accountId,
emailRequest: sendingEmailArguments?.emailRequest,
mailboxRequest: sendingEmailArguments?.mailboxRequest,
));
}
} }
} }
@@ -113,13 +131,15 @@ class CreateNewAndSendEmailInteractor {
Future<void> _deleteOldDraftsEmail({ Future<void> _deleteOldDraftsEmail({
required Session session, required Session session,
required AccountId accountId, required AccountId accountId,
required EmailId draftEmailId required EmailId draftEmailId,
CancelToken? cancelToken
}) async { }) async {
try { try {
await _emailRepository.deleteEmailPermanently( await _emailRepository.deleteEmailPermanently(
session, session,
accountId, accountId,
draftEmailId draftEmailId,
cancelToken: cancelToken
); );
} catch (e) { } catch (e) {
logError('CreateNewAndSendEmailInteractor::_deleteOldDraftsEmail: Exception: $e'); logError('CreateNewAndSendEmailInteractor::_deleteOldDraftsEmail: Exception: $e');
@@ -7,6 +7,7 @@ import 'package:core/core.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:desktop_drop/desktop_drop.dart'; import 'package:desktop_drop/desktop_drop.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart'; import 'package:filesize/filesize.dart';
@@ -29,6 +30,7 @@ import 'package:super_tag_editor/tag_editor.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/base/state/base_ui_state.dart'; import 'package:tmail_ui_user/features/base/state/base_ui_state.dart';
import 'package:tmail_ui_user/features/base/state/button_state.dart'; import 'package:tmail_ui_user/features/base/state/button_state.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart';
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart';
@@ -802,12 +804,17 @@ class ComposerController extends BaseController with DragDropFileMixin {
} }
final emailContent = await _getContentInEditor(); final emailContent = await _getContentInEditor();
final cancelToken = CancelToken();
final resultState = await _showSendingMessageDialog(emailContent: emailContent); final resultState = await _showSendingMessageDialog(
emailContent: emailContent,
cancelToken: cancelToken
);
log('ComposerController::_handleSendMessages: resultState = $resultState');
if (resultState is SendEmailSuccess) { if (resultState is SendEmailSuccess) {
_sendButtonState = ButtonState.enabled; _sendButtonState = ButtonState.enabled;
_closeComposerAction(result: resultState); _closeComposerAction(result: resultState);
} else if (resultState is SendEmailFailure && resultState.exception is SendingEmailCanceledException) {
_sendButtonState = ButtonState.enabled;
} else if ((resultState is SendEmailFailure || resultState is GenerateEmailFailure) && context.mounted) { } else if ((resultState is SendEmailFailure || resultState is GenerateEmailFailure) && context.mounted) {
_showConfirmDialogWhenSendMessageFailure( _showConfirmDialogWhenSendMessageFailure(
context: context, context: context,
@@ -818,7 +825,10 @@ class ComposerController extends BaseController with DragDropFileMixin {
} }
} }
Future<dynamic> _showSendingMessageDialog({required String emailContent}) { Future<dynamic> _showSendingMessageDialog({
required String emailContent,
CancelToken? cancelToken
}) {
return Get.dialog( return Get.dialog(
PointerInterceptor( PointerInterceptor(
child: SendingMessageDialogView( child: SendingMessageDialogView(
@@ -847,13 +857,19 @@ class ComposerController extends BaseController with DragDropFileMixin {
references: composerArguments.value!.references, references: composerArguments.value!.references,
emailSendingQueue: composerArguments.value!.sendingEmail emailSendingQueue: composerArguments.value!.sendingEmail
), ),
createNewAndSendEmailInteractor: _createNewAndSendEmailInteractor createNewAndSendEmailInteractor: _createNewAndSendEmailInteractor,
onCancelSendingEmailAction: _handleCancelSendingMessage,
cancelToken: cancelToken,
), ),
), ),
barrierColor: AppColor.colorDefaultCupertinoActionSheet, barrierColor: AppColor.colorDefaultCupertinoActionSheet,
); );
} }
void _handleCancelSendingMessage({CancelToken? cancelToken}) {
cancelToken?.cancel([SendingEmailCanceledException()]);
}
void _showConfirmDialogWhenSendMessageFailure({ void _showConfirmDialogWhenSendMessageFailure({
required BuildContext context, required BuildContext context,
required FeatureFailure failure required FeatureFailure failure
@@ -5,26 +5,36 @@ import 'package:core/presentation/extensions/capitalize_extension.dart';
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.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/state/success.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart' as dartz; import 'package:dartz/dartz.dart' as dartz;
import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart';
import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.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/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
typedef OnCancelSendingEmailAction = Function({CancelToken? cancelToken});
class SendingMessageDialogView extends StatefulWidget { class SendingMessageDialogView extends StatefulWidget {
final CreateEmailRequest createEmailRequest; final CreateEmailRequest createEmailRequest;
final CreateNewAndSendEmailInteractor createNewAndSendEmailInteractor; final CreateNewAndSendEmailInteractor createNewAndSendEmailInteractor;
final OnCancelSendingEmailAction? onCancelSendingEmailAction;
final CancelToken? cancelToken;
const SendingMessageDialogView({ const SendingMessageDialogView({
super.key, super.key,
required this.createEmailRequest, required this.createEmailRequest,
required this.createNewAndSendEmailInteractor, required this.createNewAndSendEmailInteractor,
this.onCancelSendingEmailAction,
this.cancelToken,
}); });
@override @override
@@ -40,7 +50,10 @@ class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
void initState() { void initState() {
super.initState(); super.initState();
_streamSubscription = widget.createNewAndSendEmailInteractor _streamSubscription = widget.createNewAndSendEmailInteractor
.execute(widget.createEmailRequest) .execute(
createEmailRequest: widget.createEmailRequest,
cancelToken: widget.cancelToken
)
.listen( .listen(
_handleDataStream, _handleDataStream,
onError: _handleErrorStream onError: _handleErrorStream
@@ -66,7 +79,11 @@ class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
void _handleErrorStream(Object error, StackTrace stackTrace) { void _handleErrorStream(Object error, StackTrace stackTrace) {
logError('_SendingMessageDialogViewState::_handleErrorStream: Exception = $error'); logError('_SendingMessageDialogViewState::_handleErrorStream: Exception = $error');
popBack(result: SendEmailFailure(exception: error)); if (error is UnknownError && error.message is List<SendingEmailCanceledException>) {
popBack(result: SendEmailFailure(exception: SendingEmailCanceledException()));
} else {
popBack(result: SendEmailFailure(exception: error));
}
} }
@override @override
@@ -142,6 +159,14 @@ class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
fontSize: 14 fontSize: 14
), ),
); );
} else if (success is CancelSendingEmail) {
return Text(
'${AppLocalizations.of(context).canceling}...',
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: AppColor.labelColor,
fontSize: 14
),
);
} else { } else {
return Text( return Text(
'${AppLocalizations.of(context).sendingMessage}...', '${AppLocalizations.of(context).sendingMessage}...',
@@ -167,7 +192,7 @@ class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
), ),
), ),
Padding( Padding(
padding: const EdgeInsetsDirectional.only(start: 16, end: 16, top: 4, bottom: 24), padding: const EdgeInsetsDirectional.only(start: 16, end: 16, top: 4, bottom: 16),
child: Row( child: Row(
children: [ children: [
Text( Text(
@@ -188,7 +213,24 @@ class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
) )
], ],
), ),
) ),
if (widget.onCancelSendingEmailAction != null)
Align(
alignment: AlignmentDirectional.centerEnd,
child: TMailButtonWidget.fromText(
text: AppLocalizations.of(context).cancel,
textStyle: Theme.of(context).textTheme.labelSmall?.copyWith(
color: Colors.black87,
fontSize: 15
),
padding: const EdgeInsetsDirectional.symmetric(horizontal: 20, vertical: 8),
margin: const EdgeInsetsDirectional.only(start: 12, end: 12, bottom: 16),
onTapActionCallback: () {
_viewStateNotifier.value = dartz.Right<Failure, Success>(CancelSendingEmail());
widget.onCancelSendingEmailAction!(cancelToken: widget.cancelToken);
},
),
)
], ],
) )
], ],
@@ -32,7 +32,10 @@ abstract class EmailDataSource {
Session session, Session session,
AccountId accountId, AccountId accountId,
EmailRequest emailRequest, EmailRequest emailRequest,
{CreateNewMailboxRequest? mailboxRequest} {
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken
}
); );
Future<List<Email>> markAsRead(Session session, AccountId accountId, List<Email> emails, ReadActions readActions); Future<List<Email>> markAsRead(Session session, AccountId accountId, List<Email> emails, ReadActions readActions);
@@ -79,7 +82,12 @@ abstract class EmailDataSource {
Future<List<EmailId>> deleteMultipleEmailsPermanently(Session session, AccountId accountId, List<EmailId> emailIds); Future<List<EmailId>> deleteMultipleEmailsPermanently(Session session, AccountId accountId, List<EmailId> emailIds);
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId); Future<bool> deleteEmailPermanently(
Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
);
Future<void> storeDetailedNewEmail(Session session, AccountId accountId, DetailedEmail detailedEmail); Future<void> storeDetailedNewEmail(Session session, AccountId accountId, DetailedEmail detailedEmail);
@@ -46,10 +46,19 @@ class EmailDataSourceImpl extends EmailDataSource {
Session session, Session session,
AccountId accountId, AccountId accountId,
EmailRequest emailRequest, EmailRequest emailRequest,
{CreateNewMailboxRequest? mailboxRequest} {
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken,
}
) async { ) async {
try { try {
return await emailAPI.sendEmail(session, accountId, emailRequest, mailboxRequest: mailboxRequest); return await emailAPI.sendEmail(
session,
accountId,
emailRequest,
mailboxRequest: mailboxRequest,
cancelToken: cancelToken
);
} catch (error, stackTrace) { } catch (error, stackTrace) {
return await _sendEmailExceptionThrower.throwException(error, stackTrace); return await _sendEmailExceptionThrower.throwException(error, stackTrace);
} }
@@ -157,9 +166,19 @@ class EmailDataSourceImpl extends EmailDataSource {
} }
@override @override
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId) { Future<bool> deleteEmailPermanently(
Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
) {
return Future.sync(() async { return Future.sync(() async {
return await emailAPI.deleteEmailPermanently(session, accountId, emailId); return await emailAPI.deleteEmailPermanently(
session,
accountId,
emailId,
cancelToken: cancelToken
);
}).catchError(_exceptionThrower.throwException); }).catchError(_exceptionThrower.throwException);
} }
@@ -71,7 +71,12 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource {
); );
@override @override
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId) { Future<bool> deleteEmailPermanently(
Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
) {
throw UnimplementedError(); throw UnimplementedError();
} }
@@ -134,7 +139,15 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource {
} }
@override @override
Future<bool> sendEmail(Session session, AccountId accountId, EmailRequest emailRequest, {CreateNewMailboxRequest? mailboxRequest}) { Future<bool> sendEmail(
Session session,
AccountId accountId,
EmailRequest emailRequest,
{
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken
}
) {
throw UnimplementedError(); throw UnimplementedError();
} }
+12 -4
View File
@@ -117,7 +117,10 @@ class EmailAPI with HandleSetErrorMixin {
Session session, Session session,
AccountId accountId, AccountId accountId,
EmailRequest emailRequest, EmailRequest emailRequest,
{CreateNewMailboxRequest? mailboxRequest} {
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken,
}
) async { ) async {
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
@@ -199,7 +202,7 @@ class EmailAPI with HandleSetErrorMixin {
final response = await (requestBuilder final response = await (requestBuilder
..usings(capabilities)) ..usings(capabilities))
.build() .build()
.execute(); .execute(cancelToken: cancelToken);
final setEmailResponse = response.parse<SetEmailResponse>( final setEmailResponse = response.parse<SetEmailResponse>(
setEmailInvocation.methodCallId, setEmailInvocation.methodCallId,
@@ -606,7 +609,12 @@ class EmailAPI with HandleSetErrorMixin {
return List.empty(); return List.empty();
} }
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId) async { Future<bool> deleteEmailPermanently(
Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
) async {
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
final setEmailMethod = SetEmailMethod(accountId) final setEmailMethod = SetEmailMethod(accountId)
..addDestroy({emailId.id}); ..addDestroy({emailId.id});
@@ -619,7 +627,7 @@ class EmailAPI with HandleSetErrorMixin {
final response = await (requestBuilder final response = await (requestBuilder
..usings(capabilities)) ..usings(capabilities))
.build() .build()
.execute(); .execute(cancelToken: cancelToken);
final setEmailResponse = response.parse<SetEmailResponse>( final setEmailResponse = response.parse<SetEmailResponse>(
setEmailInvocation.methodCallId, setEmailInvocation.methodCallId,
@@ -58,9 +58,18 @@ class EmailRepositoryImpl extends EmailRepository {
Session session, Session session,
AccountId accountId, AccountId accountId,
EmailRequest emailRequest, EmailRequest emailRequest,
{CreateNewMailboxRequest? mailboxRequest} {
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken
}
) { ) {
return emailDataSource[DataSourceType.network]!.sendEmail(session, accountId, emailRequest, mailboxRequest: mailboxRequest); return emailDataSource[DataSourceType.network]!.sendEmail(
session,
accountId,
emailRequest,
mailboxRequest: mailboxRequest,
cancelToken: cancelToken,
);
} }
@override @override
@@ -172,8 +181,18 @@ class EmailRepositoryImpl extends EmailRepository {
} }
@override @override
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId) { Future<bool> deleteEmailPermanently(
return emailDataSource[DataSourceType.network]!.deleteEmailPermanently(session, accountId, emailId); Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
) {
return emailDataSource[DataSourceType.network]!.deleteEmailPermanently(
session,
accountId,
emailId,
cancelToken: cancelToken
);
} }
@override @override
@@ -34,7 +34,10 @@ abstract class EmailRepository {
Session session, Session session,
AccountId accountId, AccountId accountId,
EmailRequest emailRequest, EmailRequest emailRequest,
{CreateNewMailboxRequest? mailboxRequest} {
CreateNewMailboxRequest? mailboxRequest,
CancelToken? cancelToken
}
); );
Future<List<Email>> markAsRead(Session session, AccountId accountId, List<Email> emails, ReadActions readActions); Future<List<Email>> markAsRead(Session session, AccountId accountId, List<Email> emails, ReadActions readActions);
@@ -87,7 +90,12 @@ abstract class EmailRepository {
Future<List<EmailId>> deleteMultipleEmailsPermanently(Session session, AccountId accountId, List<EmailId> emailIds); Future<List<EmailId>> deleteMultipleEmailsPermanently(Session session, AccountId accountId, List<EmailId> emailIds);
Future<bool> deleteEmailPermanently(Session session, AccountId accountId, EmailId emailId); Future<bool> deleteEmailPermanently(
Session session,
AccountId accountId,
EmailId emailId,
{CancelToken? cancelToken}
);
Future<jmap.State?> getEmailState(Session session, AccountId accountId); Future<jmap.State?> getEmailState(Session session, AccountId accountId);
@@ -415,10 +415,10 @@ class ThreadController extends BaseController with EmailActionController {
} }
_getAllEmailAction(); _getAllEmailAction();
} else if (error is MethodLevelErrors) { } else if (error is MethodLevelErrors) {
if (currentOverlayContext != null && error.message?.isNotEmpty == true) { if (currentOverlayContext != null && error.message != null) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
currentOverlayContext!, currentOverlayContext!,
error.message! error.message?.toString() ?? ''
); );
} }
clearState(); clearState();
+7 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2024-03-06T02:46:19.947772", "@@last_modified": "2024-03-12T12:50:35.525381",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -3845,5 +3845,11 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"canceling": "Canceling",
"@canceling": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+2 -2
View File
@@ -11,7 +11,7 @@ abstract class RemoteException with EquatableMixin implements Exception {
static const badCredentials = 'Bad credentials'; static const badCredentials = 'Bad credentials';
static const socketException = 'Socket exception'; static const socketException = 'Socket exception';
final String? message; final Object? message;
final int? code; final int? code;
const RemoteException({this.code, this.message}); const RemoteException({this.code, this.message});
@@ -25,7 +25,7 @@ class BadCredentialsException extends RemoteException {
} }
class UnknownError extends RemoteException { class UnknownError extends RemoteException {
const UnknownError({int? code, String? message}) : super(code: code, message: message); const UnknownError({int? code, Object? message}) : super(code: code, message: message);
@override @override
List<Object?> get props => [code, message]; List<Object?> get props => [code, message];
@@ -53,7 +53,7 @@ class RemoteExceptionThrower extends ExceptionThrower {
if (error.error is SocketException) { if (error.error is SocketException) {
throw const SocketError(); throw const SocketError();
} else if (error.error != null) { } else if (error.error != null) {
throw UnknownError(message: error.error!.toString()); throw UnknownError(message: error.error);
} else { } else {
throw const UnknownError(); throw const UnknownError();
} }
@@ -4016,4 +4016,11 @@ class AppLocalizations {
'Saving of the message to drafts folder failed.\nAn error occurred while saving mail.', 'Saving of the message to drafts folder failed.\nAn error occurred while saving mail.',
name: 'warningMessageWhenSaveEmailToDraftsFailure'); name: 'warningMessageWhenSaveEmailToDraftsFailure');
} }
String get canceling {
return Intl.message(
'Canceling',
name: 'canceling'
);
}
} }