diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index ff2873629..ec63a3110 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
package="com.linagora.android.tmail">
+
@@ -17,7 +18,7 @@
+
+
+
+
+
+ Team Mail
+ Started
+ In Progress
+ Canceled
+ Failed
+ Completed
+ Paused
+
\ No newline at end of file
diff --git a/lib/features/email/presentation/email_bindings.dart b/lib/features/email/presentation/email_bindings.dart
index 574067c74..6b156840c 100644
--- a/lib/features/email/presentation/email_bindings.dart
+++ b/lib/features/email/presentation/email_bindings.dart
@@ -1,12 +1,17 @@
+import 'package:core/core.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_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/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/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/mark_as_email_read_interactor.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 {
@override
@@ -20,5 +25,14 @@ class EmailBindings extends Bindings {
Get.put(EmailController(
Get.find(),
Get.find()));
+ Get.lazyPut(() => CredentialRepositoryImpl(Get.find()));
+ Get.lazyPut(() => Get.find());
+ Get.lazyPut(() => DownloadAttachmentsInteractor(
+ Get.find(),
+ Get.find()));
+ Get.put(EmailController(
+ Get.find(),
+ Get.find(),
+ Get.find()));
}
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/email_controller.dart b/lib/features/email/presentation/email_controller.dart
index 8218e602c..d4bf7a3d0 100644
--- a/lib/features/email/presentation/email_controller.dart
+++ b/lib/features/email/presentation/email_controller.dart
@@ -1,16 +1,21 @@
+import 'dart:io';
+
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.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/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/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/presentation/model/composer_arguments.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/route_navigation.dart';
@@ -21,11 +26,18 @@ class EmailController extends BaseController {
final GetEmailContentInteractor _getEmailContentInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
+ final DownloadAttachmentsInteractor _downloadAttachmentsInteractor;
+ final DeviceManager _deviceManager;
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
EmailContent? emailContent;
EmailController(this._getEmailContentInteractor, this._markAsEmailReadInteractor);
+ EmailController(
+ this._getEmailContentInteractor,
+ this._downloadAttachmentsInteractor,
+ this._deviceManager
+ );
@override
void onReady() {
@@ -102,6 +114,46 @@ class EmailController extends BaseController {
backToThreadView();
}
+ void downloadAttachments(BuildContext context, List 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 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
&& mailboxDashBoardController.userProfile.value != null
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox)
diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart
index 0b0fce7e8..63b87603e 100644
--- a/lib/features/email/presentation/email_view.dart
+++ b/lib/features/email/presentation/email_view.dart
@@ -141,9 +141,8 @@ class EmailView extends GetWidget {
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
.build()),
_buildLoadingView(),
- SizedBox(height: 16),
- _buildListAttachments(context),
_buildListMessageContent(),
+ _buildListAttachments(context),
],
)
);
@@ -161,14 +160,18 @@ class EmailView extends GetWidget {
key: Key('list_attachment'),
primary: false,
shrinkWrap: true,
- padding: EdgeInsets.only(bottom: 16),
+ padding: EdgeInsets.only(top: 16),
itemCount: attachments.length,
gridDelegate: SliverGridDelegateFixedHeight(
height: 60,
crossAxisCount: responsiveUtils.isMobile(context) ? 2 : 4,
crossAxisSpacing: 16.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();
} else {
return SizedBox.shrink();
@@ -191,6 +194,7 @@ class EmailView extends GetWidget {
? ListView.builder(
primary: false,
shrinkWrap: true,
+ padding: EdgeInsets.only(top: 16),
key: Key('list_message_content'),
itemCount: messageContents.length,
itemBuilder: (context, index) =>
diff --git a/lib/features/email/presentation/extensions/email_body_part_extension.dart b/lib/features/email/presentation/extensions/email_body_part_extension.dart
index 591ad61a5..0adda96d1 100644
--- a/lib/features/email/presentation/extensions/email_body_part_extension.dart
+++ b/lib/features/email/presentation/extensions/email_body_part_extension.dart
@@ -1,6 +1,6 @@
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 {
- AttachmentFile toAttachmentFile() => AttachmentFile(partId, blobId, size, name, type, cid);
+ Attachment toAttachment() => Attachment(partId, blobId, size, name, type, cid);
}
diff --git a/lib/features/email/presentation/extensions/email_content_extension.dart b/lib/features/email/presentation/extensions/email_content_extension.dart
index c60e55a80..68214dd02 100644
--- a/lib/features/email/presentation/extensions/email_content_extension.dart
+++ b/lib/features/email/presentation/extensions/email_content_extension.dart
@@ -1,7 +1,7 @@
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.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/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/text_format.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;
}
- List getListAttachment() {
+ List getListAttachment() {
if (attachments != null) {
return attachments!
.where((element) => (element.disposition != null && element.disposition != 'inline'))
- .map((item) => item.toAttachmentFile())
+ .map((item) => item.toAttachment())
.toList();
}
return [];
}
- List getListAttachmentInline() {
+ List getListAttachmentInline() {
if (attachments != null) {
return attachments!
.where((element) => element.disposition == 'inline')
- .map((item) => item.toAttachmentFile())
+ .map((item) => item.toAttachment())
.toList();
}
return [];
diff --git a/lib/features/email/presentation/model/attachment_file.dart b/lib/features/email/presentation/model/attachment_file.dart
deleted file mode 100644
index c394da3ed..000000000
--- a/lib/features/email/presentation/model/attachment_file.dart
+++ /dev/null
@@ -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