TF-2901 Implement caching composer on log out
This commit is contained in:
@@ -9,6 +9,13 @@ class NotFoundInWebSessionException with EquatableMixin implements Exception {
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class NotMatchInWebSessionException with EquatableMixin implements Exception {
|
||||
const NotMatchInWebSessionException();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class SaveToWebSessionFailException with EquatableMixin implements Exception {
|
||||
final String? errorMessage;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class ImageTransformer extends DomTransformer {
|
||||
imageSource: src
|
||||
);
|
||||
imageElement.attributes['src'] = imageBase64 ?? src;
|
||||
imageElement.attributes['id'] ??= src;
|
||||
} else if (src.startsWith('https://') || src.startsWith('http://')) {
|
||||
if (!imageElement.attributes.containsKey('loading')) {
|
||||
imageElement.attributes['loading'] = 'lazy';
|
||||
|
||||
@@ -63,6 +63,8 @@ class TransformConfiguration {
|
||||
|
||||
factory TransformConfiguration.forPreviewEmail() => TransformConfiguration.standardConfiguration;
|
||||
|
||||
factory TransformConfiguration.forRestoreEmail() => TransformConfiguration.fromDomTransformers([const ImageTransformer()]);
|
||||
|
||||
factory TransformConfiguration.forPrintEmail() => TransformConfiguration.fromDomTransformers([
|
||||
if (PlatformInfo.isWeb)
|
||||
const RemoveTooltipLinkTransformer(),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
|
||||
class RestoringEmailInlineImages extends LoadingState {}
|
||||
|
||||
class RestoreEmailInlineImagesSuccess extends UIState {
|
||||
final String emailContent;
|
||||
|
||||
RestoreEmailInlineImagesSuccess(this.emailContent);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [emailContent];
|
||||
}
|
||||
|
||||
class RestoreEmailInlineImagesFailure extends FeatureFailure {
|
||||
|
||||
RestoreEmailInlineImagesFailure({super.exception});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/restore_email_inline_images_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart';
|
||||
|
||||
class RestoreEmailInlineImagesInteractor {
|
||||
RestoreEmailInlineImagesInteractor(this._composerCacheRepository);
|
||||
|
||||
final ComposerCacheRepository _composerCacheRepository;
|
||||
|
||||
Stream<Either<Failure, Success>> execute({
|
||||
required String htmlContent,
|
||||
required TransformConfiguration transformConfiguration,
|
||||
required Map<String, String> mapUrlDownloadCID
|
||||
}) async* {
|
||||
try {
|
||||
yield Right(RestoringEmailInlineImages());
|
||||
|
||||
final emailContent = await _composerCacheRepository.restoreEmailInlineImages(
|
||||
htmlContent,
|
||||
transformConfiguration,
|
||||
mapUrlDownloadCID);
|
||||
yield Right(RestoreEmailInlineImagesSuccess(emailContent));
|
||||
} catch (exception) {
|
||||
yield Left(RestoreEmailInlineImagesFailure(exception: exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/save_composer_cache_state.dart';
|
||||
|
||||
@@ -15,10 +18,22 @@ class SaveComposerCacheOnWebInteractor {
|
||||
this._composerRepository,
|
||||
);
|
||||
|
||||
Future<Either<Failure, Success>> execute(CreateEmailRequest createEmailRequest) async {
|
||||
Future<Either<Failure, Success>> execute(
|
||||
CreateEmailRequest createEmailRequest,
|
||||
AccountId accountId,
|
||||
UserName userName,
|
||||
{required ScreenDisplayMode displayMode}
|
||||
) async {
|
||||
try {
|
||||
final emailCreated = await _composerRepository.generateEmail(createEmailRequest);
|
||||
_composerCacheRepository.saveComposerCacheOnWeb(emailCreated);
|
||||
final identity = createEmailRequest.identity;
|
||||
await _composerCacheRepository.saveComposerCacheOnWeb(
|
||||
emailCreated,
|
||||
accountId: accountId,
|
||||
userName: userName,
|
||||
displayMode: displayMode,
|
||||
identity: identity,
|
||||
readReceipentEnabled: createEmailRequest.isRequestReadReceipt);
|
||||
return Right(SaveComposerCacheSuccess());
|
||||
} catch (exception) {
|
||||
return Left(SaveComposerCacheFailure(exception));
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:tmail_ui_user/features/composer/domain/repository/contact_reposi
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_save_email_to_drafts_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/create_new_and_send_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/restore_email_inline_images_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||
@@ -208,6 +209,8 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.find<MailboxRepository>(),
|
||||
Get.find<ComposerRepository>(),
|
||||
));
|
||||
Get.lazyPut(() => RestoreEmailInlineImagesInteractor(
|
||||
Get.find<ComposerCacheRepository>()));
|
||||
|
||||
IdentityInteractorsBindings().dependencies();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
@@ -26,6 +27,8 @@ import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:rich_text_composer/rich_text_composer.dart';
|
||||
import 'package:super_tag_editor/tag_editor.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_unload_handler.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_unload_manager.dart';
|
||||
import 'package:tmail_ui_user/features/base/state/base_ui_state.dart';
|
||||
import 'package:tmail_ui_user/features/base/state/button_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart';
|
||||
@@ -34,6 +37,7 @@ import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_b
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/generate_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/restore_email_inline_images_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
||||
@@ -43,6 +47,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_a
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/restore_email_inline_images_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart';
|
||||
@@ -91,11 +96,12 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
class ComposerController extends BaseController with DragDropFileMixin {
|
||||
class ComposerController extends BaseController with DragDropFileMixin implements BeforeUnloadHandler {
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final networkConnectionController = Get.find<NetworkConnectionController>();
|
||||
final _dynamicUrlInterceptors = Get.find<DynamicUrlInterceptors>();
|
||||
final _beforeUnloadManager = Get.find<BeforeUnloadManager>();
|
||||
|
||||
final composerArguments = Rxn<ComposerArguments>();
|
||||
final isEnableEmailSendButton = false.obs;
|
||||
@@ -129,6 +135,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor;
|
||||
GetAutoCompleteInteractor? _getAutoCompleteInteractor;
|
||||
GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor;
|
||||
RestoreEmailInlineImagesInteractor? _restoreEmailInlineImagesInteractor;
|
||||
|
||||
List<EmailAddress> listToEmailAddress = <EmailAddress>[];
|
||||
List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
|
||||
@@ -162,6 +169,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
StreamSubscription<html.Event>? _subscriptionOnDragOver;
|
||||
StreamSubscription<html.Event>? _subscriptionOnDragLeave;
|
||||
StreamSubscription<html.Event>? _subscriptionOnDrop;
|
||||
StreamSubscription<String>? _composerCacheListener;
|
||||
|
||||
RichTextMobileTabletController? richTextMobileTabletController;
|
||||
RichTextWebController? richTextWebController;
|
||||
@@ -215,6 +223,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
scrollControllerEmailAddress.addListener(_scrollControllerEmailAddressListener);
|
||||
_listenStreamEvent();
|
||||
_getAlwaysReadReceiptSetting();
|
||||
_beforeUnloadManager.addListener(onBeforeUnload);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -241,6 +250,8 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
_subscriptionOnDragLeave?.cancel();
|
||||
_subscriptionOnDrop?.cancel();
|
||||
subjectEmailInputFocusNode?.removeListener(_subjectEmailInputFocusListener);
|
||||
_composerCacheListener?.cancel();
|
||||
_beforeUnloadManager.removeListener(onBeforeUnload);
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -281,7 +292,8 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
super.handleSuccessViewState(success);
|
||||
if (success is GetEmailContentLoading ||
|
||||
success is TransformHtmlEmailContentLoading ||
|
||||
success is TransformHtmlEmailContentSuccess) {
|
||||
success is TransformHtmlEmailContentSuccess ||
|
||||
success is RestoringEmailInlineImages) {
|
||||
emailContentsViewState.value = Right(success);
|
||||
} else if (success is LocalFilePickerSuccess) {
|
||||
_handlePickFileSuccess(success);
|
||||
@@ -303,9 +315,18 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
maxWithEditor = null;
|
||||
} else if (success is GetAlwaysReadReceiptSettingSuccess) {
|
||||
hasRequestReadReceipt.value = success.alwaysReadReceiptEnabled;
|
||||
} else if (success is RestoreEmailInlineImagesSuccess) {
|
||||
_updateEditorContent(success);
|
||||
}
|
||||
}
|
||||
|
||||
void _updateEditorContent(RestoreEmailInlineImagesSuccess success) {
|
||||
richTextWebController?.editorController.setText(success.emailContent);
|
||||
consumeState(Stream.value(Right(GetEmailContentSuccess(
|
||||
htmlEmailContent: success.emailContent,
|
||||
attachments: []))));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleFailureViewState(Failure failure) {
|
||||
super.handleFailureViewState(failure);
|
||||
@@ -314,7 +335,8 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
} else if (failure is LocalImagePickerFailure) {
|
||||
_handlePickImageFailure(failure);
|
||||
} else if (failure is GetEmailContentFailure ||
|
||||
failure is TransformHtmlEmailContentFailure) {
|
||||
failure is TransformHtmlEmailContentFailure ||
|
||||
failure is RestoreEmailInlineImagesFailure) {
|
||||
emailContentsViewState.value = Left(failure);
|
||||
} else if (failure is GetAllIdentitiesFailure) {
|
||||
if (identitySelected.value == null) {
|
||||
@@ -348,40 +370,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
_subscriptionOnBeforeUnload = html.window.onBeforeUnload.listen((event) async {
|
||||
await _removeComposerCacheOnWebInteractor.execute();
|
||||
|
||||
if (composerArguments.value == null ||
|
||||
mailboxDashBoardController.sessionCurrent == null ||
|
||||
mailboxDashBoardController.accountId.value == null
|
||||
) {
|
||||
log('ComposerController::_listenBrowserTabRefresh: SESSION or ACCOUNT_ID or ARGUMENTS is NULL');
|
||||
return;
|
||||
}
|
||||
|
||||
final emailContent = await _getContentInEditor();
|
||||
|
||||
await _saveComposerCacheOnWebInteractor.execute(CreateEmailRequest(
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
accountId: mailboxDashBoardController.accountId.value!,
|
||||
emailActionType: composerArguments.value!.emailActionType,
|
||||
subject: subjectEmail.value ?? '',
|
||||
emailContent: emailContent,
|
||||
fromSender: composerArguments.value!.presentationEmail?.from ?? {},
|
||||
toRecipients: listToEmailAddress.toSet(),
|
||||
ccRecipients: listCcEmailAddress.toSet(),
|
||||
bccRecipients: listBccEmailAddress.toSet(),
|
||||
isRequestReadReceipt: hasRequestReadReceipt.value,
|
||||
identity: identitySelected.value,
|
||||
attachments: uploadController.attachmentsUploaded,
|
||||
inlineAttachments: uploadController.mapInlineAttachments,
|
||||
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
|
||||
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
|
||||
draftsMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts],
|
||||
draftsEmailId: _getDraftEmailId(),
|
||||
answerForwardEmailId: composerArguments.value!.presentationEmail?.id,
|
||||
unsubscribeEmailId: composerArguments.value!.previousEmailId,
|
||||
messageId: composerArguments.value!.messageId,
|
||||
references: composerArguments.value!.references,
|
||||
emailSendingQueue: composerArguments.value!.sendingEmail
|
||||
));
|
||||
await _saveComposerCacheOnWebAction();
|
||||
});
|
||||
|
||||
_subscriptionOnDragEnter = html.window.onDragEnter.listen((event) {
|
||||
@@ -401,6 +390,56 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _saveComposerCacheOnWebAction() async {
|
||||
_autoCreateEmailTag();
|
||||
|
||||
final createEmailRequest = await _generateCreateEmailRequest();
|
||||
if (createEmailRequest == null) return;
|
||||
|
||||
await _saveComposerCacheOnWebInteractor.execute(
|
||||
createEmailRequest,
|
||||
mailboxDashBoardController.accountId.value!,
|
||||
mailboxDashBoardController.sessionCurrent!.username,
|
||||
displayMode: screenDisplayMode.value);
|
||||
}
|
||||
|
||||
Future<CreateEmailRequest?> _generateCreateEmailRequest() async {
|
||||
if (composerArguments.value == null ||
|
||||
mailboxDashBoardController.sessionCurrent == null ||
|
||||
mailboxDashBoardController.accountId.value == null
|
||||
) {
|
||||
log('ComposerController::_generateCreateEmailRequest: SESSION or ACCOUNT_ID or ARGUMENTS is NULL');
|
||||
return null;
|
||||
}
|
||||
|
||||
final emailContent = await _getContentInEditor();
|
||||
|
||||
return CreateEmailRequest(
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
accountId: mailboxDashBoardController.accountId.value!,
|
||||
emailActionType: composerArguments.value!.emailActionType,
|
||||
subject: subjectEmail.value ?? '',
|
||||
emailContent: emailContent,
|
||||
fromSender: composerArguments.value!.presentationEmail?.from ?? {},
|
||||
toRecipients: listToEmailAddress.toSet(),
|
||||
ccRecipients: listCcEmailAddress.toSet(),
|
||||
bccRecipients: listBccEmailAddress.toSet(),
|
||||
isRequestReadReceipt: hasRequestReadReceipt.value,
|
||||
identity: identitySelected.value,
|
||||
attachments: uploadController.attachmentsUploaded,
|
||||
inlineAttachments: uploadController.mapInlineAttachments,
|
||||
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
|
||||
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
|
||||
draftsMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts],
|
||||
draftsEmailId: _getDraftEmailId(),
|
||||
answerForwardEmailId: composerArguments.value!.presentationEmail?.id,
|
||||
unsubscribeEmailId: composerArguments.value!.previousEmailId,
|
||||
messageId: composerArguments.value!.messageId,
|
||||
references: composerArguments.value!.references,
|
||||
emailSendingQueue: composerArguments.value!.sendingEmail
|
||||
);
|
||||
}
|
||||
|
||||
void _scrollControllerEmailAddressListener() {
|
||||
if (toEmailAddressController.text.isNotEmpty) {
|
||||
keyToEmailTagEditor.currentState?.closeSuggestionBox();
|
||||
@@ -481,7 +520,7 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
if (arguments is ComposerArguments) {
|
||||
composerArguments.value = arguments;
|
||||
|
||||
_initIdentities(arguments.identities);
|
||||
_initIdentities(arguments);
|
||||
|
||||
injectAutoCompleteBindings(
|
||||
mailboxDashBoardController.sessionCurrent,
|
||||
@@ -563,6 +602,10 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
_transformHtmlEmailContent(arguments.emailContents);
|
||||
break;
|
||||
case EmailActionType.reopenComposerBrowser:
|
||||
if (!PlatformInfo.isWeb) return;
|
||||
|
||||
screenDisplayMode.value = arguments.displayMode;
|
||||
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.reopenComposerBrowser
|
||||
@@ -571,8 +614,22 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: EmailActionType.reopenComposerBrowser
|
||||
);
|
||||
_initAttachments(arguments.attachments ?? []);
|
||||
_getEmailContentFromSessionStorageBrowser(arguments.emailContents!);
|
||||
_initAttachments(
|
||||
arguments.attachments ?? [],
|
||||
inlineAttachments: arguments.inlineImages);
|
||||
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
final downloadUrl = mailboxDashBoardController.sessionCurrent
|
||||
?.getDownloadUrl(jmapUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
if (accountId == null || downloadUrl == null) return;
|
||||
_getEmailContentFromSessionStorageBrowser(
|
||||
htmlContent: arguments.emailContents ?? '',
|
||||
inlineImages: arguments.inlineImages ?? [],
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl
|
||||
);
|
||||
|
||||
hasRequestReadReceipt.value = arguments.readRecepientEnabled ?? false;
|
||||
break;
|
||||
case EmailActionType.composeFromUnsubscribeMailtoLink:
|
||||
if (arguments.subject != null) {
|
||||
@@ -603,17 +660,26 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
subjectEmailInputController.text = newSubject;
|
||||
}
|
||||
|
||||
void _initAttachments(List<Attachment> attachments) {
|
||||
void _initAttachments(List<Attachment> attachments, {List<Attachment>? inlineAttachments}) {
|
||||
if (attachments.isNotEmpty) {
|
||||
initialAttachments = attachments;
|
||||
uploadController.initializeUploadAttachments(attachments);
|
||||
}
|
||||
if (inlineAttachments != null) {
|
||||
uploadController.initializeUploadInlineAttachments(inlineAttachments);
|
||||
}
|
||||
}
|
||||
|
||||
void _initIdentities(List<Identity>? identities) {
|
||||
if (identities?.isNotEmpty == true) {
|
||||
listFromIdentities.value = identities!;
|
||||
identitySelected.value = identities.first;
|
||||
void _initIdentities(ComposerArguments composerArguments) {
|
||||
listFromIdentities.value = composerArguments.identities ?? [];
|
||||
if (listFromIdentities.isEmpty) {
|
||||
_getAllIdentities();
|
||||
} else if (composerArguments.selectedIdentity != null
|
||||
&& listFromIdentities.contains(composerArguments.selectedIdentity!)
|
||||
) {
|
||||
_selectIdentity(composerArguments.selectedIdentity!);
|
||||
} else if (composerArguments.identities?.isNotEmpty == true) {
|
||||
_selectIdentity(composerArguments.identities!.first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,7 +698,14 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
listFromIdentities.value = listIdentitiesMayDeleted;
|
||||
|
||||
if (identitySelected.value == null) {
|
||||
await _selectIdentity(listIdentitiesMayDeleted.first);
|
||||
final selectedIdentityFromArguments = composerArguments.value?.selectedIdentity;
|
||||
if (selectedIdentityFromArguments != null
|
||||
&& listFromIdentities.contains(selectedIdentityFromArguments)
|
||||
) {
|
||||
await _selectIdentity(selectedIdentityFromArguments);
|
||||
} else {
|
||||
await _selectIdentity(listIdentitiesMayDeleted.firstOrNull);
|
||||
}
|
||||
}
|
||||
}
|
||||
_autoFocusFieldWhenLauncher();
|
||||
@@ -1226,13 +1299,20 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
));
|
||||
}
|
||||
|
||||
void _getEmailContentFromSessionStorageBrowser(String content) {
|
||||
consumeState(Stream.value(
|
||||
Right(GetEmailContentSuccess(
|
||||
htmlEmailContent: content,
|
||||
attachments: [],
|
||||
))
|
||||
));
|
||||
void _getEmailContentFromSessionStorageBrowser({
|
||||
required String htmlContent,
|
||||
required List<Attachment> inlineImages,
|
||||
required AccountId accountId,
|
||||
required String downloadUrl
|
||||
}) {
|
||||
_restoreEmailInlineImagesInteractor = getBinding<RestoreEmailInlineImagesInteractor>();
|
||||
if (_restoreEmailInlineImagesInteractor == null) return;
|
||||
consumeState(_restoreEmailInlineImagesInteractor!.execute(
|
||||
htmlContent: htmlContent,
|
||||
transformConfiguration: TransformConfiguration.forRestoreEmail(),
|
||||
mapUrlDownloadCID: inlineImages.toMapCidImageDownloadUrl(
|
||||
accountId: accountId,
|
||||
downloadUrl: downloadUrl)));
|
||||
}
|
||||
|
||||
void _getEmailContentFromContentShared(String content) {
|
||||
@@ -1533,7 +1613,12 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
Future<void> _selectIdentity(Identity? newIdentity) async {
|
||||
final formerIdentity = identitySelected.value;
|
||||
identitySelected.value = newIdentity;
|
||||
if (newIdentity != null) {
|
||||
if (newIdentity == null) return;
|
||||
|
||||
if (composerArguments.value?.emailActionType == EmailActionType.reopenComposerBrowser) {
|
||||
composerArguments.value = composerArguments.value?.copyWith(
|
||||
emailActionType: EmailActionType.editDraft);
|
||||
} else {
|
||||
await _applyIdentityForAllFieldComposer(formerIdentity, newIdentity);
|
||||
}
|
||||
}
|
||||
@@ -2178,4 +2263,13 @@ class ComposerController extends BaseController with DragDropFileMixin {
|
||||
ccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
|
||||
bccRecipientState.value = isEnabled ? PrefixRecipientState.disabled : PrefixRecipientState.enabled;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onBeforeUnload() async {
|
||||
if (mailboxDashBoardController.accountId.value != null &&
|
||||
mailboxDashBoardController.sessionCurrent?.username != null
|
||||
) {
|
||||
await _saveComposerCacheOnWebAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,18 @@
|
||||
enum ScreenDisplayMode {
|
||||
fullScreen,
|
||||
minimize,
|
||||
normal
|
||||
normal;
|
||||
|
||||
factory ScreenDisplayMode.fromJson(String value) {
|
||||
switch (value) {
|
||||
case 'fullScreen':
|
||||
return ScreenDisplayMode.fullScreen;
|
||||
case 'minimize':
|
||||
return ScreenDisplayMode.minimize;
|
||||
default:
|
||||
return ScreenDisplayMode.normal;
|
||||
}
|
||||
}
|
||||
|
||||
String toJson() => name;
|
||||
}
|
||||
@@ -3,22 +3,10 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
|
||||
|
||||
extension ComposerArgumentsExtension on ComposerArguments {
|
||||
|
||||
ComposerArguments withIdentity({List<Identity>? identities}) {
|
||||
return ComposerArguments(
|
||||
emailActionType: emailActionType,
|
||||
presentationEmail: presentationEmail,
|
||||
emailContents: emailContents,
|
||||
attachments: attachments,
|
||||
mailboxRole: mailboxRole,
|
||||
listEmailAddress: listEmailAddress,
|
||||
listSharedMediaFile: listSharedMediaFile,
|
||||
sendingEmail: sendingEmail,
|
||||
subject: subject,
|
||||
body: body,
|
||||
messageId: messageId,
|
||||
references: references,
|
||||
previousEmailId: previousEmailId,
|
||||
ComposerArguments withIdentity({List<Identity>? identities, Identity? selectedIdentity}) {
|
||||
return copyWith(
|
||||
identities: identities,
|
||||
selectedIdentity: selectedIdentity,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart';
|
||||
@@ -24,6 +26,10 @@ class ComposerArguments extends RouterArguments {
|
||||
final MessageIdsHeaderValue? references;
|
||||
final EmailId? previousEmailId;
|
||||
final List<Identity>? identities;
|
||||
final Identity? selectedIdentity;
|
||||
final List<Attachment>? inlineImages;
|
||||
final bool? readRecepientEnabled;
|
||||
final ScreenDisplayMode displayMode;
|
||||
|
||||
ComposerArguments({
|
||||
this.emailActionType = EmailActionType.compose,
|
||||
@@ -40,6 +46,10 @@ class ComposerArguments extends RouterArguments {
|
||||
this.references,
|
||||
this.previousEmailId,
|
||||
this.identities,
|
||||
this.selectedIdentity,
|
||||
this.inlineImages,
|
||||
this.readRecepientEnabled,
|
||||
this.displayMode = ScreenDisplayMode.normal
|
||||
});
|
||||
|
||||
factory ComposerArguments.fromSendingEmail(SendingEmail sendingEmail) =>
|
||||
@@ -83,15 +93,15 @@ class ComposerArguments extends RouterArguments {
|
||||
factory ComposerArguments.fromSessionStorageBrowser(ComposerCache composerCache) =>
|
||||
ComposerArguments(
|
||||
emailActionType: EmailActionType.reopenComposerBrowser,
|
||||
presentationEmail: PresentationEmail(
|
||||
id: composerCache.id,
|
||||
subject: composerCache.subject,
|
||||
from: composerCache.from,
|
||||
to: composerCache.to,
|
||||
cc: composerCache.cc,
|
||||
bcc: composerCache.bcc,
|
||||
),
|
||||
emailContents: composerCache.emailContentList.asHtmlString,
|
||||
presentationEmail: composerCache.email?.toPresentationEmail(),
|
||||
emailContents: composerCache.email?.emailContentList.asHtmlString,
|
||||
attachments: composerCache.email?.allAttachments
|
||||
.where((attachment) => attachment.disposition != ContentDisposition.inline)
|
||||
.toList(),
|
||||
selectedIdentity: composerCache.identity,
|
||||
inlineImages: composerCache.email?.attachmentsWithCid,
|
||||
readRecepientEnabled: composerCache.readReceipentEnabled,
|
||||
displayMode: composerCache.displayMode,
|
||||
);
|
||||
|
||||
factory ComposerArguments.replyEmail({
|
||||
@@ -175,4 +185,46 @@ class ComposerArguments extends RouterArguments {
|
||||
references,
|
||||
identities,
|
||||
];
|
||||
}
|
||||
|
||||
ComposerArguments copyWith({
|
||||
EmailActionType? emailActionType,
|
||||
PresentationEmail? presentationEmail,
|
||||
String? emailContents,
|
||||
List<SharedMediaFile>? listSharedMediaFile,
|
||||
List<EmailAddress>? listEmailAddress,
|
||||
List<Attachment>? attachments,
|
||||
Role? mailboxRole,
|
||||
SendingEmail? sendingEmail,
|
||||
String? subject,
|
||||
String? body,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
EmailId? previousEmailId,
|
||||
List<Identity>? identities,
|
||||
Identity? selectedIdentity,
|
||||
List<Attachment>? inlineImages,
|
||||
bool? readRecepientEnabled,
|
||||
ScreenDisplayMode? displayMode,
|
||||
}) {
|
||||
return ComposerArguments(
|
||||
emailActionType: emailActionType ?? this.emailActionType,
|
||||
presentationEmail: presentationEmail ?? this.presentationEmail,
|
||||
emailContents: emailContents ?? this.emailContents,
|
||||
listSharedMediaFile: listSharedMediaFile ?? this.listSharedMediaFile,
|
||||
listEmailAddress: listEmailAddress ?? this.listEmailAddress,
|
||||
attachments: attachments ?? this.attachments,
|
||||
mailboxRole: mailboxRole ?? this.mailboxRole,
|
||||
sendingEmail: sendingEmail ?? this.sendingEmail,
|
||||
subject: subject ?? this.subject,
|
||||
body: body ?? this.body,
|
||||
messageId: messageId ?? this.messageId,
|
||||
references: references ?? this.references,
|
||||
previousEmailId: previousEmailId ?? this.previousEmailId,
|
||||
identities: identities ?? this.identities,
|
||||
selectedIdentity: selectedIdentity ?? this.selectedIdentity,
|
||||
inlineImages: inlineImages ?? this.inlineImages,
|
||||
readRecepientEnabled: readRecepientEnabled ?? this.readRecepientEnabled,
|
||||
displayMode: displayMode ?? this.displayMode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-3
@@ -1,10 +1,31 @@
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
|
||||
abstract class SessionStorageComposerDatasource {
|
||||
void saveComposerCacheOnWeb(Email email);
|
||||
Future<void> saveComposerCacheOnWeb(
|
||||
Email email,
|
||||
{
|
||||
required AccountId accountId,
|
||||
required UserName userName,
|
||||
required ScreenDisplayMode displayMode,
|
||||
Identity? identity,
|
||||
bool? readReceipentEnabled,
|
||||
}
|
||||
);
|
||||
|
||||
ComposerCache getComposerCacheOnWeb();
|
||||
Future<ComposerCache> getComposerCacheOnWeb(
|
||||
AccountId accountId,
|
||||
UserName userName);
|
||||
|
||||
void removeComposerCacheOnWeb();
|
||||
Future<void> removeComposerCacheOnWeb();
|
||||
|
||||
Future<String> restoreEmailInlineImages(
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Map<String, String> mapUrlDownloadCID);
|
||||
}
|
||||
+68
-21
@@ -1,47 +1,94 @@
|
||||
import 'dart:convert';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:core/core.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
class SessionStorageComposerDatasourceImpl
|
||||
extends SessionStorageComposerDatasource {
|
||||
SessionStorageComposerDatasourceImpl(this._htmlTransform, this._exceptionThrower);
|
||||
|
||||
final HtmlTransform _htmlTransform;
|
||||
final ExceptionThrower _exceptionThrower;
|
||||
|
||||
@override
|
||||
ComposerCache getComposerCacheOnWeb() {
|
||||
try {
|
||||
final result = html.window.sessionStorage.entries.firstWhereOrNull((e) => e.key == EmailActionType.reopenComposerBrowser.name);
|
||||
Future<ComposerCache> getComposerCacheOnWeb(
|
||||
AccountId accountId,
|
||||
UserName userName
|
||||
) async {
|
||||
return Future.sync(() async {
|
||||
final keyWithIdentity = TupleKey(
|
||||
EmailActionType.reopenComposerBrowser.name,
|
||||
accountId.asString,
|
||||
userName.value).toString();
|
||||
|
||||
final result = html.window.sessionStorage.entries.firstWhereOrNull(
|
||||
(entry) => entry.key == keyWithIdentity);
|
||||
if (result != null) {
|
||||
final emailCache = ComposerCache.fromJson(jsonDecode(result.value));
|
||||
return emailCache;
|
||||
return ComposerCache.fromJson(jsonDecode(result.value));
|
||||
} else {
|
||||
throw NotFoundInWebSessionException();
|
||||
}
|
||||
} catch (e) {
|
||||
throw NotFoundInWebSessionException(errorMessage: e.toString());
|
||||
}
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
void removeComposerCacheOnWeb() {
|
||||
try {
|
||||
html.window.sessionStorage.removeWhere((key, value) => key == EmailActionType.reopenComposerBrowser.name);
|
||||
} catch (e) {
|
||||
throw NotFoundInWebSessionException(errorMessage: e.toString());
|
||||
}
|
||||
Future<void> removeComposerCacheOnWeb() async {
|
||||
return Future.sync(() {
|
||||
html.window.sessionStorage.removeWhere(
|
||||
(key, value) => key.startsWith(EmailActionType.reopenComposerBrowser.name));
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
void saveComposerCacheOnWeb(Email email) {
|
||||
try {
|
||||
Future<void> saveComposerCacheOnWeb(
|
||||
Email email,
|
||||
{
|
||||
required AccountId accountId,
|
||||
required UserName userName,
|
||||
required ScreenDisplayMode displayMode,
|
||||
Identity? identity,
|
||||
bool? readReceipentEnabled
|
||||
}
|
||||
) async {
|
||||
return Future.sync(() {
|
||||
final composerCacheKey = TupleKey(
|
||||
EmailActionType.reopenComposerBrowser.name,
|
||||
accountId.asString,
|
||||
userName.value).toString();
|
||||
Map<String, String> entries = {
|
||||
EmailActionType.reopenComposerBrowser.name: email.asString()
|
||||
composerCacheKey: jsonEncode(
|
||||
ComposerCache(
|
||||
displayMode: displayMode,
|
||||
email: email,
|
||||
identity: identity,
|
||||
readReceipentEnabled: readReceipentEnabled,
|
||||
).toJson()
|
||||
)
|
||||
};
|
||||
html.window.sessionStorage.addAll(entries);
|
||||
} catch (e) {
|
||||
throw SaveToWebSessionFailException(errorMessage: e.toString());
|
||||
}
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> restoreEmailInlineImages(
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Map<String, String> mapUrlDownloadCID) {
|
||||
return Future.sync(() async {
|
||||
return await _htmlTransform.transformToHtml(
|
||||
htmlContent: htmlContent,
|
||||
transformConfiguration: transformConfiguration,
|
||||
mapCidImageDownloadUrl: mapUrlDownloadCID);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +1,44 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/http/converter/email/email_body_value_converter.dart';
|
||||
import 'package:jmap_dart_client/http/converter/email/email_mailbox_ids_converter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
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/mail/email/email_body_part.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_value.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:model/extensions/media_type_nullable_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
|
||||
class ComposerCache with EquatableMixin {
|
||||
|
||||
final EmailId? id;
|
||||
final Map<MailboxId, bool>? mailboxIds;
|
||||
final String? subject;
|
||||
final Set<EmailAddress>? from;
|
||||
final Set<EmailAddress>? to;
|
||||
final Set<EmailAddress>? cc;
|
||||
final Set<EmailAddress>? bcc;
|
||||
final Set<EmailAddress>? replyTo;
|
||||
final Set<EmailBodyPart>? textBody;
|
||||
final Set<EmailBodyPart>? htmlBody;
|
||||
final Map<PartId, EmailBodyValue>? bodyValues;
|
||||
final Email? email;
|
||||
final Identity? identity;
|
||||
final bool? readReceipentEnabled;
|
||||
final ScreenDisplayMode displayMode;
|
||||
|
||||
ComposerCache({
|
||||
this.id,
|
||||
this.mailboxIds,
|
||||
this.subject,
|
||||
this.from,
|
||||
this.to,
|
||||
this.cc,
|
||||
this.bcc,
|
||||
this.replyTo,
|
||||
this.textBody,
|
||||
this.htmlBody,
|
||||
this.bodyValues,
|
||||
required this.displayMode,
|
||||
this.email,
|
||||
this.identity,
|
||||
this.readReceipentEnabled,
|
||||
});
|
||||
|
||||
factory ComposerCache.fromJson(Map<String, dynamic> json) {
|
||||
return ComposerCache(
|
||||
id: json['id'] != null ? EmailId(Id(json['id'])) : null,
|
||||
mailboxIds: (json['mailboxIds'] as Map<String, dynamic>?)?.map((key, value) => EmailMailboxIdsConverter().parseEntry(key, value)),
|
||||
subject: json['subject'] as String?,
|
||||
from: (json['from'] as List<dynamic>?)?.map((json) => EmailAddress.fromJson(json)).toSet(),
|
||||
to: (json['to'] as List<dynamic>?)?.map((json) => EmailAddress.fromJson(json)).toSet(),
|
||||
cc: (json['cc'] as List<dynamic>?)?.map((json) => EmailAddress.fromJson(json)).toSet(),
|
||||
bcc: (json['bcc'] as List<dynamic>?)?.map((json) => EmailAddress.fromJson(json)).toSet(),
|
||||
bodyValues: (json['bodyValues'] as Map<String, dynamic>?)?.map((key, value) => EmailBodyValueConverter().parseEntry(key, value)),
|
||||
replyTo: (json['replyTo'] as List<dynamic>?)?.map((json) => EmailAddress.fromJson(json)).toSet(),
|
||||
textBody: (json['textBody'] as List<dynamic>?)?.map((json) => EmailBodyPart.fromJson(json)).toSet(),
|
||||
htmlBody: (json['htmlBody'] as List<dynamic>?)?.map((json) => EmailBodyPart.fromJson(json)).toSet(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
subject,
|
||||
from,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo,
|
||||
email,
|
||||
identity,
|
||||
readReceipentEnabled
|
||||
];
|
||||
|
||||
List<EmailContent> get emailContentList {
|
||||
final newHtmlBody = htmlBody
|
||||
?.where((emailBody) => emailBody.partId != null && emailBody.type != null)
|
||||
.toList() ?? <EmailBodyPart>[];
|
||||
|
||||
final mapHtmlBody = { for (var emailBody in newHtmlBody) emailBody.partId! : emailBody.type! };
|
||||
|
||||
final emailContents = bodyValues?.entries
|
||||
.map((entries) => EmailContent(mapHtmlBody[entries.key].toEmailContentType(), entries.value.value))
|
||||
.toList();
|
||||
|
||||
return emailContents ?? [];
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'email': email?.toJson(),
|
||||
'identity': identity?.toJson(),
|
||||
'readReceipentEnabled': readReceipentEnabled,
|
||||
'displayMode': displayMode.toJson()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
factory ComposerCache.fromJson(Map<String, dynamic> map) {
|
||||
return ComposerCache(
|
||||
displayMode: ScreenDisplayMode.fromJson(map['displayMode'] ?? ''),
|
||||
email: map['email'] != null ? Email.fromJson(map['email']) : null,
|
||||
identity: map['identity'] != null ? Identity.fromJson(map['identity']) : null,
|
||||
readReceipentEnabled: map['readReceipentEnabled'] as bool?
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/session_storage_composer_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart';
|
||||
@@ -10,17 +15,46 @@ class ComposerCacheRepositoryImpl extends ComposerCacheRepository {
|
||||
ComposerCacheRepositoryImpl(this.composerCacheDataSource);
|
||||
|
||||
@override
|
||||
ComposerCache getComposerCacheOnWeb() {
|
||||
return composerCacheDataSource.getComposerCacheOnWeb();
|
||||
Future<ComposerCache> getComposerCacheOnWeb(
|
||||
AccountId accountId,
|
||||
UserName userName
|
||||
) {
|
||||
return composerCacheDataSource.getComposerCacheOnWeb(accountId, userName);
|
||||
}
|
||||
|
||||
@override
|
||||
void removeComposerCacheOnWeb() {
|
||||
Future<void> removeComposerCacheOnWeb() {
|
||||
return composerCacheDataSource.removeComposerCacheOnWeb();
|
||||
}
|
||||
|
||||
@override
|
||||
void saveComposerCacheOnWeb(Email email) {
|
||||
return composerCacheDataSource.saveComposerCacheOnWeb(email);
|
||||
Future<void> saveComposerCacheOnWeb(
|
||||
Email email,
|
||||
{
|
||||
required AccountId accountId,
|
||||
required UserName userName,
|
||||
required ScreenDisplayMode displayMode,
|
||||
Identity? identity,
|
||||
bool? readReceipentEnabled
|
||||
}
|
||||
) {
|
||||
return composerCacheDataSource.saveComposerCacheOnWeb(
|
||||
email,
|
||||
accountId: accountId,
|
||||
userName: userName,
|
||||
displayMode: displayMode,
|
||||
identity: identity,
|
||||
readReceipentEnabled: readReceipentEnabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> restoreEmailInlineImages(
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Map<String, String> mapUrlDownloadCID) {
|
||||
return composerCacheDataSource.restoreEmailInlineImages(
|
||||
htmlContent,
|
||||
transformConfiguration,
|
||||
mapUrlDownloadCID);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,31 @@
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/composer_cache.dart';
|
||||
|
||||
abstract class ComposerCacheRepository {
|
||||
void saveComposerCacheOnWeb(Email email);
|
||||
Future<void> saveComposerCacheOnWeb(
|
||||
Email email,
|
||||
{
|
||||
required AccountId accountId,
|
||||
required UserName userName,
|
||||
required ScreenDisplayMode displayMode,
|
||||
Identity? identity,
|
||||
bool? readReceipentEnabled
|
||||
}
|
||||
);
|
||||
|
||||
ComposerCache getComposerCacheOnWeb();
|
||||
Future<ComposerCache> getComposerCacheOnWeb(
|
||||
AccountId accountId,
|
||||
UserName userName);
|
||||
|
||||
void removeComposerCacheOnWeb();
|
||||
Future<void> removeComposerCacheOnWeb();
|
||||
|
||||
Future<String> restoreEmailInlineImages(
|
||||
String htmlContent,
|
||||
TransformConfiguration transformConfiguration,
|
||||
Map<String, String> mapUrlDownloadCID);
|
||||
}
|
||||
|
||||
+6
-4
@@ -1,6 +1,8 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/composer_cache_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart';
|
||||
|
||||
@@ -9,12 +11,12 @@ class GetComposerCacheOnWebInteractor {
|
||||
|
||||
GetComposerCacheOnWebInteractor(this.composerCacheRepository);
|
||||
|
||||
Either<Failure, Success> execute() {
|
||||
Stream<Either<Failure, Success>> execute(AccountId accountId, UserName userName) async* {
|
||||
try {
|
||||
final data = composerCacheRepository.getComposerCacheOnWeb();
|
||||
return Right(GetComposerCacheSuccess(data));
|
||||
final data = await composerCacheRepository.getComposerCacheOnWeb(accountId, userName);
|
||||
yield Right(GetComposerCacheSuccess(data));
|
||||
} catch (exception) {
|
||||
return Left(GetComposerCacheFailure(exception));
|
||||
yield Left(GetComposerCacheFailure(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,6 +203,17 @@ class UploadController extends BaseController {
|
||||
_refreshListUploadAttachmentState();
|
||||
}
|
||||
|
||||
void initializeUploadInlineAttachments(List<Attachment> inlineAttachments) {
|
||||
final listUploadInlineImagesState = inlineAttachments
|
||||
.map((inlineAttachment) => UploadFileState(
|
||||
UploadTaskId(inlineAttachment.blobId!.value),
|
||||
uploadStatus: UploadFileStatus.succeed,
|
||||
attachment: inlineAttachment))
|
||||
.toList();
|
||||
_uploadingStateInlineFiles.addAll(listUploadInlineImagesState);
|
||||
_refreshListUploadAttachmentState();
|
||||
}
|
||||
|
||||
void deleteFileUploaded(UploadTaskId uploadId) {
|
||||
_uploadingStateFiles.deleteElementByUploadTaskId(uploadId);
|
||||
_refreshListUploadAttachmentState();
|
||||
|
||||
Reference in New Issue
Block a user