TF-32 Add presentation layer of download attachment for android platform
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
package="com.linagora.android.tmail">
|
package="com.linagora.android.tmail">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
|
||||||
|
|
||||||
<!-- webviewflutter support minSdk version to at least 19 -->
|
<!-- webviewflutter support minSdk version to at least 19 -->
|
||||||
<!-- flutter_inappwebview support minSdk version to at least 17 -->
|
<!-- flutter_inappwebview support minSdk version to at least 17 -->
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="TMail"
|
android:label="@string/app_name"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@@ -48,6 +49,17 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
|
||||||
|
android:authorities="${applicationId}.flutter_downloader.provider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/provider_paths"/>
|
||||||
|
</provider>
|
||||||
|
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Team Mail</string>
|
||||||
|
<string name="flutter_downloader_notification_started">Started</string>
|
||||||
|
<string name="flutter_downloader_notification_in_progress">In Progress</string>
|
||||||
|
<string name="flutter_downloader_notification_canceled">Canceled</string>
|
||||||
|
<string name="flutter_downloader_notification_failed">Failed</string>
|
||||||
|
<string name="flutter_downloader_notification_complete">Completed</string>
|
||||||
|
<string name="flutter_downloader_notification_paused">Paused</string>
|
||||||
|
</resources>
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
|
import 'package:core/core.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
|
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
|
||||||
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
|
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
|
||||||
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
||||||
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
|
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_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/mark_as_email_read_interactor.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/login/data/repository/credential_repository_impl.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||||
|
|
||||||
class EmailBindings extends Bindings {
|
class EmailBindings extends Bindings {
|
||||||
@override
|
@override
|
||||||
@@ -20,5 +25,14 @@ class EmailBindings extends Bindings {
|
|||||||
Get.put(EmailController(
|
Get.put(EmailController(
|
||||||
Get.find<GetEmailContentInteractor>(),
|
Get.find<GetEmailContentInteractor>(),
|
||||||
Get.find<MarkAsEmailReadInteractor>()));
|
Get.find<MarkAsEmailReadInteractor>()));
|
||||||
|
Get.lazyPut(() => CredentialRepositoryImpl(Get.find<SharedPreferences>()));
|
||||||
|
Get.lazyPut<CredentialRepository>(() => Get.find<CredentialRepositoryImpl>());
|
||||||
|
Get.lazyPut(() => DownloadAttachmentsInteractor(
|
||||||
|
Get.find<EmailRepository>(),
|
||||||
|
Get.find<CredentialRepository>()));
|
||||||
|
Get.put(EmailController(
|
||||||
|
Get.find<GetEmailContentInteractor>(),
|
||||||
|
Get.find<DownloadAttachmentsInteractor>(),
|
||||||
|
Get.find<DeviceManager>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,21 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_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/get_email_content_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/mark_as_email_read_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/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/routes/app_routes.dart';
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
|
|
||||||
@@ -21,11 +26,18 @@ class EmailController extends BaseController {
|
|||||||
|
|
||||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||||
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
||||||
|
final DownloadAttachmentsInteractor _downloadAttachmentsInteractor;
|
||||||
|
final DeviceManager _deviceManager;
|
||||||
|
|
||||||
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
|
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
|
||||||
EmailContent? emailContent;
|
EmailContent? emailContent;
|
||||||
|
|
||||||
EmailController(this._getEmailContentInteractor, this._markAsEmailReadInteractor);
|
EmailController(this._getEmailContentInteractor, this._markAsEmailReadInteractor);
|
||||||
|
EmailController(
|
||||||
|
this._getEmailContentInteractor,
|
||||||
|
this._downloadAttachmentsInteractor,
|
||||||
|
this._deviceManager
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
@@ -102,6 +114,46 @@ class EmailController extends BaseController {
|
|||||||
backToThreadView();
|
backToThreadView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void downloadAttachments(BuildContext context, List<Attachment> attachments) async {
|
||||||
|
final needRequestPermission = await _deviceManager.isNeedRequestStoragePermissionOnAndroid();
|
||||||
|
|
||||||
|
if (Platform.isAndroid && needRequestPermission) {
|
||||||
|
final status = await Permission.storage.status;
|
||||||
|
switch (status) {
|
||||||
|
case PermissionStatus.granted:
|
||||||
|
_downloadAttachmentsAction(context, attachments);
|
||||||
|
break;
|
||||||
|
case PermissionStatus.permanentlyDenied:
|
||||||
|
_appToast.showToast(AppLocalizations.of(context).you_need_to_grant_files_permission_to_download_attachments);
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
final requested = await Permission.storage.request();
|
||||||
|
switch (requested) {
|
||||||
|
case PermissionStatus.granted:
|
||||||
|
_downloadAttachmentsAction(context, attachments);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_appToast.showToast(AppLocalizations.of(context).you_need_to_grant_files_permission_to_download_attachments);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_downloadAttachmentsAction(context, attachments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _downloadAttachmentsAction(BuildContext context, List<Attachment> attachments) async {
|
||||||
|
final accountId = mailboxDashBoardController.accountId.value;
|
||||||
|
if (accountId != null && mailboxDashBoardController.sessionCurrent != null) {
|
||||||
|
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent!.getDownloadUrl();
|
||||||
|
await _downloadAttachmentsInteractor.execute(attachments, accountId, baseDownloadUrl)
|
||||||
|
.then((result) => result.fold(
|
||||||
|
(failure) => AppLocalizations.of(context).attachment_download_failed,
|
||||||
|
(success) => AppLocalizations.of(context).attachment_download_successfully));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
||||||
&& mailboxDashBoardController.userProfile.value != null
|
&& mailboxDashBoardController.userProfile.value != null
|
||||||
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox)
|
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox)
|
||||||
|
|||||||
@@ -141,9 +141,8 @@ class EmailView extends GetWidget {
|
|||||||
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
|
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
|
||||||
.build()),
|
.build()),
|
||||||
_buildLoadingView(),
|
_buildLoadingView(),
|
||||||
SizedBox(height: 16),
|
|
||||||
_buildListAttachments(context),
|
|
||||||
_buildListMessageContent(),
|
_buildListMessageContent(),
|
||||||
|
_buildListAttachments(context),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -161,14 +160,18 @@ class EmailView extends GetWidget {
|
|||||||
key: Key('list_attachment'),
|
key: Key('list_attachment'),
|
||||||
primary: false,
|
primary: false,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: EdgeInsets.only(bottom: 16),
|
padding: EdgeInsets.only(top: 16),
|
||||||
itemCount: attachments.length,
|
itemCount: attachments.length,
|
||||||
gridDelegate: SliverGridDelegateFixedHeight(
|
gridDelegate: SliverGridDelegateFixedHeight(
|
||||||
height: 60,
|
height: 60,
|
||||||
crossAxisCount: responsiveUtils.isMobile(context) ? 2 : 4,
|
crossAxisCount: responsiveUtils.isMobile(context) ? 2 : 4,
|
||||||
crossAxisSpacing: 16.0,
|
crossAxisSpacing: 16.0,
|
||||||
mainAxisSpacing: 8.0),
|
mainAxisSpacing: 8.0),
|
||||||
itemBuilder: (context, index) => AttachmentFileTileBuilder(imagePaths, attachments[index]).build())
|
itemBuilder: (context, index) =>
|
||||||
|
(AttachmentFileTileBuilder(imagePaths, attachments[index])
|
||||||
|
..onDownloadAttachmentFileActionClick((attachment) =>
|
||||||
|
emailController.downloadAttachments(context, [attachment])))
|
||||||
|
.build())
|
||||||
: SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
} else {
|
} else {
|
||||||
return SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
@@ -191,6 +194,7 @@ class EmailView extends GetWidget {
|
|||||||
? ListView.builder(
|
? ListView.builder(
|
||||||
primary: false,
|
primary: false,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
padding: EdgeInsets.only(top: 16),
|
||||||
key: Key('list_message_content'),
|
key: Key('list_message_content'),
|
||||||
itemCount: messageContents.length,
|
itemCount: messageContents.length,
|
||||||
itemBuilder: (context, index) =>
|
itemBuilder: (context, index) =>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart';
|
import 'package:model/model.dart';
|
||||||
|
|
||||||
extension EmailBodyPartExtension on EmailBodyPart {
|
extension EmailBodyPartExtension on EmailBodyPart {
|
||||||
AttachmentFile toAttachmentFile() => AttachmentFile(partId, blobId, size, name, type, cid);
|
Attachment toAttachment() => Attachment(partId, blobId, size, name, type, cid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
||||||
import 'package:model/email/email_content.dart';
|
import 'package:model/email/email_content.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/model/attachment_file.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/message_content.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/email_body_part_extension.dart';
|
import 'package:tmail_ui_user/features/email/presentation/extensions/email_body_part_extension.dart';
|
||||||
@@ -27,21 +27,21 @@ extension EmailContentExtension on EmailContent {
|
|||||||
return listMessageContent;
|
return listMessageContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AttachmentFile> getListAttachment() {
|
List<Attachment> getListAttachment() {
|
||||||
if (attachments != null) {
|
if (attachments != null) {
|
||||||
return attachments!
|
return attachments!
|
||||||
.where((element) => (element.disposition != null && element.disposition != 'inline'))
|
.where((element) => (element.disposition != null && element.disposition != 'inline'))
|
||||||
.map((item) => item.toAttachmentFile())
|
.map((item) => item.toAttachment())
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AttachmentFile> getListAttachmentInline() {
|
List<Attachment> getListAttachmentInline() {
|
||||||
if (attachments != null) {
|
if (attachments != null) {
|
||||||
return attachments!
|
return attachments!
|
||||||
.where((element) => element.disposition == 'inline')
|
.where((element) => element.disposition == 'inline')
|
||||||
.map((item) => item.toAttachmentFile())
|
.map((item) => item.toAttachment())
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:http_parser/http_parser.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
|
||||||
|
|
||||||
class AttachmentFile with EquatableMixin {
|
|
||||||
|
|
||||||
final PartId? partId;
|
|
||||||
final Id? blobId;
|
|
||||||
final UnsignedInt? size;
|
|
||||||
final String? name;
|
|
||||||
final MediaType? type;
|
|
||||||
final String? cid;
|
|
||||||
|
|
||||||
AttachmentFile(
|
|
||||||
this.partId,
|
|
||||||
this.blobId,
|
|
||||||
this.size,
|
|
||||||
this.name,
|
|
||||||
this.type,
|
|
||||||
this.cid
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [partId, blobId, size, name, type, cid];
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
|
|
||||||
@@ -15,16 +13,11 @@ class MessageContent with EquatableMixin {
|
|||||||
|
|
||||||
bool hasImageInlineWithCid() => content.contains('cid:');
|
bool hasImageInlineWithCid() => content.contains('cid:');
|
||||||
|
|
||||||
String getContentHasInlineAttachment(Session session, AccountId accountId, List<AttachmentFile> attachmentFiles) {
|
String getContentHasInlineAttachment(String baseDownloadUrl, AccountId accountId, List<Attachment> attachments) {
|
||||||
var contentValid = content;
|
var contentValid = content;
|
||||||
attachmentFiles.forEach((attachment) {
|
attachments.forEach((attachment) {
|
||||||
if(attachment.cid != null) {
|
if(attachment.cid != null) {
|
||||||
final urlDownloadImage = session.getDownloadUrl(
|
final urlDownloadImage = attachment.getDownloadUrl(baseDownloadUrl, accountId);
|
||||||
'${accountId.id.value}',
|
|
||||||
'${attachment.blobId?.value}',
|
|
||||||
'${attachment.name}',
|
|
||||||
'${attachment.type?.mimeType}');
|
|
||||||
|
|
||||||
contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage');
|
contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,23 +4,21 @@ import 'package:filesize/filesize.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart';
|
import 'package:model/model.dart';
|
||||||
|
|
||||||
typedef OnOpenAttachmentFileActionClick = void Function();
|
typedef OnDownloadAttachmentFileActionClick = void Function(Attachment attachment);
|
||||||
|
|
||||||
class AttachmentFileTileBuilder {
|
class AttachmentFileTileBuilder {
|
||||||
|
|
||||||
final ImagePaths _imagePaths;
|
final ImagePaths _imagePaths;
|
||||||
final AttachmentFile _attachmentFile;
|
final Attachment _attachment;
|
||||||
|
|
||||||
OnOpenAttachmentFileActionClick? _onOpenAttachmentFileActionClick;
|
OnDownloadAttachmentFileActionClick? _onDownloadAttachmentFileActionClick;
|
||||||
|
|
||||||
AttachmentFileTileBuilder(this._imagePaths, this._attachmentFile);
|
AttachmentFileTileBuilder(this._imagePaths, this._attachment);
|
||||||
|
|
||||||
AttachmentFileTileBuilder onOpenAttachmentFileActionClick(
|
void onDownloadAttachmentFileActionClick(OnDownloadAttachmentFileActionClick onDownloadAttachmentFileActionClick) {
|
||||||
OnOpenAttachmentFileActionClick onOpenAttachmentFileActionClick) {
|
_onDownloadAttachmentFileActionClick = onDownloadAttachmentFileActionClick;
|
||||||
_onOpenAttachmentFileActionClick = onOpenAttachmentFileActionClick;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget build() {
|
Widget build() {
|
||||||
@@ -38,26 +36,29 @@ class AttachmentFileTileBuilder {
|
|||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
focusColor: AppColor.primaryColor,
|
||||||
|
hoverColor: AppColor.primaryColor,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (_onOpenAttachmentFileActionClick != null) {
|
if (_onDownloadAttachmentFileActionClick != null) {
|
||||||
_onOpenAttachmentFileActionClick!();
|
_onDownloadAttachmentFileActionClick!(_attachment);
|
||||||
}},
|
}},
|
||||||
leading: Transform(
|
leading: Transform(
|
||||||
transform: Matrix4.translationValues(0.0, 2.0, 0.0),
|
transform: Matrix4.translationValues(14.0, 2.0, 0.0),
|
||||||
child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)),
|
child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)),
|
||||||
title: Transform(
|
title: Transform(
|
||||||
transform: Matrix4.translationValues(-18.0, -8.0, 0.0),
|
transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
_attachmentFile.name ?? '',
|
_attachment.name ?? '',
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileNameColor, fontWeight: FontWeight.w500),
|
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileNameColor, fontWeight: FontWeight.w500),
|
||||||
)),
|
)),
|
||||||
subtitle: _attachmentFile.size != null && _attachmentFile.size?.value != 0
|
subtitle: _attachment.size != null && _attachment.size?.value != 0
|
||||||
? Transform(
|
? Transform(
|
||||||
transform: Matrix4.translationValues(-18.0, -8.0, 0.0),
|
transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
filesize(_attachmentFile.size?.value),
|
filesize(_attachment.size?.value),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileSizeColor)))
|
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileSizeColor)))
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.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/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.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/message_content.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
|
||||||
|
|
||||||
class MessageContentTileBuilder {
|
class MessageContentTileBuilder {
|
||||||
|
|
||||||
final MessageContent messageContent;
|
final MessageContent messageContent;
|
||||||
final List<AttachmentFile> attachmentInlines;
|
final List<Attachment> attachmentInlines;
|
||||||
final Session? session;
|
final Session? session;
|
||||||
final AccountId? accountId;
|
final AccountId? accountId;
|
||||||
final HtmlMessagePurifier htmlMessagePurifier;
|
final HtmlMessagePurifier htmlMessagePurifier;
|
||||||
@@ -51,7 +51,7 @@ class MessageContentTileBuilder {
|
|||||||
|
|
||||||
String getHtmlMessageText() {
|
String getHtmlMessageText() {
|
||||||
final message = (attachmentInlines.isNotEmpty && session != null && accountId != null && messageContent.hasImageInlineWithCid())
|
final message = (attachmentInlines.isNotEmpty && session != null && accountId != null && messageContent.hasImageInlineWithCid())
|
||||||
? '${messageContent.getContentHasInlineAttachment(session!, accountId!, attachmentInlines)}'
|
? '${messageContent.getContentHasInlineAttachment(session!.getDownloadUrl(), accountId!, attachmentInlines)}'
|
||||||
: '${messageContent.content}';
|
: '${messageContent.content}';
|
||||||
|
|
||||||
final trustAsHtml = htmlMessagePurifier.purifyHtmlMessage(
|
final trustAsHtml = htmlMessagePurifier.purifyHtmlMessage(
|
||||||
|
|||||||
@@ -269,5 +269,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_failed": "Attachment download failed",
|
||||||
|
"@attachment_download_failed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_successfully": "Attachment downloaded successfully",
|
||||||
|
"@attachment_download_successfully": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,5 +269,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_failed": "Attachment download failed",
|
||||||
|
"@attachment_download_failed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_successfully": "Attachment downloaded successfully",
|
||||||
|
"@attachment_download_successfully": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-09-15T13:25:41.117609",
|
"@@last_modified": "2021-09-15T23:44:29.035668",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -269,5 +269,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_failed": "Attachment download failed",
|
||||||
|
"@attachment_download_failed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_successfully": "Attachment downloaded successfully",
|
||||||
|
"@attachment_download_successfully": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,5 +269,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_failed": "Attachment download failed",
|
||||||
|
"@attachment_download_failed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_successfully": "Attachment downloaded successfully",
|
||||||
|
"@attachment_download_successfully": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,5 +269,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_failed": "Attachment download failed",
|
||||||
|
"@attachment_download_failed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"attachment_download_successfully": "Attachment downloaded successfully",
|
||||||
|
"@attachment_download_successfully": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:core/presentation/utils/app_toast.dart';
|
import 'package:core/presentation/utils/app_toast.dart';
|
||||||
|
import 'package:device_info/device_info.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ class CoreBindings extends Bindings {
|
|||||||
_bindingKeyboardManager();
|
_bindingKeyboardManager();
|
||||||
_bindingValidator();
|
_bindingValidator();
|
||||||
_bindingToast();
|
_bindingToast();
|
||||||
|
_bindingDeviceManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bindingAppImagePaths() {
|
void _bindingAppImagePaths() {
|
||||||
@@ -38,4 +40,9 @@ class CoreBindings extends Bindings {
|
|||||||
void _bindingToast() {
|
void _bindingToast() {
|
||||||
Get.put(AppToast());
|
Get.put(AppToast());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _bindingDeviceManager() {
|
||||||
|
Get.put(DeviceInfoPlugin());
|
||||||
|
Get.put(DeviceManager(Get.find<DeviceInfoPlugin>()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -300,5 +300,19 @@ class AppLocalizations {
|
|||||||
name: 'an_error_occurred',
|
name: 'an_error_occurred',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get attachment_download_failed {
|
||||||
|
return Intl.message(
|
||||||
|
'Attachment download failed',
|
||||||
|
name: 'attachment_download_failed',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get attachment_download_successfully {
|
||||||
|
return Intl.message(
|
||||||
|
'Attachment downloaded successfully',
|
||||||
|
name: 'attachment_download_successfully',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user