TF-145 Add data layer for getAllEmail in Caching
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
|
||||
|
||||
@@ -118,4 +119,17 @@ class EmailCacheClient extends HiveCacheClient<EmailCache> {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
Future<List<EmailCache>> getListEmailCacheByMailboxId(MailboxId mailboxId) {
|
||||
return Future.sync(() async {
|
||||
final boxEmail = await openBox();
|
||||
return boxEmail.values.where((emailCache) {
|
||||
return emailCache.mailboxIds != null
|
||||
&& emailCache.mailboxIds!.containsKey(mailboxId.id.value)
|
||||
&& emailCache.mailboxIds![mailboxId.id.value] == true;
|
||||
}).toList();
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||
|
||||
abstract class ThreadDataSource {
|
||||
Future<List<Email>> getAllEmail(
|
||||
Future<EmailResponse> getAllEmail(
|
||||
AccountId accountId,
|
||||
{
|
||||
int? position,
|
||||
@@ -16,4 +20,17 @@ abstract class ThreadDataSource {
|
||||
Properties? properties
|
||||
}
|
||||
);
|
||||
|
||||
Future<EmailChangeResponse> getChanges(
|
||||
AccountId accountId,
|
||||
State sinceState,
|
||||
{
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated
|
||||
}
|
||||
);
|
||||
|
||||
Future<List<Email>> getAllEmailCache({MailboxId? inMailboxId, Set<Comparator>? sort});
|
||||
|
||||
Future<void> update({List<Email>? updated, List<Email>? created, List<EmailId>? destroyed});
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||
|
||||
class LocalThreadDataSourceImpl extends ThreadDataSource {
|
||||
|
||||
final EmailCacheManager _emailCacheManager;
|
||||
|
||||
LocalThreadDataSourceImpl(this._emailCacheManager);
|
||||
|
||||
@override
|
||||
Future<EmailResponse> getAllEmail(
|
||||
AccountId accountId,
|
||||
{
|
||||
int? position,
|
||||
UnsignedInt? limit,
|
||||
Set<Comparator>? sort,
|
||||
Filter? filter,
|
||||
Properties? properties
|
||||
}
|
||||
) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EmailChangeResponse> getChanges(
|
||||
AccountId accountId,
|
||||
State sinceState,
|
||||
{
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated
|
||||
}
|
||||
) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Email>> getAllEmailCache({MailboxId? inMailboxId, Set<Comparator>? sort}) {
|
||||
return Future.sync(() async {
|
||||
return await _emailCacheManager.getAllEmail(inMailboxId: inMailboxId, sort: sort);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update({List<Email>? updated, List<Email>? created, List<EmailId>? destroyed}) {
|
||||
return Future.sync(() async {
|
||||
return await _emailCacheManager.update(updated: updated, created: created, destroyed: destroyed);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,13 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
|
||||
|
||||
class ThreadDataSourceImpl extends ThreadDataSource {
|
||||
@@ -14,14 +18,17 @@ class ThreadDataSourceImpl extends ThreadDataSource {
|
||||
ThreadDataSourceImpl(this.threadAPI);
|
||||
|
||||
@override
|
||||
Future<List<Email>> getAllEmail(
|
||||
Future<EmailResponse> getAllEmail(
|
||||
AccountId accountId,
|
||||
{
|
||||
int? position,
|
||||
UnsignedInt? limit,
|
||||
Set<Comparator>? sort,
|
||||
Filter? filter,
|
||||
Properties? properties
|
||||
Properties? properties,
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated,
|
||||
MailboxId? inMailboxId
|
||||
}
|
||||
) {
|
||||
return Future.sync(() async {
|
||||
@@ -36,4 +43,34 @@ class ThreadDataSourceImpl extends ThreadDataSource {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EmailChangeResponse> getChanges(
|
||||
AccountId accountId,
|
||||
State sinceState,
|
||||
{
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated
|
||||
}
|
||||
) {
|
||||
return Future.sync(() async {
|
||||
return await threadAPI.getChanges(
|
||||
accountId,
|
||||
sinceState,
|
||||
propertiesCreated: propertiesCreated,
|
||||
propertiesUpdated: propertiesUpdated);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Email>> getAllEmailCache({MailboxId? inMailboxId, Set<Comparator>? sort}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update({List<Email>? updated, List<Email>? created, List<EmailId>? destroyed}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_address_hive_cache.dart';
|
||||
|
||||
extension EmailAddressHiveCacheExtension on EmailAddressHiveCache {
|
||||
|
||||
EmailAddress toEmailAddress() => EmailAddress(name, email);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/email_address_hive_cache_extension.dart';
|
||||
|
||||
extension EmailCacheExtension on EmailCache {
|
||||
Email toEmail() {
|
||||
return Email(
|
||||
EmailId(Id(id)),
|
||||
keywords: keywords != null
|
||||
? Map.fromIterables(keywords!.keys.map((value) => KeyWordIdentifier(value)), keywords!.values)
|
||||
: null,
|
||||
size: size != null ? UnsignedInt(size!) : null,
|
||||
receivedAt: receivedAt != null ? UTCDate(receivedAt!) : null,
|
||||
hasAttachment: hasAttachment,
|
||||
preview: preview,
|
||||
subject: subject,
|
||||
sentAt: sentAt != null ? UTCDate(sentAt!) : null,
|
||||
from: from?.map((emailAddressCache) => emailAddressCache.toEmailAddress()).toSet(),
|
||||
to: to?.map((emailAddressCache) => emailAddressCache.toEmailAddress()).toSet(),
|
||||
cc: cc?.map((emailAddressCache) => emailAddressCache.toEmailAddress()).toSet(),
|
||||
bcc: bcc?.map((emailAddressCache) => emailAddressCache.toEmailAddress()).toSet(),
|
||||
replyTo: replyTo?.map((emailAddressCache) => emailAddressCache.toEmailAddress()).toSet(),
|
||||
mailboxIds: mailboxIds != null
|
||||
? Map.fromIterables(mailboxIds!.keys.map((value) => MailboxId(Id(value))), mailboxIds!.values)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,13 @@ import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/map_keywords_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/map_mailbox_id_extension.dart';
|
||||
|
||||
extension EmailExtension on Email {
|
||||
|
||||
EmailCache toEmailCache() {
|
||||
return EmailCache(
|
||||
id.toString(),
|
||||
id.id.value,
|
||||
keywords: keywords?.toMapString(),
|
||||
size: size?.value.round(),
|
||||
receivedAt: receivedAt?.value,
|
||||
@@ -20,6 +21,7 @@ extension EmailExtension on Email {
|
||||
cc: cc?.map((emailAddress) => emailAddress.toEmailAddressHiveCache()).toList(),
|
||||
bcc: bcc?.map((emailAddress) => emailAddress.toEmailAddressHiveCache()).toList(),
|
||||
replyTo: replyTo?.map((emailAddress) => emailAddress.toEmailAddressHiveCache()).toList(),
|
||||
mailboxIds: mailboxIds?.toMapString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
|
||||
|
||||
extension ListEmailCacheExtension on List<EmailCache> {
|
||||
Map<String, EmailCache> toMap() {
|
||||
return Map<String, EmailCache>.fromIterable(
|
||||
this,
|
||||
key: (emailCache) => emailCache.id,
|
||||
value: (emailCache) => emailCache);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
|
||||
extension MapMailboxIdExtension on Map<MailboxId, bool> {
|
||||
|
||||
Map<String, bool> toMapString() => Map.fromIterables(keys.map((mailboxId) => mailboxId.id.value), values);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
import 'package:model/model.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/caching/email_cache_client.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/email_cache_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/extensions/list_email_cache_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
|
||||
class EmailCacheManager {
|
||||
|
||||
final EmailCacheClient _emailCacheClient;
|
||||
|
||||
EmailCacheManager(this._emailCacheClient);
|
||||
|
||||
Future<List<Email>> getAllEmail({MailboxId? inMailboxId, Set<Comparator>? sort}) async {
|
||||
final emailCacheList = inMailboxId != null
|
||||
? await _emailCacheClient.getListEmailCacheByMailboxId(inMailboxId)
|
||||
: await _emailCacheClient.getAll();
|
||||
final emailList = emailCacheList.map((emailCache) => emailCache.toEmail()).toList();
|
||||
if (sort != null) {
|
||||
sort.forEach((comparator) {
|
||||
emailList.sortBy(comparator);
|
||||
});
|
||||
}
|
||||
return emailList;
|
||||
}
|
||||
|
||||
Future<void> update({List<Email>? updated, List<Email>? created, List<EmailId>? destroyed}) async {
|
||||
final emailCacheExist = await _emailCacheClient.isExistTable();
|
||||
if (emailCacheExist) {
|
||||
final updatedCacheEmails = updated
|
||||
?.map((email) => email.toEmailCache()).toList() ?? <EmailCache>[];
|
||||
final createdCacheEmails = created
|
||||
?.map((email) => email.toEmailCache()).toList() ?? <EmailCache>[];
|
||||
final destroyedCacheEmails = destroyed
|
||||
?.map((emailId) => emailId.id.value).toList() ?? <String>[];
|
||||
await Future.wait([
|
||||
_emailCacheClient.updateMultipleItem(updatedCacheEmails.toMap()),
|
||||
_emailCacheClient.insertMultipleItem(createdCacheEmails.toMap()),
|
||||
_emailCacheClient.deleteMultipleItem(destroyedCacheEmails)
|
||||
]);
|
||||
} else {
|
||||
final createdCacheEmails = created
|
||||
?.map((email) => email.toEmailCache()).toList() ?? <EmailCache>[];
|
||||
await _emailCacheClient.insertMultipleItem(createdCacheEmails.toMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -48,6 +48,9 @@ class EmailCache extends HiveObject with EquatableMixin {
|
||||
@HiveField(12)
|
||||
final List<EmailAddressHiveCache>? replyTo;
|
||||
|
||||
@HiveField(13)
|
||||
Map<String, bool>? mailboxIds;
|
||||
|
||||
EmailCache(
|
||||
this.id,
|
||||
{
|
||||
@@ -63,6 +66,7 @@ class EmailCache extends HiveObject with EquatableMixin {
|
||||
this.cc,
|
||||
this.bcc,
|
||||
this.replyTo,
|
||||
this.mailboxIds,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -80,6 +84,7 @@ class EmailCache extends HiveObject with EquatableMixin {
|
||||
sentAt,
|
||||
replyTo,
|
||||
preview,
|
||||
hasAttachment
|
||||
hasAttachment,
|
||||
mailboxIds,
|
||||
];
|
||||
}
|
||||
@@ -30,13 +30,14 @@ class EmailCacheAdapter extends TypeAdapter<EmailCache> {
|
||||
cc: (fields[10] as List?)?.cast<EmailAddressHiveCache>(),
|
||||
bcc: (fields[11] as List?)?.cast<EmailAddressHiveCache>(),
|
||||
replyTo: (fields[12] as List?)?.cast<EmailAddressHiveCache>(),
|
||||
mailboxIds: (fields[13] as Map?)?.cast<String, bool>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, EmailCache obj) {
|
||||
writer
|
||||
..writeByte(13)
|
||||
..writeByte(14)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
@@ -62,7 +63,9 @@ class EmailCacheAdapter extends TypeAdapter<EmailCache> {
|
||||
..writeByte(11)
|
||||
..write(obj.bcc)
|
||||
..writeByte(12)
|
||||
..write(obj.replyTo);
|
||||
..write(obj.replyTo)
|
||||
..writeByte(13)
|
||||
..write(obj.mailboxIds);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
import 'package:model/model.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
|
||||
class EmailChangeResponse with EquatableMixin {
|
||||
final List<Email>? updated;
|
||||
final List<Email>? created;
|
||||
final List<EmailId>? destroyed;
|
||||
final State? newStateEmail;
|
||||
final State? newStateChanges;
|
||||
final bool hasMoreChanges;
|
||||
final Properties? updatedProperties;
|
||||
|
||||
EmailChangeResponse({
|
||||
this.updated,
|
||||
this.created,
|
||||
this.destroyed,
|
||||
this.newStateEmail,
|
||||
this.newStateChanges,
|
||||
this.hasMoreChanges = false,
|
||||
this.updatedProperties,
|
||||
});
|
||||
|
||||
EmailChangeResponse union(EmailChangeResponse other) => EmailChangeResponse(
|
||||
updated: updated.union(other.updated),
|
||||
created: created.union(other.created),
|
||||
destroyed: destroyed.union(other.destroyed),
|
||||
newStateEmail: other.newStateEmail,
|
||||
newStateChanges: other.newStateChanges,
|
||||
hasMoreChanges: other.hasMoreChanges,
|
||||
updatedProperties: other.updatedProperties,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
updated,
|
||||
created,
|
||||
destroyed,
|
||||
newStateEmail,
|
||||
newStateChanges,
|
||||
hasMoreChanges,
|
||||
updatedProperties
|
||||
];
|
||||
}
|
||||
@@ -6,12 +6,17 @@ import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/request/reference_path.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/jmap_request.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/changes/changes_email_method.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/changes/changes_email_response.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/get/get_email_method.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/get/get_email_response.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/query/query_email_method.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||
|
||||
class ThreadAPI {
|
||||
|
||||
@@ -19,7 +24,7 @@ class ThreadAPI {
|
||||
|
||||
ThreadAPI(this.httpClient);
|
||||
|
||||
Future<List<Email>> getAllEmail(
|
||||
Future<EmailResponse> getAllEmail(
|
||||
AccountId accountId,
|
||||
{
|
||||
int? position,
|
||||
@@ -69,6 +74,72 @@ class ThreadAPI {
|
||||
});
|
||||
}
|
||||
|
||||
return resultList == null ? [] : resultList.list;
|
||||
return EmailResponse(emailList: resultList?.list, state: resultList?.state);
|
||||
}
|
||||
|
||||
Future<EmailChangeResponse> getChanges(
|
||||
AccountId accountId,
|
||||
State sinceState,
|
||||
{
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated
|
||||
}
|
||||
) async {
|
||||
final processingInvocation = ProcessingInvocation();
|
||||
|
||||
final jmapRequestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
|
||||
|
||||
final changesEmailMethod = ChangesEmailMethod(accountId, sinceState, maxChanges: UnsignedInt(128));
|
||||
|
||||
final changesEmailInvocation = jmapRequestBuilder.invocation(changesEmailMethod);
|
||||
|
||||
final getMailboxUpdated = GetEmailMethod(accountId)
|
||||
..addReferenceIds(processingInvocation.createResultReference(
|
||||
changesEmailInvocation.methodCallId,
|
||||
ReferencePath.updatedPath));
|
||||
|
||||
if (propertiesUpdated != null) {
|
||||
getMailboxUpdated..addProperties(propertiesUpdated);
|
||||
}
|
||||
|
||||
final getEmailCreated = GetEmailMethod(accountId)
|
||||
..addReferenceIds(processingInvocation.createResultReference(
|
||||
changesEmailInvocation.methodCallId,
|
||||
ReferencePath.createdPath));
|
||||
|
||||
if (propertiesCreated != null) {
|
||||
getEmailCreated..addProperties(propertiesCreated);
|
||||
}
|
||||
|
||||
final getEmailUpdatedInvocation = jmapRequestBuilder.invocation(getMailboxUpdated);
|
||||
final getEmailCreatedInvocation = jmapRequestBuilder.invocation(getEmailCreated);
|
||||
|
||||
final result = await (jmapRequestBuilder
|
||||
..usings(getEmailCreated.requiredCapabilities))
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
final resultChanges = result.parse<ChangesEmailResponse>(
|
||||
changesEmailInvocation.methodCallId,
|
||||
ChangesEmailResponse.deserialize);
|
||||
|
||||
final resultUpdated = result.parse<GetEmailResponse>(
|
||||
getEmailUpdatedInvocation.methodCallId,
|
||||
GetEmailResponse.deserialize);
|
||||
|
||||
final resultCreated = result.parse<GetEmailResponse>(
|
||||
getEmailCreatedInvocation.methodCallId,
|
||||
GetEmailResponse.deserialize);
|
||||
|
||||
final listMailboxIdDestroyed = resultChanges?.destroyed.map((id) => EmailId(id)).toList() ?? <EmailId>[];
|
||||
|
||||
return EmailChangeResponse(
|
||||
updated: resultUpdated?.list,
|
||||
created: resultCreated?.list,
|
||||
destroyed: listMailboxIdDestroyed,
|
||||
newStateEmail: resultUpdated?.state,
|
||||
newStateChanges: resultChanges?.newState,
|
||||
hasMoreChanges: resultChanges?.hasMoreChanges ?? false,
|
||||
updatedProperties: propertiesUpdated);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,163 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/extensions/state_extension.dart';
|
||||
|
||||
class ThreadRepositoryImpl extends ThreadRepository {
|
||||
|
||||
final ThreadDataSource threadDataSource;
|
||||
final Map<DataSourceType, ThreadDataSource> mapDataSource;
|
||||
final StateDataSource stateDataSource;
|
||||
|
||||
ThreadRepositoryImpl(this.threadDataSource);
|
||||
ThreadRepositoryImpl(this.mapDataSource, this.stateDataSource);
|
||||
|
||||
@override
|
||||
Future<List<Email>> getAllEmail(
|
||||
Stream<EmailResponse> getAllEmail(
|
||||
AccountId accountId,
|
||||
{
|
||||
int? position,
|
||||
UnsignedInt? limit,
|
||||
Set<Comparator>? sort,
|
||||
Filter? filter,
|
||||
Properties? properties
|
||||
Properties? propertiesCreated,
|
||||
Properties? propertiesUpdated,
|
||||
MailboxId? inMailboxId
|
||||
}
|
||||
) {
|
||||
return threadDataSource.getAllEmail(
|
||||
accountId,
|
||||
position: position,
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
filter: filter,
|
||||
properties: properties
|
||||
);
|
||||
) async* {
|
||||
final localEmailResponse = await Future.wait([
|
||||
mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort),
|
||||
stateDataSource.getState(StateType.email)
|
||||
]).then((List response) {
|
||||
return EmailResponse(emailList: response.first, state: response.last);
|
||||
});
|
||||
|
||||
EmailResponse? networkEmailResponse;
|
||||
|
||||
if (!localEmailResponse.hasEmails()) {
|
||||
networkEmailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail(
|
||||
accountId,
|
||||
position: position,
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
filter: filter,
|
||||
properties: propertiesCreated);
|
||||
|
||||
yield networkEmailResponse;
|
||||
} else {
|
||||
yield localEmailResponse;
|
||||
}
|
||||
|
||||
if (localEmailResponse.hasState()) {
|
||||
EmailChangeResponse? emailChangeResponse;
|
||||
bool hasMoreChanges = true;
|
||||
State? sinceState = localEmailResponse.state!;
|
||||
|
||||
while(hasMoreChanges && sinceState != null) {
|
||||
final changesResponse = await mapDataSource[DataSourceType.network]!.getChanges(
|
||||
accountId,
|
||||
sinceState,
|
||||
propertiesCreated: propertiesCreated,
|
||||
propertiesUpdated: propertiesUpdated);
|
||||
|
||||
hasMoreChanges = changesResponse.hasMoreChanges;
|
||||
sinceState = changesResponse.newStateChanges;
|
||||
|
||||
if (emailChangeResponse != null) {
|
||||
emailChangeResponse.union(changesResponse);
|
||||
} else {
|
||||
emailChangeResponse = changesResponse;
|
||||
}
|
||||
}
|
||||
|
||||
final totalEmails = networkEmailResponse != null
|
||||
? networkEmailResponse.emailList
|
||||
: localEmailResponse.emailList;
|
||||
|
||||
final newEmailUpdated = await _combineEmailCache(
|
||||
emailUpdated: emailChangeResponse?.updated,
|
||||
updatedProperties: emailChangeResponse?.updatedProperties,
|
||||
emailCacheList: totalEmails);
|
||||
|
||||
final newEmailCreated = networkEmailResponse != null
|
||||
? networkEmailResponse.emailList
|
||||
: emailChangeResponse?.created;
|
||||
|
||||
await _updateEmailCache(
|
||||
newCreated: newEmailCreated,
|
||||
newUpdated: newEmailUpdated,
|
||||
newDestroyed: emailChangeResponse?.destroyed);
|
||||
|
||||
if (emailChangeResponse != null && emailChangeResponse.newStateEmail != null) {
|
||||
await _updateState(emailChangeResponse.newStateEmail!);
|
||||
}
|
||||
} else {
|
||||
if (networkEmailResponse != null) {
|
||||
await _updateEmailCache(newCreated: networkEmailResponse.emailList);
|
||||
if (networkEmailResponse.state != null) {
|
||||
await _updateState(networkEmailResponse.state!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final newEmailResponse = await Future.wait([
|
||||
mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort),
|
||||
stateDataSource.getState(StateType.email)
|
||||
]).then((List response) {
|
||||
return EmailResponse(emailList: response.first, state: response.last);
|
||||
});
|
||||
|
||||
yield newEmailResponse;
|
||||
}
|
||||
|
||||
Future<List<Email>?> _combineEmailCache({
|
||||
List<Email>? emailUpdated,
|
||||
Properties? updatedProperties,
|
||||
List<Email>? emailCacheList
|
||||
}) async {
|
||||
if (emailUpdated != null && emailUpdated.isNotEmpty) {
|
||||
final newEmailUpdated = emailUpdated.map((email) {
|
||||
if (updatedProperties == null) {
|
||||
return email;
|
||||
} else {
|
||||
final emailOld = emailCacheList?.findEmail(email.id);
|
||||
if (emailOld != null) {
|
||||
return emailOld.combineEmail(email, updatedProperties);
|
||||
} else {
|
||||
return email;
|
||||
}
|
||||
}
|
||||
}).toList();
|
||||
|
||||
return newEmailUpdated;
|
||||
}
|
||||
return emailUpdated;
|
||||
}
|
||||
|
||||
Future<void> _updateEmailCache({
|
||||
List<Email>? newUpdated,
|
||||
List<Email>? newCreated,
|
||||
List<EmailId>? newDestroyed
|
||||
}) async {
|
||||
await mapDataSource[DataSourceType.local]!.update(
|
||||
updated: newUpdated,
|
||||
created: newCreated,
|
||||
destroyed: newDestroyed);
|
||||
}
|
||||
|
||||
Future<void> _updateState(State newState) async {
|
||||
await stateDataSource.saveState(newState.toStateCache(StateType.email));
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
||||
import 'package:tmail_ui_user/features/caching/email_cache_client.dart';
|
||||
import 'package:tmail_ui_user/features/caching/mailbox_cache_client.dart';
|
||||
import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart';
|
||||
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
|
||||
|
||||
class LocalBindings extends Bindings {
|
||||
|
||||
@@ -25,5 +27,7 @@ class LocalBindings extends Bindings {
|
||||
Get.put(CachingManager(
|
||||
Get.find<MailboxCacheClient>(),
|
||||
Get.find<StateCacheClient>()));
|
||||
Get.put(EmailCacheClient());
|
||||
Get.put(EmailCacheManager(Get.find<EmailCacheClient>()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user