Skip to content

Commit 7342bbc

Browse files
dab246hoangdat
authored andcommitted
TF-3601 View entire message on dialog
Signed-off-by: dab246 <[email protected]>
1 parent 1c97c8a commit 7342bbc

19 files changed

+273
-1
lines changed

lib/features/composer/presentation/composer_bindings.dart

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class ComposerBindings extends BaseBindings {
136136
), tag: composerId);
137137
Get.lazyPut(() => EmailLocalStorageDataSourceImpl(
138138
Get.find<LocalStorageManager>(),
139+
Get.find<PreviewEmlFileUtils>(),
139140
Get.find<CacheExceptionThrower>(),
140141
), tag: composerId);
141142
Get.lazyPut(() => EmailSessionStorageDatasourceImpl(

lib/features/email/data/datasource/email_datasource.dart

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
2626
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
2727
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
2828
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
29+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
2930
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
3031
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
3132
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
@@ -221,4 +222,6 @@ abstract class EmailDataSource {
221222
AccountRequest accountRequest,
222223
{CancelToken? cancelToken}
223224
);
225+
226+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest);
224227
}

lib/features/email/data/datasource_impl/email_datasource_impl.dart

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
3636
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3737
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3838
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
39+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
3940
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
4041
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
4142
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
@@ -582,4 +583,9 @@ class EmailDataSourceImpl extends EmailDataSource {
582583
cancelToken: cancelToken,
583584
);
584585
}).catchError(_exceptionThrower.throwException);
586+
587+
@override
588+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
589+
throw UnimplementedError();
590+
}
585591
}

lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
3636
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3737
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3838
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
39+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
3940
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
4041
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
4142
import 'package:tmail_ui_user/features/offline_mode/extensions/list_sending_email_hive_cache_extension.dart';
@@ -582,4 +583,9 @@ class EmailHiveCacheDataSourceImpl extends EmailDataSource {
582583
Future<DownloadedResponse> exportAllAttachments(AccountId accountId, EmailId emailId, String baseDownloadAllUrl, String outputFileName, AccountRequest accountRequest, {CancelToken? cancelToken}) {
583584
throw UnimplementedError();
584585
}
586+
587+
@override
588+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
589+
throw UnimplementedError();
590+
}
585591
}

lib/features/email/data/datasource_impl/email_local_storage_datasource_impl.dart

+88
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@ import 'dart:async';
33
import 'dart:convert';
44
import 'dart:typed_data';
55

6+
import 'package:core/data/model/preview_attachment.dart';
67
import 'package:core/data/network/download/downloaded_response.dart';
8+
import 'package:core/domain/extensions/datetime_extension.dart';
9+
import 'package:core/presentation/extensions/html_extension.dart';
10+
import 'package:core/presentation/resources/image_paths.dart';
711
import 'package:core/presentation/state/failure.dart';
812
import 'package:core/presentation/state/success.dart';
13+
import 'package:core/utils/file_utils.dart';
14+
import 'package:core/utils/preview_eml_file_utils.dart';
915
import 'package:dartz/dartz.dart';
1016
import 'package:dio/dio.dart';
1117
import 'package:email_recovery/email_recovery/email_recovery_action.dart';
1218
import 'package:email_recovery/email_recovery/email_recovery_action_id.dart';
19+
import 'package:filesize/filesize.dart';
20+
import 'package:get/get.dart';
1321
import 'package:jmap_dart_client/jmap/account_id.dart';
1422
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
1523
import 'package:jmap_dart_client/jmap/core/id.dart';
@@ -22,6 +30,8 @@ import 'package:model/download/download_task_id.dart';
2230
import 'package:model/email/attachment.dart';
2331
import 'package:model/email/mark_star_action.dart';
2432
import 'package:model/email/read_actions.dart';
33+
import 'package:model/extensions/list_email_address_extension.dart';
34+
import 'package:model/extensions/presentation_email_extension.dart';
2535
import 'package:tmail_ui_user/features/caching/utils/local_storage_manager.dart';
2636
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
2737
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
@@ -30,6 +40,8 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
3040
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3141
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3242
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
43+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
44+
import 'package:tmail_ui_user/features/email/presentation/extensions/attachment_extension.dart';
3345
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
3446
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
3547
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
@@ -38,10 +50,14 @@ import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
3850
class EmailLocalStorageDataSourceImpl extends EmailDataSource {
3951

4052
final LocalStorageManager _localStorageManager;
53+
final PreviewEmlFileUtils _previewEmlFileUtils;
4154
final ExceptionThrower _exceptionThrower;
55+
final ImagePaths _imagePaths = Get.find<ImagePaths>();
56+
final FileUtils _fileUtils = Get.find<FileUtils>();
4257

4358
EmailLocalStorageDataSourceImpl(
4459
this._localStorageManager,
60+
this._previewEmlFileUtils,
4561
this._exceptionThrower,
4662
);
4763

@@ -273,4 +289,76 @@ class EmailLocalStorageDataSourceImpl extends EmailDataSource {
273289
Future<DownloadedResponse> exportAllAttachments(AccountId accountId, EmailId emailId, String baseDownloadAllUrl, String outputFileName, AccountRequest accountRequest, {CancelToken? cancelToken}) {
274290
throw UnimplementedError();
275291
}
292+
293+
@override
294+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
295+
return Future.sync(() async {
296+
final email = entireMessageRequest.presentationEmail;
297+
final appLocalizations = entireMessageRequest.appLocalizations;
298+
final locale = entireMessageRequest.locale.toLanguageTag();
299+
final listAttachments = entireMessageRequest.attachments;
300+
final emailContentEscaped = entireMessageRequest.emailContent;
301+
302+
final sender = email.from?.isNotEmpty == true
303+
? email.from!.first
304+
: null;
305+
306+
final receiveTime = email.getReceivedAt(
307+
locale,
308+
pattern: email.receivedAt?.value.toLocal().toPatternForPrinting(locale)
309+
);
310+
311+
final sentTime = email.getSentAt(
312+
locale,
313+
pattern: email.sentAt?.value.toLocal().toPatternForPrinting(locale)
314+
);
315+
316+
final List<PreviewAttachment> listPreviewAttachment = [];
317+
318+
if (listAttachments.isNotEmpty) {
319+
await Future.forEach<Attachment>(listAttachments, (attachment) async {
320+
final iconBase64Data = await _fileUtils.convertImageAssetToBase64(
321+
attachment.getIcon(_imagePaths));
322+
323+
final previewAttachment = PreviewAttachment(
324+
iconBase64Data: iconBase64Data,
325+
name: attachment.name.escapeLtGtHtmlString(),
326+
size: filesize(attachment.size?.value),
327+
link: attachment.hyperLink,
328+
);
329+
330+
listPreviewAttachment.add(previewAttachment);
331+
});
332+
}
333+
334+
final attachmentIconBase64Data = email.hasAttachment == true
335+
? await _fileUtils.convertImageAssetToBase64(_imagePaths.icAttachment)
336+
: '';
337+
338+
final htmlDocument = _previewEmlFileUtils.generatePreviewEml(
339+
appName: appLocalizations.app_name,
340+
userName: entireMessageRequest.userName.value,
341+
subjectPrefix: appLocalizations.subject,
342+
subject: email.subject?.escapeLtGtHtmlString() ?? '',
343+
emailContent: emailContentEscaped,
344+
senderName: sender?.name.escapeLtGtHtmlString() ?? '',
345+
senderEmailAddress: sender?.email ?? '',
346+
dateTime: receiveTime.isNotEmpty ? receiveTime : sentTime,
347+
fromPrefix: appLocalizations.from_email_address_prefix,
348+
toPrefix: appLocalizations.to_email_address_prefix,
349+
ccPrefix: appLocalizations.cc_email_address_prefix,
350+
bccPrefix: appLocalizations.bcc_email_address_prefix,
351+
replyToPrefix: appLocalizations.replyToEmailAddressPrefix,
352+
titleAttachment: appLocalizations.attachments.toLowerCase(),
353+
attachmentIcon: attachmentIconBase64Data,
354+
toAddress: email.to?.listEmailAddressToString(isFullEmailAddress: true),
355+
ccAddress: email.cc?.listEmailAddressToString(isFullEmailAddress: true),
356+
bccAddress: email.bcc?.listEmailAddressToString(isFullEmailAddress: true),
357+
replyToAddress: email.replyTo?.listEmailAddressToString(isFullEmailAddress: true),
358+
listAttachment: listPreviewAttachment,
359+
);
360+
361+
return htmlDocument;
362+
}).catchError(_exceptionThrower.throwException);
363+
}
276364
}

lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
3030
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3131
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3232
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
33+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
3334
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
3435
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
3536
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
@@ -271,4 +272,9 @@ class EmailSessionStorageDatasourceImpl extends EmailDataSource {
271272
Future<DownloadedResponse> exportAllAttachments(AccountId accountId, EmailId emailId, String baseDownloadAllUrl, String outputFileName, AccountRequest accountRequest, {CancelToken? cancelToken}) {
272273
throw UnimplementedError();
273274
}
275+
276+
@override
277+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
278+
throw UnimplementedError();
279+
}
274280
}

lib/features/email/data/repository/email_repository_impl.dart

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
3434
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3535
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3636
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
37+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
3738
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
3839
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
3940
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
@@ -567,4 +568,9 @@ class EmailRepositoryImpl extends EmailRepository {
567568
outputFileName,
568569
accountRequest,
569570
);
571+
572+
@override
573+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest) {
574+
return emailDataSource[DataSourceType.local]!.generateEntireMessageAsDocument(entireMessageRequest);
575+
}
570576
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'package:equatable/equatable.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:jmap_dart_client/jmap/core/user_name.dart';
4+
import 'package:model/email/attachment.dart';
5+
import 'package:model/email/presentation_email.dart';
6+
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
7+
8+
class ViewEntireMessageRequest with EquatableMixin {
9+
final UserName userName;
10+
final PresentationEmail presentationEmail;
11+
final List<Attachment> attachments;
12+
final String emailContent;
13+
final Locale locale;
14+
final AppLocalizations appLocalizations;
15+
16+
ViewEntireMessageRequest({
17+
required this.userName,
18+
required this.presentationEmail,
19+
required this.attachments,
20+
required this.emailContent,
21+
required this.locale,
22+
required this.appLocalizations,
23+
});
24+
25+
@override
26+
List<Object?> get props => [
27+
userName,
28+
presentationEmail,
29+
attachments,
30+
emailContent,
31+
locale,
32+
appLocalizations,
33+
];
34+
}

lib/features/email/domain/repository/email_repository.dart

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
2929
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
3030
import 'package:tmail_ui_user/features/email/domain/model/preview_email_eml_request.dart';
3131
import 'package:tmail_ui_user/features/email/domain/model/restore_deleted_message_request.dart';
32+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
3233
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
3334
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
3435

@@ -219,4 +220,6 @@ abstract class EmailRepository {
219220
AccountRequest accountRequest,
220221
{CancelToken? cancelToken}
221222
);
223+
224+
Future<String> generateEntireMessageAsDocument(ViewEntireMessageRequest entireMessageRequest);
222225
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'package:core/presentation/state/failure.dart';
2+
import 'package:core/presentation/state/success.dart';
3+
4+
class GettingEntireMessageAsDocument extends LoadingState {}
5+
6+
class GetEntireMessageAsDocumentSuccess extends UIState {
7+
final String messageDocument;
8+
9+
GetEntireMessageAsDocumentSuccess(this.messageDocument);
10+
11+
@override
12+
List<Object?> get props => [messageDocument];
13+
}
14+
15+
class GetEntireMessageAsDocumentFailure extends FeatureFailure {
16+
17+
GetEntireMessageAsDocumentFailure({dynamic exception}) : super(exception: exception);
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'package:core/presentation/state/failure.dart';
2+
import 'package:core/presentation/state/success.dart';
3+
import 'package:dartz/dartz.dart';
4+
import 'package:tmail_ui_user/features/email/domain/model/view_entire_message_request.dart';
5+
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
6+
import 'package:tmail_ui_user/features/email/domain/state/get_entire_message_as_document_state.dart';
7+
8+
class GetEntireMessageAsDocumentInteractor {
9+
final EmailRepository _emailRepository;
10+
11+
GetEntireMessageAsDocumentInteractor(this._emailRepository);
12+
13+
Stream<Either<Failure, Success>> execute(ViewEntireMessageRequest messageRequest) async* {
14+
try {
15+
yield Right(GettingEntireMessageAsDocument());
16+
final messageDocument = await _emailRepository.generateEntireMessageAsDocument(messageRequest);
17+
yield Right(GetEntireMessageAsDocumentSuccess(messageDocument));
18+
} catch (e) {
19+
yield Left(GetEntireMessageAsDocumentFailure(exception: e));
20+
}
21+
}
22+
}

lib/features/email/presentation/bindings/email_bindings.dart

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment
2222
import 'package:tmail_ui_user/features/email/domain/usecases/export_all_attachments_interactor.dart';
2323
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
2424
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
25+
import 'package:tmail_ui_user/features/email/domain/usecases/get_entire_message_as_document_interactor.dart';
2526
import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart';
2627
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
2728
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
@@ -134,6 +135,7 @@ class EmailBindings extends BaseBindings {
134135
Get.find<CacheExceptionThrower>()));
135136
Get.lazyPut(() => EmailLocalStorageDataSourceImpl(
136137
Get.find<LocalStorageManager>(),
138+
Get.find<PreviewEmlFileUtils>(),
137139
Get.find<CacheExceptionThrower>()));
138140
Get.lazyPut(() => EmailSessionStorageDatasourceImpl(
139141
Get.find<SessionStorageManager>(),
@@ -182,6 +184,11 @@ class EmailBindings extends BaseBindings {
182184
Get.find<AccountRepository>(),
183185
Get.find<AuthenticationOIDCRepository>(),
184186
Get.find<CredentialRepository>()));
187+
if (PlatformInfo.isIOS) {
188+
Get.lazyPut(() => GetEntireMessageAsDocumentInteractor(
189+
Get.find<EmailRepository>(),
190+
));
191+
}
185192
}
186193

187194
@override

0 commit comments

Comments
 (0)