TF-2901 Implement caching composer on log out
This commit is contained in:
+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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user