TF-105 [BUG] Fix loading is blinking when reading email
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import 'package:core/core.dart';
|
|
||||||
import 'package:core/presentation/utils/html_transformer/html_transform.dart';
|
import 'package:core/presentation/utils/html_transformer/html_transform.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
@@ -109,15 +108,7 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (_isGenerating) {
|
if (_isGenerating) {
|
||||||
return Padding(
|
return SizedBox.shrink();
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Center(
|
|
||||||
child: SizedBox(
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
child: CircularProgressIndicator(color: AppColor.primaryColor)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (widget.blockExternalImages != _wereExternalImagesBlocked) {
|
if (widget.blockExternalImages != _wereExternalImagesBlocked) {
|
||||||
_generateHtml(widget.blockExternalImages);
|
_generateHtml(widget.blockExternalImages);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.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_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||||
@@ -30,9 +29,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_inter
|
|||||||
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart';
|
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/constants/email_constants.dart';
|
import 'package:tmail_ui_user/features/email/presentation/constants/email_constants.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/email_content_extension.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart';
|
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
|
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
|
||||||
@@ -157,19 +154,6 @@ class ComposerController extends BaseController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple3<List<MessageContent>, List<Attachment>, Session>? getContentEmailQuoted() {
|
|
||||||
if (composerArguments.value != null) {
|
|
||||||
final emailContent = composerArguments.value!.emailContent;
|
|
||||||
final session = composerArguments.value!.session;
|
|
||||||
if (emailContent != null) {
|
|
||||||
final messageContents = emailContent.getListMessageContent();
|
|
||||||
final attachmentsInline = emailContent.getListAttachmentInline();
|
|
||||||
return Tuple3(messageContents, attachmentsInline, session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void expandEmailAddressAction() {
|
void expandEmailAddressAction() {
|
||||||
final newExpandMode = expandMode.value == ExpandMode.COLLAPSE ? ExpandMode.EXPAND : ExpandMode.COLLAPSE;
|
final newExpandMode = expandMode.value == ExpandMode.COLLAPSE ? ExpandMode.EXPAND : ExpandMode.COLLAPSE;
|
||||||
expandMode.value = newExpandMode;
|
expandMode.value = newExpandMode;
|
||||||
@@ -229,7 +213,6 @@ class ComposerController extends BaseController {
|
|||||||
|
|
||||||
String _getBodyEmailQuotedAsHtml(BuildContext context, HtmlMessagePurifier htmlMessagePurifier) {
|
String _getBodyEmailQuotedAsHtml(BuildContext context, HtmlMessagePurifier htmlMessagePurifier) {
|
||||||
final headerEmailQuoted = getHeaderEmailQuoted(Localizations.localeOf(context).toLanguageTag());
|
final headerEmailQuoted = getHeaderEmailQuoted(Localizations.localeOf(context).toLanguageTag());
|
||||||
final contentEmail = getContentEmailQuoted();
|
|
||||||
|
|
||||||
final headerEmailQuotedAsHtml = headerEmailQuoted != null
|
final headerEmailQuotedAsHtml = headerEmailQuoted != null
|
||||||
? AppLocalizations.of(context).header_email_quoted(headerEmailQuoted.value1, headerEmailQuoted.value2)
|
? AppLocalizations.of(context).header_email_quoted(headerEmailQuoted.value1, headerEmailQuoted.value2)
|
||||||
@@ -237,9 +220,12 @@ class ComposerController extends BaseController {
|
|||||||
: '';
|
: '';
|
||||||
|
|
||||||
var trustAsHtml = '';
|
var trustAsHtml = '';
|
||||||
if (contentEmail != null && contentEmail.value1.isNotEmpty) {
|
|
||||||
final messageContent = contentEmail.value1.first;
|
if (composerArguments.value != null) {
|
||||||
trustAsHtml = messageContent.content;
|
final emailContents = composerArguments.value!.emailContents;
|
||||||
|
if (emailContents != null && emailContents.isNotEmpty) {
|
||||||
|
trustAsHtml = emailContents.first.content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final emailQuotedHtml = '</br></br></br>$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}</br>';
|
final emailQuotedHtml = '</br></br></br>$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}</br>';
|
||||||
@@ -281,7 +267,7 @@ class ComposerController extends BaseController {
|
|||||||
|
|
||||||
Set<EmailBodyPart> _generateAttachments() {
|
Set<EmailBodyPart> _generateAttachments() {
|
||||||
return attachments.map((attachment) =>
|
return attachments.map((attachment) =>
|
||||||
attachment.toEmailBodyPart(Attachment.dispositionAttachment)).toSet();
|
attachment.toEmailBodyPart(ContentDisposition.attachment.value)).toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendEmailAction(BuildContext context) async {
|
void sendEmailAction(BuildContext context) async {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:model/email/email_content.dart';
|
import 'package:model/model.dart';
|
||||||
|
|
||||||
class GetEmailContentSuccess extends UIState {
|
class GetEmailContentSuccess extends UIState {
|
||||||
final EmailContent? emailContent;
|
final List<EmailContent> emailContents;
|
||||||
|
final List<Attachment> attachments;
|
||||||
|
|
||||||
GetEmailContentSuccess(this.emailContent);
|
GetEmailContentSuccess(this.emailContents, this.attachments);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [emailContent];
|
List<Object?> get props => [emailContents, attachments];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetEmailContentFailure extends FeatureFailure {
|
class GetEmailContentFailure extends FeatureFailure {
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ class GetEmailContentInteractor {
|
|||||||
try {
|
try {
|
||||||
yield Right<Failure, Success>(LoadingState());
|
yield Right<Failure, Success>(LoadingState());
|
||||||
final email = await emailRepository.getEmailContent(accountId, emailId);
|
final email = await emailRepository.getEmailContent(accountId, emailId);
|
||||||
yield Right<Failure, Success>(GetEmailContentSuccess(email.toEmailContent()));
|
yield Right<Failure, Success>(GetEmailContentSuccess(
|
||||||
|
email.emailContentList,
|
||||||
|
email.allAttachments));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
yield Left(GetEmailContentFailure(e));
|
yield Left(GetEmailContentFailure(e));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_
|
|||||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/model/web_view_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.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/app_routes.dart';
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
@@ -48,7 +49,8 @@ class EmailController extends BaseController {
|
|||||||
|
|
||||||
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
|
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
|
||||||
final attachmentsExpandMode = ExpandMode.COLLAPSE.obs;
|
final attachmentsExpandMode = ExpandMode.COLLAPSE.obs;
|
||||||
final emailContent = Rxn<EmailContent>();
|
final emailContents = <EmailContent>[].obs;
|
||||||
|
final attachments = <Attachment>[].obs;
|
||||||
EmailId? _currentEmailId;
|
EmailId? _currentEmailId;
|
||||||
|
|
||||||
EmailController(
|
EmailController(
|
||||||
@@ -109,7 +111,7 @@ class EmailController extends BaseController {
|
|||||||
},
|
},
|
||||||
(success) {
|
(success) {
|
||||||
if (success is GetEmailContentSuccess) {
|
if (success is GetEmailContentSuccess) {
|
||||||
emailContent.value = success.emailContent;
|
_getEmailContentSuccess(success);
|
||||||
} else if (success is MarkAsEmailReadSuccess) {
|
} else if (success is MarkAsEmailReadSuccess) {
|
||||||
_markAsEmailReadSuccess(success);
|
_markAsEmailReadSuccess(success);
|
||||||
} else if (success is ExportAttachmentSuccess) {
|
} else if (success is ExportAttachmentSuccess) {
|
||||||
@@ -126,10 +128,19 @@ class EmailController extends BaseController {
|
|||||||
void onError(error) {
|
void onError(error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _getEmailContentSuccess(GetEmailContentSuccess success) {
|
||||||
|
emailContents.value = success.emailContents;
|
||||||
|
attachments.value = success.attachments;
|
||||||
|
if (emailContents.isNotEmpty) {
|
||||||
|
dispatchState(Right(WebViewLoadingState()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _clearEmailContent() {
|
void _clearEmailContent() {
|
||||||
toggleDisplayEmailAddressAction(expandMode: ExpandMode.COLLAPSE);
|
toggleDisplayEmailAddressAction(expandMode: ExpandMode.COLLAPSE);
|
||||||
attachmentsExpandMode.value = ExpandMode.COLLAPSE;
|
attachmentsExpandMode.value = ExpandMode.COLLAPSE;
|
||||||
emailContent.value = null;
|
emailContents.clear();
|
||||||
|
attachments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleDisplayEmailAddressAction({required ExpandMode expandMode}) {
|
void toggleDisplayEmailAddressAction({required ExpandMode expandMode}) {
|
||||||
@@ -150,13 +161,19 @@ class EmailController extends BaseController {
|
|||||||
}
|
}
|
||||||
mailboxDashBoardController.dispatchState(Right(success));
|
mailboxDashBoardController.dispatchState(Right(success));
|
||||||
|
|
||||||
if (success is MarkAsEmailReadSuccess && success.readActions == ReadActions.markAsUnread) {
|
if (success is MarkAsEmailReadSuccess
|
||||||
|
&& success.readActions == ReadActions.markAsUnread
|
||||||
|
&& Get.context != null
|
||||||
|
&& !responsiveUtils.isDesktop(Get.context!)) {
|
||||||
backToThreadView();
|
backToThreadView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _markAsEmailReadFailure(Failure failure) {
|
void _markAsEmailReadFailure(Failure failure) {
|
||||||
if (failure is MarkAsEmailReadFailure && failure.readActions == ReadActions.markAsUnread) {
|
if (failure is MarkAsEmailReadFailure
|
||||||
|
&& failure.readActions == ReadActions.markAsUnread
|
||||||
|
&& Get.context != null
|
||||||
|
&& !responsiveUtils.isDesktop(Get.context!)) {
|
||||||
backToThreadView();
|
backToThreadView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,17 +347,25 @@ class EmailController extends BaseController {
|
|||||||
&& mailboxDashBoardController.selectedEmail.value != null;
|
&& mailboxDashBoardController.selectedEmail.value != null;
|
||||||
|
|
||||||
void backToThreadView() {
|
void backToThreadView() {
|
||||||
|
if (emailContents.isNotEmpty) {
|
||||||
|
dispatchState(Right(WebViewLoadCompletedState()));
|
||||||
|
}
|
||||||
popBack();
|
popBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pressEmailAction(EmailActionType emailActionType) {
|
void pressEmailAction(EmailActionType emailActionType) {
|
||||||
if (canComposeEmail()) {
|
if (canComposeEmail()) {
|
||||||
|
if (emailContents.isNotEmpty) {
|
||||||
|
clearState();
|
||||||
|
}
|
||||||
|
|
||||||
push(
|
push(
|
||||||
AppRoutes.COMPOSER,
|
AppRoutes.COMPOSER,
|
||||||
arguments: ComposerArguments(
|
arguments: ComposerArguments(
|
||||||
emailActionType: emailActionType,
|
emailActionType: emailActionType,
|
||||||
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
||||||
emailContent: emailContent.value,
|
emailContents: emailContents,
|
||||||
|
attachments: attachments,
|
||||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
session: mailboxDashBoardController.sessionCurrent!,
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/email_controller.dart';
|
import 'package:tmail_ui_user/features/email/presentation/email_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/web_view_state.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/web_view_state.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/app_bar_mail_widget_builder.dart';
|
import 'package:tmail_ui_user/features/email/presentation/widgets/app_bar_mail_widget_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart';
|
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart';
|
import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/email_content_extension.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/list_attachment_extension.dart';
|
import 'package:tmail_ui_user/features/email/presentation/extensions/list_attachment_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/widgets/email_content_place_holder_loading_widget.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart';
|
import 'package:tmail_ui_user/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:filesize/filesize.dart';
|
import 'package:filesize/filesize.dart';
|
||||||
@@ -28,6 +27,11 @@ class EmailView extends GetView {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
emailController.viewState.value.map((success) {
|
||||||
|
if (success is WebViewLoadCompletedState && emailController.emailContents.isNotEmpty) {
|
||||||
|
emailController.dispatchState(Right(WebViewLoadingState()));
|
||||||
|
}
|
||||||
|
});
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
backgroundColor: AppColor.primaryLightColor,
|
backgroundColor: AppColor.primaryLightColor,
|
||||||
@@ -41,7 +45,7 @@ class EmailView extends GetView {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildAppBar(context),
|
_buildAppBar(context),
|
||||||
Expanded(child: _buildEmailContent(context)),
|
Expanded(child: _buildEmailBody(context)),
|
||||||
_buildBottomBar(context),
|
_buildBottomBar(context),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
@@ -74,7 +78,7 @@ class EmailView extends GetView {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEmailContent(BuildContext context) {
|
Widget _buildEmailBody(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: AppColor.bgMessenger,
|
color: AppColor.bgMessenger,
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
@@ -122,12 +126,7 @@ class EmailView extends GetView {
|
|||||||
return Obx(() => emailController.viewState.value.fold(
|
return Obx(() => emailController.viewState.value.fold(
|
||||||
(failure) => SizedBox.shrink(),
|
(failure) => SizedBox.shrink(),
|
||||||
(success) => success is LoadingState || success is WebViewLoadingState
|
(success) => success is LoadingState || success is WebViewLoadingState
|
||||||
? Center(child: Padding(
|
? EmailContentPlaceHolderLoading(responsiveUtils: responsiveUtils)
|
||||||
padding: EdgeInsets.only(top: 16, bottom: 16),
|
|
||||||
child: SizedBox(
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
|
||||||
: SizedBox.shrink()));
|
: SizedBox.shrink()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,29 +149,27 @@ class EmailView extends GetView {
|
|||||||
emailController.emailAddressExpandMode.value)
|
emailController.emailAddressExpandMode.value)
|
||||||
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
|
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
|
||||||
.build()),
|
.build()),
|
||||||
_buildListAttachments(context),
|
|
||||||
_buildLoadingView(),
|
_buildLoadingView(),
|
||||||
_buildListMessageContent(),
|
_buildAttachments(context),
|
||||||
|
_buildEmailContent(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildListAttachments(BuildContext context) {
|
Widget _buildAttachments(BuildContext context) {
|
||||||
if (emailController.mailboxDashBoardController.selectedEmail.value?.hasAttachment == true) {
|
return Obx(() => emailController.viewState.value.fold(
|
||||||
return Obx(() {
|
(failure) => SizedBox.shrink(),
|
||||||
if (emailController.emailContent.value != null) {
|
(success) {
|
||||||
final attachments = emailController.emailContent.value!.getListAttachment();
|
if (success is LoadingState || success is WebViewLoadingState) {
|
||||||
return attachments.isNotEmpty
|
return SizedBox.shrink();
|
||||||
? _buildAttachmentsBody(context, attachments)
|
} else {
|
||||||
: SizedBox.shrink();
|
final attachments = emailController.attachments.attachmentsWithDispositionAttachment;
|
||||||
} else {
|
return attachments.isNotEmpty
|
||||||
return SizedBox.shrink();
|
? _buildAttachmentsBody(context, attachments)
|
||||||
}
|
: SizedBox.shrink();
|
||||||
});
|
}
|
||||||
} else {
|
}));
|
||||||
return SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _getAttachmentLimitDisplayed(BuildContext context) {
|
int _getAttachmentLimitDisplayed(BuildContext context) {
|
||||||
@@ -281,31 +278,12 @@ class EmailView extends GetView {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildListMessageContent() {
|
Widget _buildEmailContent() {
|
||||||
return Obx(() {
|
return Obx(() => emailController.emailContents.isNotEmpty
|
||||||
final messageContents = emailController.emailContent.value?.getListMessageContent();
|
? HtmlContentViewer(
|
||||||
|
message: emailController.emailContents.first.content,
|
||||||
if (messageContents != null && messageContents.isNotEmpty) {
|
onWebViewLoadStop: (webController, uri) => emailController.dispatchState(Right(WebViewLoadCompletedState())),
|
||||||
return messageContents.first.textFormat == TextFormat.PLAIN
|
mailtoDelegate: (uri) async {})
|
||||||
? Padding(
|
: SizedBox.shrink());
|
||||||
padding: EdgeInsets.only(top: 16),
|
|
||||||
child: Text(
|
|
||||||
'${messageContents.first.content}',
|
|
||||||
style: TextStyle(fontSize: 12,
|
|
||||||
color: AppColor.mailboxTextColor)))
|
|
||||||
: HtmlContentViewer(
|
|
||||||
message: messageContents.first.content,
|
|
||||||
onWebViewLoadStart: (webController, uri) {
|
|
||||||
emailController.dispatchState(Right(WebViewLoadingState()));
|
|
||||||
},
|
|
||||||
onWebViewLoadStop: (webController, uri) {
|
|
||||||
emailController.clearState();
|
|
||||||
},
|
|
||||||
mailtoDelegate: (uri) async {},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return SizedBox.shrink();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/constants/email_constants.dart';
|
|
||||||
import 'package:model/model.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
|
||||||
|
|
||||||
extension EmailContentExtension on EmailContent {
|
|
||||||
|
|
||||||
List<MessageContent> getListMessageContent() {
|
|
||||||
Map<PartId, TextFormat> mapHtmlBody = Map();
|
|
||||||
List<MessageContent> listMessageContent = [];
|
|
||||||
|
|
||||||
htmlBody?.forEach((element) {
|
|
||||||
if (element.partId != null && element.type != null) {
|
|
||||||
mapHtmlBody[element.partId!] = element.type!.mimeType == EmailConstants.HTML_TEXT
|
|
||||||
? TextFormat.HTML
|
|
||||||
: TextFormat.PLAIN;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bodyValues?.forEach((key, value) {
|
|
||||||
listMessageContent.add(MessageContent(mapHtmlBody[key] ?? TextFormat.PLAIN, value.value));
|
|
||||||
});
|
|
||||||
|
|
||||||
return listMessageContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Attachment> getListAttachment() {
|
|
||||||
if (attachments != null) {
|
|
||||||
return attachments!
|
|
||||||
.where((element) => (element.disposition != null && element.disposition != 'inline'))
|
|
||||||
.map((item) => item.toAttachment())
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Attachment> getListAttachmentInline() {
|
|
||||||
if (attachments != null) {
|
|
||||||
return attachments!
|
|
||||||
.where((element) => element.disposition == 'inline')
|
|
||||||
.map((item) => item.toAttachment())
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,4 +11,12 @@ extension ListAttachmentExtension on List<Attachment> {
|
|||||||
});
|
});
|
||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Attachment> get attachmentsWithDispositionAttachment {
|
||||||
|
return where((element) => element.disposition == ContentDisposition.attachment).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Attachment> get attachmentWithDispositionInlines {
|
||||||
|
return where((element) => element.disposition == ContentDisposition.inline).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,8 @@ import 'package:model/model.dart';
|
|||||||
class ComposerArguments with EquatableMixin {
|
class ComposerArguments with EquatableMixin {
|
||||||
final EmailActionType emailActionType;
|
final EmailActionType emailActionType;
|
||||||
final PresentationEmail? presentationEmail;
|
final PresentationEmail? presentationEmail;
|
||||||
final EmailContent? emailContent;
|
final List<EmailContent>? emailContents;
|
||||||
|
final List<Attachment>? attachments;
|
||||||
final Session session;
|
final Session session;
|
||||||
final UserProfile userProfile;
|
final UserProfile userProfile;
|
||||||
final Map<Role, MailboxId> mapMailboxId;
|
final Map<Role, MailboxId> mapMailboxId;
|
||||||
@@ -16,7 +17,8 @@ class ComposerArguments with EquatableMixin {
|
|||||||
ComposerArguments({
|
ComposerArguments({
|
||||||
this.emailActionType = EmailActionType.compose,
|
this.emailActionType = EmailActionType.compose,
|
||||||
this.presentationEmail,
|
this.presentationEmail,
|
||||||
this.emailContent,
|
this.emailContents,
|
||||||
|
this.attachments,
|
||||||
this.mailboxRole,
|
this.mailboxRole,
|
||||||
required this.session,
|
required this.session,
|
||||||
required this.userProfile,
|
required this.userProfile,
|
||||||
@@ -27,7 +29,8 @@ class ComposerArguments with EquatableMixin {
|
|||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
emailActionType,
|
emailActionType,
|
||||||
presentationEmail,
|
presentationEmail,
|
||||||
emailContent,
|
emailContents,
|
||||||
|
attachments,
|
||||||
mailboxRole,
|
mailboxRole,
|
||||||
session,
|
session,
|
||||||
userProfile,
|
userProfile,
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
|
||||||
import 'package:model/model.dart';
|
|
||||||
|
|
||||||
class MessageContent with EquatableMixin {
|
|
||||||
|
|
||||||
final TextFormat textFormat;
|
|
||||||
final String content;
|
|
||||||
|
|
||||||
MessageContent(this.textFormat, this.content);
|
|
||||||
|
|
||||||
bool hasImageInlineWithCid() => content.contains('cid:');
|
|
||||||
|
|
||||||
String getContentHasInlineAttachment(String baseDownloadUrl, AccountId accountId, List<Attachment> attachments) {
|
|
||||||
var contentValid = content;
|
|
||||||
attachments.forEach((attachment) {
|
|
||||||
if(attachment.cid != null) {
|
|
||||||
final urlDownloadImage = attachment.getDownloadUrl(baseDownloadUrl, accountId);
|
|
||||||
contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return contentValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [textFormat, content];
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
enum TextFormat {
|
|
||||||
HTML,
|
|
||||||
PLAIN
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,13 @@ import 'package:core/core.dart';
|
|||||||
class WebViewLoadingState extends UIState {
|
class WebViewLoadingState extends UIState {
|
||||||
WebViewLoadingState();
|
WebViewLoadingState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebViewLoadCompletedState extends UIState {
|
||||||
|
WebViewLoadCompletedState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
|
||||||
|
import 'package:core/core.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const List<Color> _defaultColors = [Color.fromRGBO(0, 0, 0, 0.1), Color(0x44CCCCCC), Color.fromRGBO(0, 0, 0, 0.1)];
|
||||||
|
|
||||||
|
Decoration _radiusBoxDecoration({
|
||||||
|
required Animation animation,
|
||||||
|
bool hasCustomColors = false,
|
||||||
|
AlignmentGeometry beginAlign = Alignment.topLeft,
|
||||||
|
AlignmentGeometry endAlign = Alignment.bottomRight,
|
||||||
|
List<Color> colors = _defaultColors,
|
||||||
|
double radius = 10.0
|
||||||
|
}) {
|
||||||
|
return BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(radius),
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: beginAlign,
|
||||||
|
end: endAlign,
|
||||||
|
colors: hasCustomColors
|
||||||
|
? colors.map((color) {
|
||||||
|
return color;
|
||||||
|
}).toList()
|
||||||
|
: [
|
||||||
|
Color.fromRGBO(0, 0, 0, 0.1),
|
||||||
|
Color(0x32E5E5E5),
|
||||||
|
Color.fromRGBO(0, 0, 0, 0.1),
|
||||||
|
],
|
||||||
|
stops: [animation.value - 2, animation.value, animation.value + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailContentPlaceHolderLoading extends StatefulWidget {
|
||||||
|
|
||||||
|
final ResponsiveUtils responsiveUtils;
|
||||||
|
|
||||||
|
const EmailContentPlaceHolderLoading({
|
||||||
|
Key? key,
|
||||||
|
required this.responsiveUtils,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EmailContentPlaceHolderLoadingState createState() => _EmailContentPlaceHolderLoadingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmailContentPlaceHolderLoadingState extends State<EmailContentPlaceHolderLoading> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _animationController;
|
||||||
|
late Animation<double> _animation;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_animationController = AnimationController(duration: Duration(seconds: 1), vsync: this)..repeat();
|
||||||
|
_animation = Tween<double>(begin: -2, end: 2)
|
||||||
|
.animate(CurvedAnimation(curve: Curves.easeInOutSine, parent: _animationController));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_animationController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedBuilder(
|
||||||
|
animation: _animation,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(top: 20),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(children: [
|
||||||
|
_placeHolderAttachment(context),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
_placeHolderAttachment(context),
|
||||||
|
if (!widget.responsiveUtils.isMobile(context))
|
||||||
|
SizedBox(width: 16),
|
||||||
|
if (!widget.responsiveUtils.isMobile(context))
|
||||||
|
_placeHolderAttachment(context),
|
||||||
|
if (widget.responsiveUtils.isTablet(context))
|
||||||
|
SizedBox(width: 16),
|
||||||
|
if (widget.responsiveUtils.isTablet(context))
|
||||||
|
_placeHolderAttachment(context),
|
||||||
|
]),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(right: 64),
|
||||||
|
height: 10,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation, radius: 5)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation, radius: 5)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(right: 128),
|
||||||
|
height: 10,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation, radius: 5)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _placeHolderAttachment(BuildContext context) {
|
||||||
|
double width = MediaQuery.of(context).size.width;
|
||||||
|
final percentAttachment = widget.responsiveUtils.isMobile(context)
|
||||||
|
? 0.4
|
||||||
|
: widget.responsiveUtils.isTablet(context) ? 0.22 : 0.14;
|
||||||
|
return Container(
|
||||||
|
height: 55,
|
||||||
|
width: width * percentAttachment,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation, radius: 12)),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Expanded(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 5,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation)),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
height: 5,
|
||||||
|
decoration: _radiusBoxDecoration(animation: _animation))
|
||||||
|
],
|
||||||
|
))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,15 +9,13 @@ import 'package:uri/uri.dart';
|
|||||||
|
|
||||||
class Attachment with EquatableMixin {
|
class Attachment with EquatableMixin {
|
||||||
|
|
||||||
static final String dispositionAttachment = 'attachment';
|
|
||||||
|
|
||||||
final PartId? partId;
|
final PartId? partId;
|
||||||
final Id? blobId;
|
final Id? blobId;
|
||||||
final UnsignedInt? size;
|
final UnsignedInt? size;
|
||||||
final String? name;
|
final String? name;
|
||||||
final MediaType? type;
|
final MediaType? type;
|
||||||
final String? cid;
|
final String? cid;
|
||||||
final String? disposition;
|
final ContentDisposition? disposition;
|
||||||
|
|
||||||
Attachment({
|
Attachment({
|
||||||
this.partId,
|
this.partId,
|
||||||
@@ -42,4 +40,39 @@ class Attachment with EquatableMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [partId, blobId, size, name, type, cid, disposition];
|
List<Object?> get props => [partId, blobId, size, name, type, cid, disposition];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ContentDisposition {
|
||||||
|
inline,
|
||||||
|
attachment,
|
||||||
|
other
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ContentDispositionExtension on ContentDisposition {
|
||||||
|
String get value {
|
||||||
|
switch(this) {
|
||||||
|
case ContentDisposition.inline:
|
||||||
|
return 'inline';
|
||||||
|
case ContentDisposition.attachment:
|
||||||
|
return 'attachment';
|
||||||
|
case ContentDisposition.other:
|
||||||
|
return this.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DispositionStringExtension on String? {
|
||||||
|
ContentDisposition? toContentDisposition() {
|
||||||
|
if (this != null) {
|
||||||
|
switch(this) {
|
||||||
|
case 'inline':
|
||||||
|
return ContentDisposition.inline;
|
||||||
|
case 'attachment':
|
||||||
|
return ContentDisposition.attachment;
|
||||||
|
default:
|
||||||
|
return ContentDisposition.other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,29 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
import 'package:model/email/email_content_type.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_value.dart';
|
import 'package:model/model.dart';
|
||||||
|
|
||||||
class EmailContent with EquatableMixin {
|
class EmailContent with EquatableMixin {
|
||||||
|
|
||||||
final EmailId id;
|
final String content;
|
||||||
final Set<EmailBodyPart>? htmlBody;
|
final EmailContentType type;
|
||||||
final Set<EmailBodyPart>? attachments;
|
|
||||||
final Map<PartId, EmailBodyValue>? bodyValues;
|
|
||||||
|
|
||||||
EmailContent(
|
EmailContent(this.type, this.content);
|
||||||
this.id,
|
|
||||||
{
|
bool hasImageInlineWithCid() => content.contains('cid:');
|
||||||
this.htmlBody,
|
|
||||||
this.attachments,
|
String getContentHasInlineAttachment(String baseDownloadUrl, AccountId accountId, List<Attachment> attachments) {
|
||||||
this.bodyValues
|
var contentValid = content;
|
||||||
}
|
attachments.forEach((attachment) {
|
||||||
);
|
if(attachment.cid != null) {
|
||||||
|
final urlDownloadImage = attachment.getDownloadUrl(baseDownloadUrl, accountId);
|
||||||
|
contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return contentValid;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [type, content];
|
||||||
id,
|
|
||||||
htmlBody,
|
|
||||||
attachments,
|
|
||||||
bodyValues
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
enum EmailContentType {
|
||||||
|
textHtml,
|
||||||
|
textPlain,
|
||||||
|
other
|
||||||
|
}
|
||||||
@@ -9,5 +9,5 @@ extension EmailBodyPartExtension on EmailBodyPart {
|
|||||||
name: name,
|
name: name,
|
||||||
type: type,
|
type: type,
|
||||||
cid: cid,
|
cid: cid,
|
||||||
disposition: disposition);
|
disposition: disposition.toContentDisposition());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.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:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||||
import 'package:model/email/email_property.dart';
|
import 'package:model/email/email_property.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
@@ -22,15 +24,6 @@ extension EmailExtension on Email {
|
|||||||
return listEmailAddress;
|
return listEmailAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmailContent toEmailContent() {
|
|
||||||
return EmailContent(
|
|
||||||
id,
|
|
||||||
htmlBody: htmlBody,
|
|
||||||
attachments: attachments,
|
|
||||||
bodyValues: bodyValues
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Email updatedEmail({Map<KeyWordIdentifier, bool>? newKeywords}) {
|
Email updatedEmail({Map<KeyWordIdentifier, bool>? newKeywords}) {
|
||||||
return Email(
|
return Email(
|
||||||
id,
|
id,
|
||||||
@@ -86,4 +79,32 @@ extension EmailExtension on Email {
|
|||||||
mailboxIds: updatedProperties.contain(EmailProperty.mailboxIds) ? newEmail.mailboxIds : mailboxIds,
|
mailboxIds: updatedProperties.contain(EmailProperty.mailboxIds) ? newEmail.mailboxIds : mailboxIds,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<EmailContent> get emailContentList {
|
||||||
|
final newHtmlBody = htmlBody
|
||||||
|
?.where((emailBody) => emailBody.partId != null && emailBody.type != null)
|
||||||
|
.toList() ?? <EmailBodyPart>[];
|
||||||
|
|
||||||
|
final mapHtmlBody = Map<PartId, MediaType>.fromIterable(
|
||||||
|
newHtmlBody,
|
||||||
|
key: (emailBody) => emailBody.partId!,
|
||||||
|
value: (emailBody) => emailBody.type!,
|
||||||
|
);
|
||||||
|
|
||||||
|
final emailContents = bodyValues?.entries
|
||||||
|
.map((entries) => EmailContent(mapHtmlBody[entries.key].toEmailContentType(), entries.value.value))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return emailContents ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Attachment> get allAttachments {
|
||||||
|
if (attachments != null) {
|
||||||
|
return attachments!
|
||||||
|
.where((element) => element.disposition != null)
|
||||||
|
.map((item) => item.toAttachment())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import 'package:http_parser/http_parser.dart';
|
||||||
|
import 'package:model/email/email_content_type.dart';
|
||||||
|
|
||||||
|
extension MediaTypeExtension on MediaType? {
|
||||||
|
|
||||||
|
EmailContentType toEmailContentType() {
|
||||||
|
if (this == null) {
|
||||||
|
return EmailContentType.textHtml;
|
||||||
|
} else {
|
||||||
|
switch(this!.mimeType) {
|
||||||
|
case 'text/html':
|
||||||
|
return EmailContentType.textHtml;
|
||||||
|
case 'text/plain':
|
||||||
|
return EmailContentType.textPlain;
|
||||||
|
default:
|
||||||
|
return EmailContentType.other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ export 'email/move_action.dart';
|
|||||||
export 'email/mark_star_action.dart';
|
export 'email/mark_star_action.dart';
|
||||||
export 'email/email_property.dart';
|
export 'email/email_property.dart';
|
||||||
export 'email/email_filter.dart';
|
export 'email/email_filter.dart';
|
||||||
|
export 'email/email_content_type.dart';
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
export 'extensions/email_address_extension.dart';
|
export 'extensions/email_address_extension.dart';
|
||||||
@@ -50,6 +51,7 @@ export 'extensions/properties_extension.dart';
|
|||||||
export 'extensions/list_mailbox_extension.dart';
|
export 'extensions/list_mailbox_extension.dart';
|
||||||
export 'extensions/list_extension.dart';
|
export 'extensions/list_extension.dart';
|
||||||
export 'extensions/list_email_extension.dart';
|
export 'extensions/list_email_extension.dart';
|
||||||
|
export 'extensions/media_type_extension.dart';
|
||||||
|
|
||||||
// Download
|
// Download
|
||||||
export 'download/download_task_id.dart';
|
export 'download/download_task_id.dart';
|
||||||
|
|||||||
Reference in New Issue
Block a user