TF-2667 Add cancel button in progress send message dialog
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
class SendingEmailCanceledException implements Exception {}
|
||||||
@@ -54,3 +54,5 @@ class SendEmailFailure extends FeatureFailure {
|
|||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user