TF-2628 Integrate ViewAttachmentForWebInteractor with SingleEmailController
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
class Constant {
|
||||
static const acceptHeaderDefault = 'application/json';
|
||||
static const contentTypeHeaderDefault = 'application/json';
|
||||
static const pdfMimeType = 'application/pdf';
|
||||
}
|
||||
@@ -19,6 +19,7 @@ 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/mdn/disposition.dart';
|
||||
import 'package:jmap_dart_client/jmap/mdn/mdn.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
@@ -44,6 +45,7 @@ import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.
|
||||
import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/send_receipt_to_sender_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/view_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_interactor.dart';
|
||||
@@ -54,6 +56,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_int
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/send_receipt_to_sender_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/view_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/bindings/calendar_event_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart';
|
||||
@@ -107,6 +110,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
|
||||
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
|
||||
final StoreOpenedEmailInteractor _storeOpenedEmailInteractor;
|
||||
final ViewAttachmentForWebInteractor _viewAttachmentForWebInteractor;
|
||||
|
||||
CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
|
||||
SendReceiptToSenderInteractor? _sendReceiptToSenderInteractor;
|
||||
@@ -141,7 +145,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
this._markAsStarEmailInteractor,
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
this._getAllIdentitiesInteractor,
|
||||
this._storeOpenedEmailInteractor
|
||||
this._storeOpenedEmailInteractor,
|
||||
this._viewAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -174,6 +179,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_moveToMailboxSuccess(success);
|
||||
} else if (success is MarkAsStarEmailSuccess) {
|
||||
_markAsEmailStarSuccess(success);
|
||||
} else if (success is ViewAttachmentForWebSuccess) {
|
||||
_viewAttachmentForWebSuccessAction(success);
|
||||
} else if (success is DownloadAttachmentForWebSuccess) {
|
||||
_downloadAttachmentForWebSuccessAction(success);
|
||||
} else if (success is GetAllIdentitiesSuccess) {
|
||||
@@ -198,6 +205,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_downloadAttachmentsFailure(failure);
|
||||
} else if (failure is ExportAttachmentFailure) {
|
||||
_exportAttachmentFailureAction(failure);
|
||||
} else if (failure is ViewAttachmentForWebFailure) {
|
||||
_viewAttachmentForWebFailureAction(failure);
|
||||
} else if (failure is DownloadAttachmentForWebFailure) {
|
||||
_downloadAttachmentForWebFailureAction(failure);
|
||||
} else if (failure is ParseCalendarEventFailure) {
|
||||
@@ -721,11 +730,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void downloadAttachmentForWeb(BuildContext context, Attachment attachment) {
|
||||
_downloadAttachmentForWebAction(context, attachment);
|
||||
}
|
||||
|
||||
void _downloadAttachmentForWebAction(BuildContext context, Attachment attachment) async {
|
||||
void downloadAttachmentForWeb(Attachment attachment) {
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
if (accountId != null && session != null) {
|
||||
@@ -744,6 +749,25 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void viewAttachmentForWeb(Attachment attachment) {
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
if (accountId != null && session != null) {
|
||||
final baseDownloadUrl = session.getDownloadUrl(jmapUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
final generateTaskId = DownloadTaskId(uuid.v4());
|
||||
consumeState(_viewAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
attachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
_downloadProgressStateController));
|
||||
} else {
|
||||
consumeState(Stream.value(
|
||||
Left(ViewAttachmentForWebFailure(exception: NotFoundSessionException()))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _downloadAttachmentForWebSuccessAction(DownloadAttachmentForWebSuccess success) {
|
||||
log('SingleEmailController::_downloadAttachmentForWebSuccessAction():');
|
||||
mailboxDashBoardController.deleteDownloadTask(success.taskId);
|
||||
@@ -753,6 +777,24 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
success.attachment.generateFileName());
|
||||
}
|
||||
|
||||
void _viewAttachmentForWebSuccessAction(
|
||||
ViewAttachmentForWebSuccess success,
|
||||
) {
|
||||
log('SingleEmailController::_viewAttachmentForWebSuccessAction():');
|
||||
final mimeType = success.attachment.type?.mimeType ??
|
||||
lookupMimeType('', headerBytes: success.bytes);
|
||||
if (mimeType != Constant.pdfMimeType) {
|
||||
_downloadAttachmentForWebSuccessAction(success);
|
||||
return;
|
||||
}
|
||||
|
||||
mailboxDashBoardController.deleteDownloadTask(success.taskId);
|
||||
|
||||
_downloadManager.openDownloadedFileWeb(
|
||||
success.bytes,
|
||||
success.attachment.type?.mimeType);
|
||||
}
|
||||
|
||||
void _downloadAttachmentForWebFailureAction(DownloadAttachmentForWebFailure failure) {
|
||||
log('SingleEmailController::_downloadAttachmentForWebFailureAction(): $failure');
|
||||
if (failure.taskId != null) {
|
||||
@@ -766,6 +808,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void _viewAttachmentForWebFailureAction(ViewAttachmentForWebFailure failure) {
|
||||
log('SingleEmailController::_viewAttachmentForWebFailureAction(): $failure');
|
||||
_downloadAttachmentForWebFailureAction(failure);
|
||||
}
|
||||
|
||||
void moveToMailbox(BuildContext context, PresentationEmail email) async {
|
||||
final currentMailbox = getMailboxContain(email);
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
@@ -1384,7 +1431,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
..onCloseButtonAction(() => popBack())
|
||||
..onDownloadAttachmentFileAction((attachment) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
downloadAttachmentForWeb(context, attachment);
|
||||
downloadAttachmentForWeb(attachment);
|
||||
} else {
|
||||
exportAttachment(context, attachment);
|
||||
}
|
||||
@@ -1402,7 +1449,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
onCloseButtonAction: () => popBack(),
|
||||
onDownloadAttachmentFileAction: (attachment) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
downloadAttachmentForWeb(context, attachment);
|
||||
downloadAttachmentForWeb(attachment);
|
||||
} else {
|
||||
exportAttachment(context, attachment);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1192,7 +1192,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mime
|
||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||
|
||||
@@ -229,6 +229,8 @@ dependencies:
|
||||
|
||||
flutter_secure_storage: 8.0.0
|
||||
|
||||
mime: 1.0.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart' hide State;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_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/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/view_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/export_attachment_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_star_email_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/store_opened_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/view_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
|
||||
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import 'single_email_controller_test.mocks.dart';
|
||||
|
||||
mockControllerCallback() => InternalFinalCallback<void>(callback: () {});
|
||||
const fallbackGenerators = {
|
||||
#onStart: mockControllerCallback,
|
||||
#onDelete: mockControllerCallback,
|
||||
};
|
||||
|
||||
@GenerateNiceMocks([
|
||||
MockSpec<GetEmailContentInteractor>(),
|
||||
MockSpec<MarkAsEmailReadInteractor>(),
|
||||
MockSpec<DownloadAttachmentsInteractor>(),
|
||||
MockSpec<DeviceManager>(),
|
||||
MockSpec<ExportAttachmentInteractor>(),
|
||||
MockSpec<MoveToMailboxInteractor>(),
|
||||
MockSpec<MarkAsStarEmailInteractor>(),
|
||||
MockSpec<DownloadAttachmentForWebInteractor>(),
|
||||
MockSpec<GetAllIdentitiesInteractor>(),
|
||||
MockSpec<StoreOpenedEmailInteractor>(),
|
||||
MockSpec<ViewAttachmentForWebInteractor>(),
|
||||
MockSpec<MailboxDashBoardController>(fallbackGenerators: fallbackGenerators),
|
||||
MockSpec<EmailSupervisorController>(fallbackGenerators: fallbackGenerators),
|
||||
MockSpec<DownloadManager>(fallbackGenerators: fallbackGenerators),
|
||||
MockSpec<CachingManager>(fallbackGenerators: fallbackGenerators),
|
||||
MockSpec<LanguageCacheManager>(fallbackGenerators: fallbackGenerators),
|
||||
MockSpec<AuthorizationInterceptors>(),
|
||||
MockSpec<DynamicUrlInterceptors>(),
|
||||
MockSpec<DeleteCredentialInteractor>(),
|
||||
MockSpec<LogoutOidcInteractor>(),
|
||||
MockSpec<DeleteAuthorityOidcInteractor>(),
|
||||
MockSpec<AppToast>(),
|
||||
MockSpec<ImagePaths>(),
|
||||
MockSpec<ResponsiveUtils>(),
|
||||
MockSpec<Uuid>(),
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final getEmailContentInteractor = MockGetEmailContentInteractor();
|
||||
final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor();
|
||||
final downloadAttachmentsInteractor = MockDownloadAttachmentsInteractor();
|
||||
final deviceManager = MockDeviceManager();
|
||||
final exportAttachmentInteractor = MockExportAttachmentInteractor();
|
||||
final moveToMailboxInteractor = MockMoveToMailboxInteractor();
|
||||
final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor();
|
||||
final downloadAttachmentForWebInteractor =
|
||||
MockDownloadAttachmentForWebInteractor();
|
||||
final getAllIdentitiesInteractor = MockGetAllIdentitiesInteractor();
|
||||
final storeOpenedEmailInteractor = MockStoreOpenedEmailInteractor();
|
||||
final viewAttachmentForWebInteractor = MockViewAttachmentForWebInteractor();
|
||||
final mailboxDashboardController = MockMailboxDashBoardController();
|
||||
final emailSupervisorController = MockEmailSupervisorController();
|
||||
final downloadManager = MockDownloadManager();
|
||||
final cachingManager = MockCachingManager();
|
||||
final languageCacheManager = MockLanguageCacheManager();
|
||||
final authorizationInterceptors = MockAuthorizationInterceptors();
|
||||
final dynamicUrlInterceptors = MockDynamicUrlInterceptors();
|
||||
final deleteCredentialInteractor = MockDeleteCredentialInteractor();
|
||||
final logoutOidcInteractor = MockLogoutOidcInteractor();
|
||||
final deleteAuthorityOidcInteractor = MockDeleteAuthorityOidcInteractor();
|
||||
final appToast = MockAppToast();
|
||||
final imagePaths = MockImagePaths();
|
||||
final responsiveUtils = MockResponsiveUtils();
|
||||
final uuid = MockUuid();
|
||||
|
||||
late SingleEmailController singleEmailController = SingleEmailController(
|
||||
getEmailContentInteractor,
|
||||
markAsEmailReadInteractor,
|
||||
downloadAttachmentsInteractor,
|
||||
deviceManager,
|
||||
exportAttachmentInteractor,
|
||||
moveToMailboxInteractor,
|
||||
markAsStarEmailInteractor,
|
||||
downloadAttachmentForWebInteractor,
|
||||
getAllIdentitiesInteractor,
|
||||
storeOpenedEmailInteractor,
|
||||
viewAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
final testAccountId = AccountId(Id('123'));
|
||||
final google = Uri.parse('https://www.google.com');
|
||||
final testSession =
|
||||
Session({}, {}, {}, UserName('data'), google, google, google, google, State('1'));
|
||||
const testTaskId = 'taskId';
|
||||
final testDownloadTaskId = DownloadTaskId(testTaskId);
|
||||
final testBytes = Uint8List(123);
|
||||
|
||||
setUpAll(() {
|
||||
Get.put<MailboxDashBoardController>(mailboxDashboardController);
|
||||
Get.put<EmailSupervisorController>(emailSupervisorController);
|
||||
Get.put<DownloadManager>(downloadManager);
|
||||
Get.put<CachingManager>(cachingManager);
|
||||
Get.put<LanguageCacheManager>(languageCacheManager);
|
||||
Get.put<AuthorizationInterceptors>(authorizationInterceptors);
|
||||
Get.put<AuthorizationInterceptors>(
|
||||
authorizationInterceptors,
|
||||
tag: BindingTag.isolateTag,
|
||||
);
|
||||
Get.put<DynamicUrlInterceptors>(dynamicUrlInterceptors);
|
||||
Get.put<DeleteCredentialInteractor>(deleteCredentialInteractor);
|
||||
Get.put<LogoutOidcInteractor>(logoutOidcInteractor);
|
||||
Get.put<DeleteAuthorityOidcInteractor>(deleteAuthorityOidcInteractor);
|
||||
Get.put<AppToast>(appToast);
|
||||
Get.put<ImagePaths>(imagePaths);
|
||||
Get.put<ResponsiveUtils>(responsiveUtils);
|
||||
Get.put<Uuid>(uuid);
|
||||
|
||||
when(mailboxDashboardController.accountId).thenReturn(Rxn(testAccountId));
|
||||
when(uuid.v4()).thenReturn(testTaskId);
|
||||
});
|
||||
|
||||
group('single email controller', () {
|
||||
test(
|
||||
'should call execute on ViewAttachmentForWebInteractor '
|
||||
'when viewAttachmentForWeb is called',
|
||||
() {
|
||||
// arrange
|
||||
when(mailboxDashboardController.sessionCurrent).thenReturn(testSession);
|
||||
final testAttachment = Attachment();
|
||||
|
||||
// act
|
||||
singleEmailController.viewAttachmentForWeb(testAttachment);
|
||||
|
||||
// assert
|
||||
verify(viewAttachmentForWebInteractor.execute(
|
||||
any,
|
||||
testAttachment,
|
||||
testAccountId,
|
||||
any,
|
||||
any,
|
||||
)).called(1);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'should trigger mailboxDashBoardController.deleteDownloadTask & downloadManager.openDownloadedFileWeb'
|
||||
'when attachment mime type is pdf',
|
||||
() async {
|
||||
// arrange
|
||||
final testAttachment = Attachment(type: MediaType('application', 'pdf'));
|
||||
when(mailboxDashboardController.sessionCurrent).thenReturn(testSession);
|
||||
when(viewAttachmentForWebInteractor.execute(
|
||||
testDownloadTaskId,
|
||||
testAttachment,
|
||||
testAccountId,
|
||||
any,
|
||||
any,
|
||||
)).thenAnswer((_) => Stream.value(
|
||||
right(ViewAttachmentForWebSuccess(
|
||||
testDownloadTaskId,
|
||||
testAttachment,
|
||||
testBytes,
|
||||
)),
|
||||
));
|
||||
|
||||
// act
|
||||
singleEmailController.viewAttachmentForWeb(testAttachment);
|
||||
|
||||
// assert
|
||||
await untilCalled(mailboxDashboardController.deleteDownloadTask(any));
|
||||
verify(mailboxDashboardController.deleteDownloadTask(testDownloadTaskId))
|
||||
.called(1);
|
||||
await untilCalled(downloadManager.openDownloadedFileWeb(any, any));
|
||||
verify(downloadManager.openDownloadedFileWeb(
|
||||
testBytes,
|
||||
Constant.pdfMimeType,
|
||||
)).called(1);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'should trigger mailboxDashBoardController.deleteDownloadTask & downloadManager.createAnchorElementDownloadFileWeb'
|
||||
'when attachment mime type is not pdf',
|
||||
() async {
|
||||
// arrange
|
||||
const testFileName = 'test_file.txt';
|
||||
final testAttachment = Attachment(name: testFileName);
|
||||
when(mailboxDashboardController.sessionCurrent).thenReturn(testSession);
|
||||
when(viewAttachmentForWebInteractor.execute(
|
||||
testDownloadTaskId,
|
||||
testAttachment,
|
||||
testAccountId,
|
||||
any,
|
||||
any,
|
||||
)).thenAnswer((_) => Stream.value(
|
||||
right(ViewAttachmentForWebSuccess(
|
||||
testDownloadTaskId,
|
||||
testAttachment,
|
||||
testBytes,
|
||||
)),
|
||||
));
|
||||
|
||||
// act
|
||||
singleEmailController.viewAttachmentForWeb(testAttachment);
|
||||
|
||||
// assert
|
||||
await untilCalled(mailboxDashboardController.deleteDownloadTask(any));
|
||||
verify(mailboxDashboardController.deleteDownloadTask(testDownloadTaskId))
|
||||
.called(1);
|
||||
await untilCalled(
|
||||
downloadManager.createAnchorElementDownloadFileWeb(any, any),
|
||||
);
|
||||
verify(downloadManager.createAnchorElementDownloadFileWeb(
|
||||
testBytes,
|
||||
testFileName,
|
||||
)).called(1);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user