TF-2667 Show sending message dialog when click send button
This commit is contained in:
@@ -2,6 +2,7 @@ class Constant {
|
||||
static const acceptHeaderDefault = 'application/json';
|
||||
static const contentTypeHeaderDefault = 'application/json';
|
||||
static const pdfMimeType = 'application/pdf';
|
||||
static const base64Charset = 'base64';
|
||||
static const textHtmlMimeType = 'text/html';
|
||||
static const octetStreamMimeType = 'application/octet-stream';
|
||||
static const pdfExtension = '.pdf';
|
||||
|
||||
@@ -34,6 +34,7 @@ class ApplicationManager {
|
||||
userAgent = FkUserAgent.userAgent ?? '';
|
||||
FkUserAgent.release();
|
||||
}
|
||||
log('ApplicationManager::getUserAgent: $userAgent');
|
||||
return userAgent;
|
||||
} catch(e) {
|
||||
logError('ApplicationManager::getUserAgent: Exception: $e');
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/utils/application_manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ApplicationVersionWidget extends StatelessWidget {
|
||||
class ApplicationVersionWidget extends StatefulWidget {
|
||||
|
||||
final ApplicationManager applicationManager;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
@@ -17,18 +17,32 @@ class ApplicationVersionWidget extends StatelessWidget {
|
||||
this.padding,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ApplicationVersionWidget> createState() => _ApplicationVersionWidgetState();
|
||||
}
|
||||
|
||||
class _ApplicationVersionWidgetState extends State<ApplicationVersionWidget> {
|
||||
|
||||
Future<String>? _versionStream;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_versionStream = widget.applicationManager.getVersion();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: applicationManager.getVersion(),
|
||||
future: _versionStream,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Padding(
|
||||
padding: padding ?? const EdgeInsets.only(top: 6),
|
||||
padding: widget.padding ?? const EdgeInsets.only(top: 6),
|
||||
child: Text(
|
||||
'${title ?? 'v.'}${snapshot.data}',
|
||||
'${widget.title ?? 'v.'}${snapshot.data}',
|
||||
textAlign: TextAlign.center,
|
||||
style: textStyle ?? Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
style: widget.textStyle ?? Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
fontSize: 13,
|
||||
color: AppColor.colorContentEmail,
|
||||
fontWeight: FontWeight.w500
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
|
||||
import 'package:core/data/constants/constant.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/application_manager.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/upload/file_info.dart';
|
||||
import 'package:tmail_ui_user/features/composer/data/datasource/composer_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/create_email_request_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
||||
import 'package:tmail_ui_user/features/upload/data/datasource/attachment_upload_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class ComposerRepositoryImpl extends ComposerRepository {
|
||||
|
||||
final AttachmentUploadDataSource _attachmentUploadDataSource;
|
||||
final ComposerDataSource _composerDataSource;
|
||||
final HtmlDataSource _htmlDataSource;
|
||||
final ApplicationManager _applicationManager;
|
||||
final Uuid _uuid;
|
||||
|
||||
ComposerRepositoryImpl(
|
||||
this._attachmentUploadDataSource,
|
||||
this._composerDataSource);
|
||||
this._composerDataSource,
|
||||
this._htmlDataSource,
|
||||
this._applicationManager,
|
||||
this._uuid,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken}) {
|
||||
@@ -24,4 +42,62 @@ class ComposerRepositoryImpl extends ComposerRepository {
|
||||
Future<String?> downloadImageAsBase64(String url, String cid, FileInfo fileInfo, {double? maxWidth, bool? compress}) {
|
||||
return _composerDataSource.downloadImageAsBase64(url, cid, fileInfo, maxWidth: maxWidth, compress: compress);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Email> generateEmail(CreateEmailRequest createEmailRequest) async {
|
||||
String emailContent = createEmailRequest.emailContent;
|
||||
Set<EmailBodyPart> emailAttachments = Set.from(createEmailRequest.createAttachments());
|
||||
|
||||
if (createEmailRequest.inlineAttachments?.isNotEmpty == true) {
|
||||
final tupleContentInlineAttachments = await _replaceImageBase64ToImageCID(
|
||||
emailContent: emailContent,
|
||||
inlineAttachments: createEmailRequest.inlineAttachments!
|
||||
);
|
||||
|
||||
emailContent = tupleContentInlineAttachments.value1;
|
||||
emailAttachments.addAll(tupleContentInlineAttachments.value2);
|
||||
}
|
||||
|
||||
emailContent = await _removeCollapsedExpandedSignatureEffect(emailContent: emailContent);
|
||||
|
||||
final userAgent = await _applicationManager.generateApplicationUserAgent();
|
||||
final emailBodyPartId = PartId(_uuid.v1());
|
||||
|
||||
final emailObject = createEmailRequest.generateEmail(
|
||||
newEmailContent: emailContent,
|
||||
newEmailAttachments: emailAttachments,
|
||||
userAgent: userAgent,
|
||||
partId: emailBodyPartId
|
||||
);
|
||||
|
||||
return emailObject;
|
||||
}
|
||||
|
||||
Future<Tuple2<String, Set<EmailBodyPart>>> _replaceImageBase64ToImageCID({
|
||||
required String emailContent,
|
||||
required Map<String, Attachment> inlineAttachments
|
||||
}) {
|
||||
try {
|
||||
return _htmlDataSource.replaceImageBase64ToImageCID(
|
||||
emailContent: emailContent,
|
||||
inlineAttachments: inlineAttachments);
|
||||
} catch (e) {
|
||||
logError('ComposerRepositoryImpl::_replaceImageBase64ToImageCID: Exception: $e');
|
||||
return Future.value(
|
||||
Tuple2(
|
||||
emailContent,
|
||||
inlineAttachments.values.toList().toEmailBodyPart(charset: Constant.base64Charset)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> _removeCollapsedExpandedSignatureEffect({required String emailContent}) {
|
||||
try {
|
||||
return _htmlDataSource.removeCollapsedExpandedSignatureEffect(emailContent: emailContent);
|
||||
} catch (e) {
|
||||
logError('ComposerRepositoryImpl::_removeCollapsedExpandedSignatureEffect: Exception: $e');
|
||||
return Future.value(emailContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/upload/file_info.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart';
|
||||
|
||||
abstract class ComposerRepository {
|
||||
Future<Email> generateEmail(CreateEmailRequest createEmailRequest);
|
||||
|
||||
Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken});
|
||||
|
||||
Future<String?> downloadImageAsBase64(String url, String cid, FileInfo fileInfo, {double? maxWidth, bool? compress});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
|
||||
class GenerateEmailLoading extends LoadingState {}
|
||||
|
||||
class GenerateEmailFailure extends FeatureFailure {
|
||||
|
||||
GenerateEmailFailure(dynamic exception) : super(exception: exception);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart';
|
||||
|
||||
class SendEmailLoading extends UIState {}
|
||||
class SendEmailLoading extends LoadingState {}
|
||||
|
||||
class SendEmailSuccess extends UIActionState {
|
||||
|
||||
@@ -29,17 +29,17 @@ class SendEmailSuccess extends UIActionState {
|
||||
|
||||
class SendEmailFailure extends FeatureFailure {
|
||||
|
||||
final Session session;
|
||||
final AccountId accountId;
|
||||
final EmailRequest emailRequest;
|
||||
final Session? session;
|
||||
final AccountId? accountId;
|
||||
final EmailRequest? emailRequest;
|
||||
final CreateNewMailboxRequest? mailboxRequest;
|
||||
final SendingEmailActionType? sendingEmailActionType;
|
||||
|
||||
SendEmailFailure({
|
||||
dynamic exception,
|
||||
required this.session,
|
||||
required this.accountId,
|
||||
required this.emailRequest,
|
||||
this.session,
|
||||
this.accountId,
|
||||
this.emailRequest,
|
||||
this.mailboxRequest,
|
||||
this.sendingEmailActionType
|
||||
}) : super(exception: exception);
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
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/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.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/send_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/create_email_request_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.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/sending_queue/presentation/model/sending_email_arguments.dart';
|
||||
|
||||
class CreateNewAndSendEmailInteractor {
|
||||
final EmailRepository _emailRepository;
|
||||
final MailboxRepository _mailboxRepository;
|
||||
final ComposerRepository _composerRepository;
|
||||
|
||||
CreateNewAndSendEmailInteractor(
|
||||
this._emailRepository,
|
||||
this._mailboxRepository,
|
||||
this._composerRepository,
|
||||
);
|
||||
|
||||
Stream<dartz.Either<Failure, Success>> execute(CreateEmailRequest createEmailRequest) async* {
|
||||
SendingEmailArguments? sendingEmailArguments;
|
||||
try {
|
||||
yield dartz.Right<Failure, Success>(GenerateEmailLoading());
|
||||
|
||||
final listCurrentState = await _getStoredCurrentState(
|
||||
session: createEmailRequest.session,
|
||||
accountId: createEmailRequest.accountId
|
||||
);
|
||||
|
||||
sendingEmailArguments = await _createEmailObject(createEmailRequest);
|
||||
|
||||
if (sendingEmailArguments != null) {
|
||||
yield dartz.Right<Failure, Success>(SendEmailLoading());
|
||||
|
||||
await _emailRepository.sendEmail(
|
||||
sendingEmailArguments.session,
|
||||
sendingEmailArguments.accountId,
|
||||
sendingEmailArguments.emailRequest,
|
||||
mailboxRequest: sendingEmailArguments.mailboxRequest
|
||||
);
|
||||
|
||||
if (sendingEmailArguments.emailRequest.emailIdDestroyed != null) {
|
||||
await _deleteOldDraftsEmail(
|
||||
session: sendingEmailArguments.session,
|
||||
accountId: sendingEmailArguments.accountId,
|
||||
draftEmailId: sendingEmailArguments.emailRequest.emailIdDestroyed!
|
||||
);
|
||||
}
|
||||
|
||||
yield dartz.Right<Failure, Success>(
|
||||
SendEmailSuccess(
|
||||
currentMailboxState: listCurrentState?.value1,
|
||||
currentEmailState: listCurrentState?.value2,
|
||||
emailRequest: sendingEmailArguments.emailRequest
|
||||
)
|
||||
);
|
||||
} else {
|
||||
yield dartz.Left<Failure, Success>(GenerateEmailFailure(CannotCreateEmailObjectException()));
|
||||
}
|
||||
} catch (e) {
|
||||
logError('CreateNewAndSendEmailInteractor::execute: Exception: $e');
|
||||
yield dartz.Left<Failure, Success>(SendEmailFailure(
|
||||
exception: e,
|
||||
session: sendingEmailArguments?.session,
|
||||
accountId: sendingEmailArguments?.accountId,
|
||||
emailRequest: sendingEmailArguments?.emailRequest,
|
||||
mailboxRequest: sendingEmailArguments?.mailboxRequest,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Future<SendingEmailArguments?> _createEmailObject(CreateEmailRequest createEmailRequest) async {
|
||||
try {
|
||||
final emailCreated = await _composerRepository.generateEmail(createEmailRequest);
|
||||
final sendingEmailArgument = createEmailRequest.toSendingEmailArguments(emailObject: emailCreated);
|
||||
return sendingEmailArgument;
|
||||
} catch (e) {
|
||||
logError('CreateNewAndSendEmailInteractor::_createEmailObject: Exception: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<dartz.Tuple2<State?, State?>?> _getStoredCurrentState({
|
||||
required Session session,
|
||||
required AccountId accountId
|
||||
}) async {
|
||||
try {
|
||||
final listState = await Future.wait([
|
||||
_mailboxRepository.getMailboxState(session, accountId),
|
||||
_emailRepository.getEmailState(session, accountId),
|
||||
]);
|
||||
|
||||
final mailboxState = listState.first;
|
||||
final emailState = listState.last;
|
||||
|
||||
return dartz.Tuple2(mailboxState, emailState);
|
||||
} catch (e) {
|
||||
logError('CreateNewAndSendEmailInteractor::_getStoredCurrentState: Exception: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _deleteOldDraftsEmail({
|
||||
required Session session,
|
||||
required AccountId accountId,
|
||||
required EmailId draftEmailId
|
||||
}) async {
|
||||
try {
|
||||
await _emailRepository.deleteEmailPermanently(
|
||||
session,
|
||||
accountId,
|
||||
draftEmailId
|
||||
);
|
||||
} catch (e) {
|
||||
logError('CreateNewAndSendEmailInteractor::_deleteOldDraftsEmail: Exception: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,34 +38,24 @@ class SendEmailInteractor {
|
||||
final currentMailboxState = listState.first;
|
||||
final currentEmailState = listState.last;
|
||||
|
||||
final result = await _emailRepository.sendEmail(
|
||||
await _emailRepository.sendEmail(
|
||||
session,
|
||||
accountId,
|
||||
emailRequest,
|
||||
mailboxRequest: mailboxRequest
|
||||
);
|
||||
|
||||
if (result) {
|
||||
if (emailRequest.emailIdDestroyed != null) {
|
||||
await _emailRepository.deleteEmailPermanently(session, accountId, emailRequest.emailIdDestroyed!);
|
||||
}
|
||||
|
||||
yield Right<Failure, Success>(
|
||||
SendEmailSuccess(
|
||||
currentEmailState: currentEmailState,
|
||||
currentMailboxState: currentMailboxState,
|
||||
emailRequest: emailRequest
|
||||
)
|
||||
);
|
||||
} else {
|
||||
yield Left<Failure, Success>(SendEmailFailure(
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
emailRequest: emailRequest,
|
||||
mailboxRequest: mailboxRequest,
|
||||
sendingEmailActionType: sendingEmailActionType,
|
||||
));
|
||||
if (emailRequest.emailIdDestroyed != null) {
|
||||
await _emailRepository.deleteEmailPermanently(session, accountId, emailRequest.emailIdDestroyed!);
|
||||
}
|
||||
|
||||
yield Right<Failure, Success>(
|
||||
SendEmailSuccess(
|
||||
currentEmailState: currentEmailState,
|
||||
currentMailboxState: currentMailboxState,
|
||||
emailRequest: emailRequest
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
yield Left<Failure, Success>(SendEmailFailure(
|
||||
exception: e,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:core/utils/application_manager.dart';
|
||||
import 'package:core/utils/file_utils.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/composer/data/datasource/composer_datasource.dart';
|
||||
@@ -10,6 +11,7 @@ import 'package:tmail_ui_user/features/composer/data/repository/composer_reposit
|
||||
import 'package:tmail_ui_user/features/composer/data/repository/contact_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/repository/contact_repository.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/download_image_as_base64_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart';
|
||||
@@ -104,7 +106,7 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.lazyPut(() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => StateDataSourceImpl(
|
||||
Get.find<StateCacheManager>(),
|
||||
Get.find<IOSSharingManager>(),
|
||||
@@ -147,8 +149,12 @@ class ComposerBindings extends BaseBindings {
|
||||
@override
|
||||
void bindingsRepositoryImpl() {
|
||||
Get.lazyPut(() => ComposerRepositoryImpl(
|
||||
Get.find<AttachmentUploadDataSource>(),
|
||||
Get.find<ComposerDataSource>()));
|
||||
Get.find<AttachmentUploadDataSource>(),
|
||||
Get.find<ComposerDataSource>(),
|
||||
Get.find<HtmlDataSource>(),
|
||||
Get.find<ApplicationManager>(),
|
||||
Get.find<Uuid>(),
|
||||
));
|
||||
Get.lazyPut(() => ContactRepositoryImpl(Get.find<ContactDataSource>()));
|
||||
Get.lazyPut(() => MailboxRepositoryImpl(
|
||||
{
|
||||
@@ -197,6 +203,11 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.lazyPut(() => DownloadImageAsBase64Interactor(Get.find<ComposerRepository>()));
|
||||
Get.lazyPut(() => TransformHtmlEmailContentInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => GetAlwaysReadReceiptSettingInteractor(Get.find<ServerSettingsRepository>()));
|
||||
Get.lazyPut(() => CreateNewAndSendEmailInteractor(
|
||||
Get.find<EmailRepository>(),
|
||||
Get.find<MailboxRepository>(),
|
||||
Get.find<ComposerRepository>(),
|
||||
));
|
||||
|
||||
IdentityInteractorsBindings().dependencies();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:html_editor_enhanced/html_editor.dart' as web_html_editor;
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
@@ -29,6 +28,7 @@ import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:rich_text_composer/rich_text_composer.dart';
|
||||
import 'package:super_tag_editor/tag_editor.dart';
|
||||
@@ -36,12 +36,12 @@ 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/button_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/model/email_request.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/get_autocomplete_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_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/download_image_as_base64_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
|
||||
@@ -53,6 +53,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/file_upl
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_identities_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_shared_media_file_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
|
||||
@@ -60,13 +61,13 @@ import 'package:tmail_ui_user/features/composer/presentation/model/save_to_draft
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/from_composer_bottom_sheet_builder.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/sending_message_dialog_view.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
@@ -76,7 +77,6 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_id
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/identity_extension.dart';
|
||||
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart'
|
||||
if (dart.library.html) 'package:tmail_ui_user/features/network_connection/presentation/web_network_connection_controller.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/server_settings/domain/state/get_always_read_receipt_setting_state.dart';
|
||||
@@ -131,6 +131,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
final DownloadImageAsBase64Interactor _downloadImageAsBase64Interactor;
|
||||
final TransformHtmlEmailContentInteractor _transformHtmlEmailContentInteractor;
|
||||
final GetAlwaysReadReceiptSettingInteractor _getAlwaysReadReceiptSettingInteractor;
|
||||
final CreateNewAndSendEmailInteractor _createNewAndSendEmailInteractor;
|
||||
|
||||
GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor;
|
||||
GetAutoCompleteInteractor? _getAutoCompleteInteractor;
|
||||
@@ -198,6 +199,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
this._downloadImageAsBase64Interactor,
|
||||
this._transformHtmlEmailContentInteractor,
|
||||
this._getAlwaysReadReceiptSettingInteractor,
|
||||
this._createNewAndSendEmailInteractor,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -760,7 +762,6 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
bodyValues: {
|
||||
generatePartId: EmailBodyValue(emailBodyText, false, false)
|
||||
},
|
||||
headerUserAgent: {IndividualHeaderIdentifier.headerUserAgent : userAgent},
|
||||
attachments: attachments.isNotEmpty ? attachments : null,
|
||||
headerMdn: hasRequestReadReceipt.value ? { IndividualHeaderIdentifier.headerMdn: getEmailAddressSender() } : {},
|
||||
);
|
||||
@@ -899,67 +900,64 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
_handleSendMessages(context);
|
||||
}
|
||||
|
||||
bool get _isParamUserNull {
|
||||
Future<String> _getContentInEditor() async {
|
||||
final htmlTextEditor = PlatformInfo.isWeb
|
||||
? _textEditorWeb
|
||||
: await htmlEditorApi?.getText();
|
||||
if (htmlTextEditor?.isNotEmpty == true) {
|
||||
return htmlTextEditor!.removeEditorStartTag();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
void _handleSendMessages(BuildContext context) async {
|
||||
if (composerArguments.value == null ||
|
||||
mailboxDashBoardController.sessionCurrent == null ||
|
||||
mailboxDashBoardController.accountId.value == null
|
||||
) {
|
||||
logError('ComposerController::isParamUserNotNull: Param is NULL');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _handleSendMessages(BuildContext context) async {
|
||||
if (_isParamUserNull) {
|
||||
logError('ComposerController::_handleSendMessages: Param is NULL');
|
||||
log('ComposerController::_handleSendMessages: SESSION or ACCOUNT_ID or ARGUMENTS is NULL');
|
||||
_closeComposerAction();
|
||||
return;
|
||||
}
|
||||
|
||||
final sendingArgs = await createSendingEmailArguments(context);
|
||||
_closeComposerAction(result: sendingArgs);
|
||||
}
|
||||
final emailContent = await _getContentInEditor();
|
||||
|
||||
Future<SendingEmailArguments> createSendingEmailArguments(BuildContext context) async {
|
||||
final session = mailboxDashBoardController.sessionCurrent!;
|
||||
final arguments = composerArguments.value!;
|
||||
final accountId = mailboxDashBoardController.accountId.value!;
|
||||
|
||||
final createdEmail = await _generateEmail(
|
||||
context,
|
||||
session.username,
|
||||
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.id,
|
||||
arguments: arguments
|
||||
final resultState = await Get.dialog(
|
||||
PointerInterceptor(
|
||||
child: SendingMessageDialogView(
|
||||
createEmailRequest: CreateEmailRequest(
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
accountId: mailboxDashBoardController.accountId.value!,
|
||||
emailActionType: composerArguments.value!.emailActionType,
|
||||
subject: subjectEmail.value ?? '',
|
||||
emailContent: emailContent,
|
||||
fromSender: composerArguments.value!.presentationEmail?.from ?? {},
|
||||
toRecipients: listToEmailAddress.toSet(),
|
||||
ccRecipients: listCcEmailAddress.toSet(),
|
||||
bccRecipients: listBccEmailAddress.toSet(),
|
||||
isRequestReadReceipt: hasRequestReadReceipt.value,
|
||||
identity: identitySelected.value,
|
||||
attachments: uploadController.attachmentsUploaded,
|
||||
inlineAttachments: uploadController.mapInlineAttachments,
|
||||
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
|
||||
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
|
||||
draftsEmailId: composerArguments.value!.emailActionType == EmailActionType.editDraft
|
||||
? composerArguments.value!.presentationEmail?.id
|
||||
: null,
|
||||
answerForwardEmailId: composerArguments.value!.presentationEmail?.id,
|
||||
unsubscribeEmailId: composerArguments.value!.previousEmailId,
|
||||
messageId: composerArguments.value!.messageId,
|
||||
references: composerArguments.value!.references,
|
||||
emailSendingQueue: composerArguments.value!.sendingEmail
|
||||
),
|
||||
createNewAndSendEmailInteractor: _createNewAndSendEmailInteractor
|
||||
),
|
||||
),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
|
||||
final emailRequest = arguments.emailActionType == EmailActionType.editSendingEmail
|
||||
? arguments.sendingEmail!.toEmailRequest(newEmail: createdEmail)
|
||||
: EmailRequest(
|
||||
email: createdEmail,
|
||||
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
|
||||
identityId: identitySelected.value?.id,
|
||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.editDraft
|
||||
? arguments.presentationEmail?.id
|
||||
: null,
|
||||
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
|
||||
emailActionType: arguments.emailActionType,
|
||||
previousEmailId: arguments.previousEmailId,
|
||||
);
|
||||
|
||||
final mailboxRequest = mailboxDashBoardController.outboxMailbox?.id == null
|
||||
? CreateNewMailboxRequest(
|
||||
Id(uuid.v1()),
|
||||
MailboxName(PresentationMailbox.outboxRole.inCaps)
|
||||
)
|
||||
: null;
|
||||
|
||||
return SendingEmailArguments(
|
||||
session,
|
||||
accountId,
|
||||
emailRequest,
|
||||
mailboxRequest,
|
||||
);
|
||||
_closeComposerAction(result: resultState);
|
||||
}
|
||||
|
||||
void _checkContactPermission() async {
|
||||
@@ -1370,7 +1368,6 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
}
|
||||
|
||||
void _closeComposerAction({dynamic result}) {
|
||||
log('ComposerController::_closeComposerAction:');
|
||||
isSendEmailLoading.value = false;
|
||||
|
||||
if (PlatformInfo.isWeb) {
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_value.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
import 'package:model/extensions/username_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/identity_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_arguments.dart';
|
||||
|
||||
extension CreateEmailRequestExtension on CreateEmailRequest {
|
||||
|
||||
Set<EmailAddress> createSenders() {
|
||||
if (identity?.email?.isNotEmpty == true) {
|
||||
return { identity!.toEmailAddress() };
|
||||
} else {
|
||||
return { session.username.toEmailAddress() };
|
||||
}
|
||||
}
|
||||
|
||||
String createMdnEmailAddress() {
|
||||
if (emailActionType == EmailActionType.editDraft && fromSender.isNotEmpty) {
|
||||
return fromSender.first.emailAddress;
|
||||
} else {
|
||||
return session.username.value;
|
||||
}
|
||||
}
|
||||
|
||||
Set<EmailAddress> createReplyToRecipients() {
|
||||
if (identity?.replyTo?.isNotEmpty == true) {
|
||||
return identity!.replyTo!.toSet();
|
||||
} else {
|
||||
return { session.username.toEmailAddress() };
|
||||
}
|
||||
}
|
||||
|
||||
Set<EmailBodyPart> createAttachments() => attachments?.toEmailBodyPart() ?? {};
|
||||
|
||||
Map<KeyWordIdentifier, bool>? createKeywords() {
|
||||
if (draftsMailboxId != null) {
|
||||
return {
|
||||
KeyWordIdentifier.emailDraft: true,
|
||||
KeyWordIdentifier.emailSeen: true,
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Map<MailboxId, bool>? createMailboxIds() {
|
||||
if (draftsMailboxId != null || outboxMailboxId != null) {
|
||||
return {
|
||||
if (draftsMailboxId != null)
|
||||
draftsMailboxId!: true,
|
||||
if (outboxMailboxId != null)
|
||||
outboxMailboxId!: true,
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
MessageIdsHeaderValue? createInReplyTo() {
|
||||
if (emailActionType == EmailActionType.reply ||
|
||||
emailActionType == EmailActionType.replyAll
|
||||
) {
|
||||
return messageId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
MessageIdsHeaderValue? createReferences() {
|
||||
if (emailActionType == EmailActionType.reply ||
|
||||
emailActionType == EmailActionType.replyAll ||
|
||||
emailActionType == EmailActionType.forward
|
||||
) {
|
||||
Set<String> ids = {};
|
||||
if (messageId?.ids.isNotEmpty == true) {
|
||||
ids.addAll(messageId!.ids);
|
||||
}
|
||||
if (references?.ids.isNotEmpty == true) {
|
||||
ids.addAll(references!.ids);
|
||||
}
|
||||
if (ids.isNotEmpty) {
|
||||
return MessageIdsHeaderValue(ids);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Email generateEmail({
|
||||
required String newEmailContent,
|
||||
required Set<EmailBodyPart> newEmailAttachments,
|
||||
required String userAgent,
|
||||
required PartId partId,
|
||||
}) {
|
||||
return Email(
|
||||
mailboxIds: createMailboxIds(),
|
||||
from: createSenders(),
|
||||
to: toRecipients,
|
||||
cc: ccRecipients,
|
||||
bcc: bccRecipients,
|
||||
replyTo: createReplyToRecipients(),
|
||||
inReplyTo: createInReplyTo(),
|
||||
references: createReferences(),
|
||||
keywords: createKeywords(),
|
||||
subject: subject,
|
||||
htmlBody: {
|
||||
EmailBodyPart(
|
||||
partId: partId,
|
||||
type: MediaType.parse(Constant.textHtmlMimeType)
|
||||
)
|
||||
},
|
||||
bodyValues: {
|
||||
partId: EmailBodyValue(
|
||||
newEmailContent,
|
||||
false,
|
||||
false
|
||||
)
|
||||
},
|
||||
headerUserAgent: {
|
||||
IndividualHeaderIdentifier.headerUserAgent : userAgent
|
||||
},
|
||||
attachments: newEmailAttachments.isNotEmpty
|
||||
? newEmailAttachments
|
||||
: null,
|
||||
headerMdn: isRequestReadReceipt
|
||||
? { IndividualHeaderIdentifier.headerMdn: createMdnEmailAddress() }
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
EmailRequest createEmailRequest({required Email emailObject}) {
|
||||
if (emailActionType == EmailActionType.editSendingEmail) {
|
||||
return emailSendingQueue!.toEmailRequest(newEmail: emailObject);
|
||||
} else {
|
||||
return EmailRequest(
|
||||
email: emailObject,
|
||||
sentMailboxId: sentMailboxId,
|
||||
identityId: identity?.id,
|
||||
emailIdDestroyed: draftsEmailId,
|
||||
emailIdAnsweredOrForwarded: answerForwardEmailId,
|
||||
emailActionType: emailActionType,
|
||||
previousEmailId: unsubscribeEmailId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CreateNewMailboxRequest? createMailboxRequest() {
|
||||
if (outboxMailboxId == null) {
|
||||
return CreateNewMailboxRequest(MailboxName(PresentationMailbox.outboxRole.inCaps));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
SendingEmailArguments toSendingEmailArguments({required Email emailObject}) {
|
||||
return SendingEmailArguments(
|
||||
session,
|
||||
accountId,
|
||||
createEmailRequest(emailObject: emailObject),
|
||||
createMailboxRequest()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
|
||||
extension IdentityExtension on Identity {
|
||||
EmailAddress toEmailAddress() => EmailAddress(name, email);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
import 'package:equatable/equatable.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/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
|
||||
|
||||
class CreateEmailRequest with EquatableMixin {
|
||||
|
||||
final Session session;
|
||||
final AccountId accountId;
|
||||
final EmailActionType emailActionType;
|
||||
final String subject;
|
||||
final String emailContent;
|
||||
final bool isRequestReadReceipt;
|
||||
final Set<EmailAddress> fromSender;
|
||||
final Set<EmailAddress> toRecipients;
|
||||
final Set<EmailAddress> ccRecipients;
|
||||
final Set<EmailAddress> bccRecipients;
|
||||
final Identity? identity;
|
||||
final List<Attachment>? attachments;
|
||||
final Map<String, Attachment>? inlineAttachments;
|
||||
final MailboxId? outboxMailboxId;
|
||||
final MailboxId? sentMailboxId;
|
||||
final MailboxId? draftsMailboxId;
|
||||
final EmailId? draftsEmailId;
|
||||
final EmailId? answerForwardEmailId;
|
||||
final EmailId? unsubscribeEmailId;
|
||||
final MessageIdsHeaderValue? messageId;
|
||||
final MessageIdsHeaderValue? references;
|
||||
final SendingEmail? emailSendingQueue;
|
||||
|
||||
CreateEmailRequest({
|
||||
required this.session,
|
||||
required this.accountId,
|
||||
required this.emailActionType,
|
||||
required this.subject,
|
||||
required this.emailContent,
|
||||
required this.fromSender,
|
||||
required this.toRecipients,
|
||||
required this.ccRecipients,
|
||||
required this.bccRecipients,
|
||||
this.isRequestReadReceipt = true,
|
||||
this.identity,
|
||||
this.attachments,
|
||||
this.inlineAttachments,
|
||||
this.outboxMailboxId,
|
||||
this.sentMailboxId,
|
||||
this.draftsMailboxId,
|
||||
this.draftsEmailId,
|
||||
this.answerForwardEmailId,
|
||||
this.unsubscribeEmailId,
|
||||
this.messageId,
|
||||
this.references,
|
||||
this.emailSendingQueue
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
session,
|
||||
accountId,
|
||||
emailActionType,
|
||||
subject,
|
||||
emailContent,
|
||||
fromSender,
|
||||
toRecipients,
|
||||
ccRecipients,
|
||||
bccRecipients,
|
||||
identity,
|
||||
isRequestReadReceipt,
|
||||
attachments,
|
||||
inlineAttachments,
|
||||
outboxMailboxId,
|
||||
sentMailboxId,
|
||||
draftsMailboxId,
|
||||
draftsEmailId,
|
||||
answerForwardEmailId,
|
||||
unsubscribeEmailId,
|
||||
references,
|
||||
references,
|
||||
emailSendingQueue
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/presentation/extensions/capitalize_extension.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
import 'package:flutter/material.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/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/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
class SendingMessageDialogView extends StatefulWidget {
|
||||
|
||||
final CreateEmailRequest createEmailRequest;
|
||||
final CreateNewAndSendEmailInteractor createNewAndSendEmailInteractor;
|
||||
|
||||
const SendingMessageDialogView({
|
||||
super.key,
|
||||
required this.createEmailRequest,
|
||||
required this.createNewAndSendEmailInteractor,
|
||||
});
|
||||
|
||||
@override
|
||||
State<SendingMessageDialogView> createState() => _SendingMessageDialogViewState();
|
||||
}
|
||||
|
||||
class _SendingMessageDialogViewState extends State<SendingMessageDialogView> {
|
||||
|
||||
StreamSubscription? _sendingStreamSubscription;
|
||||
final ValueNotifier<dartz.Either<Failure, Success>?> _sendingNotifier = ValueNotifier(null);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_sendingStreamSubscription = widget.createNewAndSendEmailInteractor
|
||||
.execute(widget.createEmailRequest)
|
||||
.listen(
|
||||
_handleDataStream,
|
||||
onError: _handleErrorStream
|
||||
);
|
||||
}
|
||||
|
||||
void _handleDataStream(dartz.Either<Failure, Success> newState) {
|
||||
_sendingNotifier.value = newState;
|
||||
|
||||
newState.fold(
|
||||
(failure) {
|
||||
if (failure is SendEmailFailure || failure is GenerateEmailFailure) {
|
||||
popBack(result: failure);
|
||||
}
|
||||
},
|
||||
(success) {
|
||||
if (success is SendEmailSuccess) {
|
||||
popBack(result: success);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void _handleErrorStream(Object error, StackTrace stackTrace) {
|
||||
logError('_SendingMessageDialogViewState::_handleErrorStream: Exception = $error');
|
||||
popBack(result: SendEmailFailure(exception: error));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12))),
|
||||
insetPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 24.0,
|
||||
vertical: 16.0
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
color: Colors.white,
|
||||
),
|
||||
width: 400,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
padding: const EdgeInsetsDirectional.symmetric(vertical: 8, horizontal: 12),
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
color: AppColor.colorItemSelected,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
AppLocalizations.of(context).sendingMessage.capitalizeFirstEach,
|
||||
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 17
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 16, end: 16, top: 12, bottom: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'${AppLocalizations.of(context).status}:',
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _sendingNotifier,
|
||||
builder: (context, value, child) {
|
||||
if (value == null) {
|
||||
return child!;
|
||||
}
|
||||
|
||||
return value.fold(
|
||||
(failure) => child!,
|
||||
(success) {
|
||||
if (success is GenerateEmailLoading) {
|
||||
return Text(
|
||||
'Creating email...',
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: AppColor.labelColor,
|
||||
fontSize: 14
|
||||
),
|
||||
);
|
||||
} else if (success is SendEmailLoading) {
|
||||
return Text(
|
||||
'${AppLocalizations.of(context).sendingMessage}...',
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: AppColor.labelColor,
|
||||
fontSize: 14
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return child!;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'${AppLocalizations.of(context).sendingMessage}...',
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: AppColor.labelColor,
|
||||
fontSize: 14
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 16, end: 16, top: 4, bottom: 24),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'${AppLocalizations.of(context).progress}:',
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: LinearProgressIndicator(
|
||||
color: Colors.white.withOpacity(0.6),
|
||||
backgroundColor: AppColor.primaryColor,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_sendingStreamSubscription?.cancel();
|
||||
_sendingNotifier.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.
|
||||
abstract class EmailDataSource {
|
||||
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId);
|
||||
|
||||
Future<bool> sendEmail(
|
||||
Future<void> sendEmail(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
EmailRequest emailRequest,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
|
||||
abstract class HtmlDataSource {
|
||||
Future<EmailContent> transformEmailContent(
|
||||
@@ -13,4 +15,11 @@ abstract class HtmlDataSource {
|
||||
String htmlContent,
|
||||
TransformConfiguration configuration
|
||||
);
|
||||
|
||||
Future<Tuple2<String, Set<EmailBodyPart>>> replaceImageBase64ToImageCID({
|
||||
required String emailContent,
|
||||
required Map<String, Attachment> inlineAttachments
|
||||
});
|
||||
|
||||
Future<String> removeCollapsedExpandedSignatureEffect({required String emailContent});
|
||||
}
|
||||
@@ -42,7 +42,7 @@ class EmailDataSourceImpl extends EmailDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> sendEmail(
|
||||
Future<void> sendEmail(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
EmailRequest emailRequest,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
|
||||
@@ -35,4 +38,26 @@ class HtmlDataSourceImpl extends HtmlDataSource {
|
||||
);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Tuple2<String, Set<EmailBodyPart>>> replaceImageBase64ToImageCID({
|
||||
required String emailContent,
|
||||
required Map<String, Attachment> inlineAttachments
|
||||
}) {
|
||||
return Future.sync(() async {
|
||||
return await _htmlAnalyzer.replaceImageBase64ToImageCID(
|
||||
emailContent: emailContent,
|
||||
inlineAttachments: inlineAttachments
|
||||
);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> removeCollapsedExpandedSignatureEffect({required String emailContent}) {
|
||||
return Future.sync(() async {
|
||||
return await _htmlAnalyzer.removeCollapsedExpandedSignatureEffect(
|
||||
emailContent: emailContent
|
||||
);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:core/data/constants/constant.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/html_transform.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:html/parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:model/email/email_content_type.dart';
|
||||
import 'package:model/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
|
||||
|
||||
class HtmlAnalyzer {
|
||||
@@ -99,4 +104,57 @@ class HtmlAnalyzer {
|
||||
);
|
||||
return htmlContentTransformed;
|
||||
}
|
||||
|
||||
Future<Tuple2<String, Set<EmailBodyPart>>> replaceImageBase64ToImageCID({
|
||||
required String emailContent,
|
||||
required Map<String, Attachment> inlineAttachments
|
||||
}) async {
|
||||
final document = parse(emailContent);
|
||||
final listImgTag = document.querySelectorAll('img[src^="data:image/"][id^="cid:"]');
|
||||
|
||||
final listInlineAttachment = await Future.wait(listImgTag.map((imgTag) async {
|
||||
final idImg = imgTag.attributes['id'];
|
||||
final cid = idImg!.replaceFirst('cid:', '').trim();
|
||||
imgTag.attributes['src'] = 'cid:$cid';
|
||||
imgTag.attributes.remove('id');
|
||||
return cid;
|
||||
})).then((listCid) {
|
||||
final listInlineAttachment = listCid
|
||||
.map((cid) {
|
||||
if (inlineAttachments.containsKey(cid)) {
|
||||
return inlineAttachments[cid]!.toEmailBodyPart(charset: Constant.base64Charset);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.whereNotNull()
|
||||
.toSet();
|
||||
|
||||
return listInlineAttachment;
|
||||
});
|
||||
|
||||
final newContent = document.body?.innerHtml ?? emailContent;
|
||||
|
||||
return Tuple2(newContent, listInlineAttachment);
|
||||
}
|
||||
|
||||
Future<String> removeCollapsedExpandedSignatureEffect({required String emailContent}) async {
|
||||
log('HtmlAnalyzer::removeCollapsedExpandedSignatureEffect: BEFORE = $emailContent');
|
||||
final document = parse(emailContent);
|
||||
final signatureElements = document.querySelectorAll('div.tmail-signature');
|
||||
await Future.wait(signatureElements.map((signatureTag) async {
|
||||
final signatureChildren = signatureTag.children;
|
||||
for (var child in signatureChildren) {
|
||||
log('HtmlAnalyzer::removeCollapsedExpandedSignatureEffect: CHILD = ${child.outerHtml}');
|
||||
if (child.attributes['class']?.contains('tmail-signature-button') == true) {
|
||||
child.remove();
|
||||
} else if (child.attributes['class']?.contains('tmail-signature-content') == true) {
|
||||
signatureTag.innerHtml = child.innerHtml;
|
||||
}
|
||||
}
|
||||
}));
|
||||
final newContent = document.body?.innerHtml ?? emailContent;
|
||||
log('HtmlAnalyzer::removeCollapsedExpandedSignatureEffect: AFTER = $newContent');
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class EmailRepositoryImpl extends EmailRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> sendEmail(
|
||||
Future<void> sendEmail(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
EmailRequest emailRequest,
|
||||
|
||||
@@ -6,4 +6,6 @@ class EmptyEmailContentException implements Exception {}
|
||||
|
||||
class NotFoundEmailRecoveryActionException implements Exception {}
|
||||
|
||||
class NotFoundEmailBlobIdException implements Exception {}
|
||||
class NotFoundEmailBlobIdException implements Exception {}
|
||||
|
||||
class CannotCreateEmailObjectException implements Exception {}
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/extensions/attachment_extension.dart';
|
||||
import 'package:tmail_ui_user/features/offline_mode/model/attachment_hive_cache.dart';
|
||||
|
||||
@@ -19,4 +21,6 @@ extension ListAttachmentsExtension on List<Attachment> {
|
||||
.map((attachment) => attachment.blobId)
|
||||
.whereNotNull()
|
||||
.toSet();
|
||||
|
||||
Set<EmailBodyPart> toEmailBodyPart({String? charset}) => map((attachment) => attachment.toEmailBodyPart(charset: charset)).toSet();
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_r
|
||||
abstract class EmailRepository {
|
||||
Future<Email> getEmailContent(Session session, AccountId accountId, EmailId emailId);
|
||||
|
||||
Future<bool> sendEmail(
|
||||
Future<void> sendEmail(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
EmailRequest emailRequest,
|
||||
|
||||
@@ -96,7 +96,7 @@ class EmailBindings extends BaseBindings {
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.lazyPut(() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => StateDataSourceImpl(
|
||||
Get.find<StateCacheManager>(),
|
||||
Get.find<IOSSharingManager>(),
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ class MailboxDashBoardBindings extends BaseBindings {
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.lazyPut(() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => SearchDataSourceImpl(
|
||||
Get.find<RecentSearchCacheClient>(),
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
|
||||
+9
-1
@@ -30,6 +30,7 @@ import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dar
|
||||
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/extensions/email_request_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||
@@ -1256,11 +1257,14 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
composerArguments = null;
|
||||
ComposerBindings().dispose();
|
||||
composerOverlayState.value = ComposerOverlayState.inActive;
|
||||
|
||||
if (result is SendingEmailArguments) {
|
||||
handleSendEmailAction(result);
|
||||
} else if (result is SaveToDraftArguments) {
|
||||
saveEmailToDraft(arguments: result);
|
||||
} else if (result is SendEmailSuccess) {
|
||||
consumeState(Stream.value(Right<Failure, Success>(result)));
|
||||
} else if (result is SendEmailFailure || result is GenerateEmailFailure) {
|
||||
consumeState(Stream.value(Left<Failure, Success>(result)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1394,6 +1398,10 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
handleSendEmailAction(result);
|
||||
} else if (result is SaveToDraftArguments) {
|
||||
saveEmailToDraft(arguments: result);
|
||||
} else if (result is SendEmailSuccess) {
|
||||
consumeState(Stream.value(Right<Failure, Success>(result)));
|
||||
} else if (result is SendEmailFailure || result is GenerateEmailFailure) {
|
||||
consumeState(Stream.value(Left<Failure, Success>(result)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,10 @@ class ManageAccountDashBoardView extends GetWidget<ManageAccountDashBoardControl
|
||||
const Spacer(),
|
||||
const SizedBox(width: 16),
|
||||
Obx(() => (AvatarBuilder()
|
||||
..text(controller.sessionCurrent?.username.firstCharacter ?? '')
|
||||
..text(controller.accountId.value != null
|
||||
? controller.sessionCurrent?.username.firstCharacter ?? ''
|
||||
: ''
|
||||
)
|
||||
..backgroundColor(Colors.white)
|
||||
..textColor(Colors.black)
|
||||
..context(context)
|
||||
|
||||
@@ -94,4 +94,6 @@ class NetworkConnectionController extends GetxController {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> hasInternetConnection() async => isNetworkConnectionAvailable();
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class SendEmailInteractorBindings extends InteractorsBindings {
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => StateDataSourceImpl(
|
||||
Get.find<StateCacheManager>(),
|
||||
Get.find<IOSSharingManager>(),
|
||||
|
||||
@@ -105,7 +105,7 @@ class FcmInteractorBindings extends InteractorsBindings {
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.lazyPut(() => HtmlDataSourceImpl(
|
||||
Get.find<HtmlAnalyzer>(),
|
||||
Get.find<RemoteExceptionThrower>()));
|
||||
Get.find<CacheExceptionThrower>()));
|
||||
Get.lazyPut(() => StateDataSourceImpl(
|
||||
Get.find<StateCacheManager>(),
|
||||
Get.find<IOSSharingManager>(),
|
||||
|
||||
@@ -255,8 +255,7 @@ class UploadController extends BaseController {
|
||||
return null;
|
||||
}
|
||||
return attachmentsUploaded
|
||||
.map((attachment) => attachment.toEmailBodyPart(
|
||||
disposition: ContentDisposition.attachment.value))
|
||||
.map((attachment) => attachment.toEmailBodyPart())
|
||||
.toSet();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart';
|
||||
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart'
|
||||
if (dart.library.html) 'package:tmail_ui_user/features/network_connection/presentation/web_network_connection_controller.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
@@ -38,17 +38,22 @@ class LocalizationService extends Translations {
|
||||
}
|
||||
|
||||
static Locale getLocaleFromLanguage({String? langCode}) {
|
||||
final languageCacheManager = getBinding<LanguageCacheManager>();
|
||||
log('LocalizationService::_getLocaleFromLanguage:languageCacheManager: $languageCacheManager');
|
||||
final localeStored = languageCacheManager?.getStoredLanguage();
|
||||
log('LocalizationService::_getLocaleFromLanguage():localeStored: $localeStored');
|
||||
if (localeStored != null) {
|
||||
return localeStored;
|
||||
} else {
|
||||
final languageCodeCurrent = langCode ?? Get.deviceLocale?.languageCode;
|
||||
log('LocalizationService::_getLocaleFromLanguage():languageCodeCurrent: $languageCodeCurrent');
|
||||
final localeSelected = supportedLocales.firstWhereOrNull((locale) => locale.languageCode == languageCodeCurrent);
|
||||
return localeSelected ?? Get.deviceLocale ?? defaultLocale;
|
||||
try {
|
||||
final languageCacheManager = getBinding<LanguageCacheManager>();
|
||||
log('LocalizationService::_getLocaleFromLanguage:languageCacheManager: $languageCacheManager');
|
||||
final localeStored = languageCacheManager?.getStoredLanguage();
|
||||
log('LocalizationService::_getLocaleFromLanguage():localeStored: $localeStored');
|
||||
if (localeStored != null) {
|
||||
return localeStored;
|
||||
} else {
|
||||
final languageCodeCurrent = langCode ?? Get.deviceLocale?.languageCode;
|
||||
log('LocalizationService::_getLocaleFromLanguage():languageCodeCurrent: $languageCodeCurrent');
|
||||
final localeSelected = supportedLocales.firstWhereOrNull((locale) => locale.languageCode == languageCodeCurrent);
|
||||
return localeSelected ?? Get.deviceLocale ?? defaultLocale;
|
||||
}
|
||||
} catch (e) {
|
||||
logError('LocalizationService::getLocaleFromLanguage: Exception: $e');
|
||||
return Get.deviceLocale ?? defaultLocale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,19 +68,6 @@ enum ContentDisposition {
|
||||
other
|
||||
}
|
||||
|
||||
extension ContentDispositionExtension on ContentDisposition {
|
||||
String get value {
|
||||
switch(this) {
|
||||
case ContentDisposition.inline:
|
||||
return 'inline';
|
||||
case ContentDisposition.attachment:
|
||||
return 'attachment';
|
||||
case ContentDisposition.other:
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension DispositionStringExtension on String? {
|
||||
ContentDisposition? toContentDisposition() {
|
||||
if (this != null) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:model/extensions/list_attachment_extension.dart';
|
||||
|
||||
extension AttachmentExtension on Attachment {
|
||||
EmailBodyPart toEmailBodyPart({String? disposition, String? charset}) => EmailBodyPart(
|
||||
EmailBodyPart toEmailBodyPart({String? charset}) => EmailBodyPart(
|
||||
partId: partId,
|
||||
blobId: blobId,
|
||||
size: size,
|
||||
@@ -11,7 +12,7 @@ extension AttachmentExtension on Attachment {
|
||||
type: type,
|
||||
cid: cid,
|
||||
charset: charset,
|
||||
disposition: disposition ?? this.disposition?.value);
|
||||
disposition: disposition?.name ?? ContentDisposition.attachment.name);
|
||||
|
||||
Attachment toAttachmentWithDisposition({
|
||||
ContentDisposition? disposition,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
import 'package:core/presentation/extensions/string_extension.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
|
||||
extension UsernameExtension on UserName {
|
||||
String get firstCharacter => value.firstLetterToUpperCase.toUpperCase();
|
||||
String get firstCharacter => value.isNotEmpty ? value[0].toUpperCase() : '';
|
||||
|
||||
EmailAddress toEmailAddress() => EmailAddress(null, value);
|
||||
}
|
||||
Reference in New Issue
Block a user