Add presentation layer for GetEmailContent
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
|
||||
typedef OnBackActionClick = void Function();
|
||||
|
||||
@@ -11,11 +14,13 @@ class AppBarMailWidgetBuilder {
|
||||
final BuildContext _context;
|
||||
final ImagePaths _imagePaths;
|
||||
final ResponsiveUtils _responsiveUtils;
|
||||
final PresentationEmail? _presentationEmail;
|
||||
|
||||
AppBarMailWidgetBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._responsiveUtils,
|
||||
this._presentationEmail,
|
||||
);
|
||||
|
||||
AppBarMailWidgetBuilder onBackActionClick(
|
||||
@@ -28,6 +33,7 @@ class AppBarMailWidgetBuilder {
|
||||
return Container(
|
||||
key: Key('app_bar_messenger_widget'),
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.zero,
|
||||
color: Colors.white,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
@@ -35,7 +41,7 @@ class AppBarMailWidgetBuilder {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (!_responsiveUtils.isDesktop(_context))
|
||||
if (!_responsiveUtils.isDesktop(_context) || Get.currentRoute != AppRoutes.MAILBOX_DASHBOARD)
|
||||
Expanded(child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@@ -63,11 +69,15 @@ class AppBarMailWidgetBuilder {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ButtonBuilder(_imagePaths.icTrash).key(Key('button_delete_message')).build(),
|
||||
SizedBox(width: 20),
|
||||
SizedBox(width: 10),
|
||||
ButtonBuilder(_imagePaths.icEyeDisable).key(Key('button_hide_message')).build(),
|
||||
SizedBox(width: 20),
|
||||
ButtonBuilder(_imagePaths.icStar).key(Key('button_favorite_message')).build(),
|
||||
SizedBox(width: 20),
|
||||
SizedBox(width: 10),
|
||||
ButtonBuilder((_presentationEmail != null && _presentationEmail!.isFlaggedEmail())
|
||||
? _imagePaths.icFlagged
|
||||
: _imagePaths.icFlag)
|
||||
.key(Key('button_favorite_message'))
|
||||
.build(),
|
||||
SizedBox(width: 10),
|
||||
ButtonBuilder(_imagePaths.icFolder).key(Key('button_add_folder_message')).build(),
|
||||
]
|
||||
);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:filesize/filesize.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart';
|
||||
|
||||
typedef OnOpenAttachmentFileActionClick = void Function();
|
||||
|
||||
class AttachmentFileTileBuilder {
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
final AttachmentFile _attachmentFile;
|
||||
|
||||
OnOpenAttachmentFileActionClick? _onOpenAttachmentFileActionClick;
|
||||
|
||||
AttachmentFileTileBuilder(this._imagePaths, this._attachmentFile);
|
||||
|
||||
AttachmentFileTileBuilder onOpenAttachmentFileActionClick(
|
||||
OnOpenAttachmentFileActionClick onOpenAttachmentFileActionClick) {
|
||||
_onOpenAttachmentFileActionClick = onOpenAttachmentFileActionClick;
|
||||
return this;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
splashColor: Colors.transparent ,
|
||||
highlightColor: Colors.transparent),
|
||||
child: Container(
|
||||
key: Key('attach_file_tile'),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.attachmentFileBorderColor),
|
||||
color: Colors.white),
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
if (_onOpenAttachmentFileActionClick != null) {
|
||||
_onOpenAttachmentFileActionClick!();
|
||||
}},
|
||||
leading: Transform(
|
||||
transform: Matrix4.translationValues(0.0, 2.0, 0.0),
|
||||
child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)),
|
||||
title: Transform(
|
||||
transform: Matrix4.translationValues(-18.0, -8.0, 0.0),
|
||||
child: Text(
|
||||
_attachmentFile.name ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileNameColor, fontWeight: FontWeight.w500),
|
||||
)),
|
||||
subtitle: _attachmentFile.size != null && _attachmentFile.size?.value != 0
|
||||
? Transform(
|
||||
transform: Matrix4.translationValues(-18.0, -8.0, 0.0),
|
||||
child: Text(
|
||||
filesize(_attachmentFile.size?.value),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileSizeColor)))
|
||||
: null
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.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';
|
||||
import 'package:sanitize_html/sanitize_html.dart' show sanitizeHtml;
|
||||
|
||||
class MessageContentTileBuilder {
|
||||
|
||||
final MessageContent _messageContent;
|
||||
final ImagePaths _imagePaths;
|
||||
final List<AttachmentFile> _attachmentInlines;
|
||||
final Session? _session;
|
||||
final AccountId? _accountId;
|
||||
|
||||
MessageContentTileBuilder(
|
||||
this._messageContent,
|
||||
this._imagePaths,
|
||||
this._attachmentInlines,
|
||||
this._session,
|
||||
this._accountId,
|
||||
);
|
||||
|
||||
Widget build() {
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent),
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: Center(
|
||||
child: _messageContent.textFormat == TextFormat.PLAIN
|
||||
? Text('${_messageContent.content}', style: TextStyle(fontSize: 12, color: AppColor.mailboxTextColor))
|
||||
: HtmlWidget(
|
||||
cleanHtmlMessage(_messageContent.content),
|
||||
textStyle: TextStyle(fontSize: 12, color: AppColor.mailboxTextColor),
|
||||
buildAsync: true,
|
||||
factoryBuilder: () => _PopupPhotoViewWidgetFactory(_imagePaths),
|
||||
buildAsyncBuilder: (_, snapshot) => snapshot.data ?? SizedBox(
|
||||
height: 30,
|
||||
width: 30,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor)),
|
||||
webViewJs: false),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
String getHtmlMessageText() {
|
||||
final message = (_attachmentInlines.isNotEmpty && _session != null && _accountId != null && _messageContent.hasImageInlineWithCid())
|
||||
? '${_messageContent.getContentHasInlineAttachment(_session!, _accountId!, _attachmentInlines)}'
|
||||
: '${_messageContent.content}';
|
||||
return message;
|
||||
}
|
||||
|
||||
String cleanHtmlMessage(String message) => hasTagTable(getHtmlMessageText()) ? sanitizeHtml(getHtmlMessageText()) : message;
|
||||
|
||||
bool hasTagTable(String html) => html.toLowerCase().contains('</table>');
|
||||
}
|
||||
|
||||
class _PopupPhotoViewWidgetFactory extends WidgetFactory {
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
|
||||
_PopupPhotoViewWidgetFactory(this._imagePaths);
|
||||
|
||||
@override
|
||||
Widget? buildImageWidget(BuildMetadata meta, {String? semanticLabel, required String url}) {
|
||||
final built = super.buildImageWidget(meta, semanticLabel: semanticLabel, url: url);
|
||||
|
||||
if (built is Image) {
|
||||
return Builder(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
PhotoView(
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: url),
|
||||
imageProvider: built.image),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, top: 35),
|
||||
child: IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill)))
|
||||
],
|
||||
),
|
||||
))),
|
||||
child: Hero(tag: url, child: built),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return built;
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnOpenExpandAddressReceiverActionClick = void Function();
|
||||
|
||||
class SenderAndReceiverInformationTileBuilder {
|
||||
|
||||
static const int LIMIT_ADDRESS_DISPLAY = 1;
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
final BuildContext _context;
|
||||
final PresentationEmail? _presentationEmail;
|
||||
final ExpandMode _expandMode;
|
||||
|
||||
OnOpenExpandAddressReceiverActionClick? _onOpenExpandAddressReceiverActionClick;
|
||||
|
||||
SenderAndReceiverInformationTileBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._presentationEmail,
|
||||
this._expandMode,
|
||||
);
|
||||
|
||||
SenderAndReceiverInformationTileBuilder onOpenExpandAddressReceiverActionClick(OnOpenExpandAddressReceiverActionClick onOpenExpandAddressReceiverActionClick) {
|
||||
_onOpenExpandAddressReceiverActionClick = onOpenExpandAddressReceiverActionClick;
|
||||
return this;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
if (_presentationEmail == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent),
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: ListTile(
|
||||
leading: Transform(
|
||||
transform: Matrix4.translationValues(-15.0, -8.0, 0.0),
|
||||
child: AvatarBuilder()
|
||||
.text('${_presentationEmail!.getAvatarText()}')
|
||||
.size(40)
|
||||
.iconStatus(_imagePaths.icOffline)
|
||||
.build()),
|
||||
title: Transform(
|
||||
transform: Matrix4.translationValues(-15.0, 0.0, 0.0),
|
||||
child: Text(
|
||||
'${AppLocalizations.of(_context).from_email_address_prefix}: ${_presentationEmail!.getSenderName().inCaps}',
|
||||
style: TextStyle(fontSize: 16, color: AppColor.nameUserColor, fontWeight: FontWeight.w500),
|
||||
)),
|
||||
subtitle: Transform(
|
||||
transform: Matrix4.translationValues(-15.0, 0.0, 0.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) _buildAddressToReceiverWidget(),
|
||||
if (_presentationEmail!.cc.numberEmailAddress() > 0) _buildAddressCcReceiverWidget(),
|
||||
if (_presentationEmail!.bcc.numberEmailAddress() > 0) _buildAddressBccReceiverWidget(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: Text(
|
||||
'${_presentationEmail!.getSentTime()}',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor),
|
||||
))
|
||||
],
|
||||
))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildExpandAddressWidget(String typeReceiver, String nameAddress) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$typeReceiver: ',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)),
|
||||
Expanded(child: Text(
|
||||
'$nameAddress',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500),
|
||||
))
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildCollapseAddressWidget(String typeReceiver, String nameAddress) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
'$typeReceiver: $nameAddress',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)),
|
||||
if (_expandMode == ExpandMode.COLLAPSE
|
||||
&& _presentationEmail != null
|
||||
&& _presentationEmail!.numberOfAllEmailAddress() > LIMIT_ADDRESS_DISPLAY)
|
||||
_buildButtonExpandAddress()
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildAddressWidget(String typeReceiver, String nameAddress) {
|
||||
if (_expandMode == ExpandMode.EXPAND
|
||||
|| (_presentationEmail != null && _presentationEmail!.numberOfAllEmailAddress() <= LIMIT_ADDRESS_DISPLAY)) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(typeReceiver, nameAddress));
|
||||
} else {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildCollapseAddressWidget(typeReceiver, nameAddress));
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildAddressToReceiverWidget() {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).to_email_address_prefix,
|
||||
_presentationEmail!.to.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
|
||||
Widget _buildAddressCcReceiverWidget() {
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).cc_email_address_prefix, _presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).cc_email_address_prefix,
|
||||
_presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildAddressBccReceiverWidget() {
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
if (_presentationEmail!.cc.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).bcc_email_address_prefix,
|
||||
_presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getRemainCountAddressReceiver() {
|
||||
if (_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY >= 999) {
|
||||
return '999';
|
||||
}
|
||||
return '${_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY}';
|
||||
}
|
||||
|
||||
Widget _buildButtonExpandAddress() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (_onOpenExpandAddressReceiverActionClick != null) {
|
||||
_onOpenExpandAddressReceiverActionClick!();
|
||||
}},
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'+${getRemainCountAddressReceiver()}',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500),
|
||||
),
|
||||
SvgPicture.asset(_imagePaths.icMoreReceiver, width: 14, height: 14, fit: BoxFit.fill),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user