From 3cac5e4e83a63a602d593b3b71421577b0cf602a Mon Sep 17 00:00:00 2001 From: dab246 Date: Thu, 7 Oct 2021 15:01:23 +0700 Subject: [PATCH] TF-145 Add domain layer for getAllEmail in Caching --- .../domain/constants/thread_constants.dart | 22 +++++++++++ .../thread/domain/model/email_response.dart | 21 ++++++++++ .../domain/repository/thread_repository.dart | 9 +++-- .../domain/state/get_all_email_state.dart | 6 ++- .../get_emails_in_mailbox_interactor.dart | 39 +++++++++++++------ model/lib/email/email_property.dart | 17 ++++++++ model/lib/extensions/email_extension.dart | 21 ++++++++++ .../lib/extensions/list_email_extension.dart | 35 +++++++++++++++++ model/lib/extensions/list_extension.dart | 10 +++++ model/lib/model.dart | 3 ++ 10 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 lib/features/thread/domain/model/email_response.dart create mode 100644 model/lib/email/email_property.dart create mode 100644 model/lib/extensions/list_email_extension.dart create mode 100644 model/lib/extensions/list_extension.dart diff --git a/lib/features/thread/domain/constants/thread_constants.dart b/lib/features/thread/domain/constants/thread_constants.dart index 6568ef856..3cfc46910 100644 --- a/lib/features/thread/domain/constants/thread_constants.dart +++ b/lib/features/thread/domain/constants/thread_constants.dart @@ -1,5 +1,27 @@ +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; +import 'package:model/email/email_property.dart'; class ThreadConstants { static final defaultLimit = UnsignedInt(20); + static final propertiesDefault = Properties({ + EmailProperty.id, + EmailProperty.subject, + EmailProperty.from, + EmailProperty.to, + EmailProperty.cc, + EmailProperty.bcc, + EmailProperty.keywords, + EmailProperty.size, + EmailProperty.receivedAt, + EmailProperty.sentAt, + EmailProperty.preview, + EmailProperty.hasAttachment, + EmailProperty.replyTo, + EmailProperty.mailboxIds, + }); + static final propertiesUpdatedDefault = Properties({ + EmailProperty.keywords, + EmailProperty.mailboxIds, + }); } \ No newline at end of file diff --git a/lib/features/thread/domain/model/email_response.dart b/lib/features/thread/domain/model/email_response.dart new file mode 100644 index 000000000..e4681b022 --- /dev/null +++ b/lib/features/thread/domain/model/email_response.dart @@ -0,0 +1,21 @@ + +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; + +class EmailResponse with EquatableMixin { + final List? emailList; + final State? state; + + EmailResponse({ + this.emailList, + this.state + }); + + bool hasEmails() => emailList != null && emailList!.isNotEmpty; + + bool hasState() => state != null; + + @override + List get props => [emailList, state]; +} \ No newline at end of file diff --git a/lib/features/thread/domain/repository/thread_repository.dart b/lib/features/thread/domain/repository/thread_repository.dart index 1e7b8a5b2..91b9f3ec9 100644 --- a/lib/features/thread/domain/repository/thread_repository.dart +++ b/lib/features/thread/domain/repository/thread_repository.dart @@ -3,17 +3,20 @@ 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/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/domain/model/email_response.dart'; abstract class ThreadRepository { - Future> getAllEmail( + Stream getAllEmail( AccountId accountId, { int? position, UnsignedInt? limit, Set? sort, Filter? filter, - Properties? properties + Properties? propertiesCreated, + Properties? propertiesUpdated, + MailboxId? inMailboxId } ); } \ No newline at end of file diff --git a/lib/features/thread/domain/state/get_all_email_state.dart b/lib/features/thread/domain/state/get_all_email_state.dart index fb1e7be9a..da69af096 100644 --- a/lib/features/thread/domain/state/get_all_email_state.dart +++ b/lib/features/thread/domain/state/get_all_email_state.dart @@ -1,13 +1,15 @@ import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:model/model.dart'; class GetAllEmailSuccess extends UIState { final List emailList; + final State? currentEmailState; - GetAllEmailSuccess(this.emailList); + GetAllEmailSuccess({required this.emailList, this.currentEmailState}); @override - List get props => [emailList]; + List get props => [emailList, currentEmailState]; } class GetAllEmailFailure extends FeatureFailure { diff --git a/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart b/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart index ee9aab0ce..1e825843e 100644 --- a/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart +++ b/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart @@ -1,13 +1,15 @@ import 'package:core/core.dart'; -import 'package:model/model.dart'; import 'package:dartz/dartz.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/unsigned_int.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.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/thread/domain/state/get_all_email_state.dart'; +import 'package:model/model.dart'; class GetEmailsInMailboxInteractor { final ThreadRepository threadRepository; @@ -21,23 +23,36 @@ class GetEmailsInMailboxInteractor { UnsignedInt? limit, Set? sort, Filter? filter, - Properties? properties + Properties? propertiesCreated, + Properties? propertiesUpdated, + MailboxId? inMailboxId } ) async* { try { yield Right(LoadingState()); - final emailList = await threadRepository.getAllEmail( - accountId, - position: position, - limit: limit, - sort: sort, - filter: filter, - properties: properties - ); - final presentationEmailList = emailList.map((email) => email.toPresentationEmail()).toList(); - yield Right(GetAllEmailSuccess(presentationEmailList)); + + yield* threadRepository + .getAllEmail( + accountId, + position: position, + limit: limit, + sort: sort, + filter: filter, + propertiesCreated: propertiesCreated, + propertiesUpdated: propertiesUpdated, + inMailboxId: inMailboxId) + .map(_toGetEmailState); } catch (e) { yield Left(GetAllEmailFailure(e)); } } + + Either _toGetEmailState(EmailResponse emailResponse) { + final presentationEmailList = emailResponse.emailList + ?.map((email) => email.toPresentationEmail()).toList() ?? List.empty(); + + return Right(GetAllEmailSuccess( + emailList: presentationEmailList, + currentEmailState: emailResponse.state)); + } } \ No newline at end of file diff --git a/model/lib/email/email_property.dart b/model/lib/email/email_property.dart new file mode 100644 index 000000000..03359299b --- /dev/null +++ b/model/lib/email/email_property.dart @@ -0,0 +1,17 @@ + +class EmailProperty { + static const String id = 'id'; + static const String keywords = 'keywords'; + static const String size = 'size'; + static const String receivedAt = 'receivedAt'; + static const String hasAttachment = 'hasAttachment'; + static const String preview = 'preview'; + static const String subject = 'subject'; + static const String sentAt = 'sentAt'; + static const String from = 'from'; + static const String to = 'to'; + static const String cc = 'cc'; + static const String bcc = 'bcc'; + static const String replyTo = 'replyTo'; + static const String mailboxIds = 'mailboxIds'; +} \ No newline at end of file diff --git a/model/lib/extensions/email_extension.dart b/model/lib/extensions/email_extension.dart index b7d2bc1ea..86369ef24 100644 --- a/model/lib/extensions/email_extension.dart +++ b/model/lib/extensions/email_extension.dart @@ -1,6 +1,8 @@ +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; +import 'package:model/email/email_property.dart'; import 'package:model/model.dart'; extension EmailExtension on Email { @@ -65,4 +67,23 @@ extension EmailExtension on Email { selectMode: selectMode ); } + + Email combineEmail(Email newEmail, Properties updatedProperties) { + return Email( + newEmail.id, + keywords: updatedProperties.contain(EmailProperty.keywords) ? newEmail.keywords : keywords, + size: updatedProperties.contain(EmailProperty.size) ? newEmail.size : size, + receivedAt: updatedProperties.contain(EmailProperty.receivedAt) ? newEmail.receivedAt : receivedAt, + hasAttachment: updatedProperties.contain(EmailProperty.hasAttachment) ? newEmail.hasAttachment : hasAttachment, + preview: updatedProperties.contain(EmailProperty.preview) ? newEmail.preview : preview, + subject: updatedProperties.contain(EmailProperty.subject) ? newEmail.subject : subject, + sentAt: updatedProperties.contain(EmailProperty.sentAt) ? newEmail.sentAt : sentAt, + from: updatedProperties.contain(EmailProperty.from) ? newEmail.from : from, + to: updatedProperties.contain(EmailProperty.to) ? newEmail.to : to, + cc: updatedProperties.contain(EmailProperty.cc) ? newEmail.cc : cc, + bcc: updatedProperties.contain(EmailProperty.bcc) ? newEmail.bcc : bcc, + replyTo: updatedProperties.contain(EmailProperty.replyTo) ? newEmail.replyTo : replyTo, + mailboxIds: updatedProperties.contain(EmailProperty.mailboxIds) ? newEmail.mailboxIds : mailboxIds, + ); + } } \ No newline at end of file diff --git a/model/lib/extensions/list_email_extension.dart b/model/lib/extensions/list_email_extension.dart new file mode 100644 index 000000000..fc887ca3a --- /dev/null +++ b/model/lib/extensions/list_email_extension.dart @@ -0,0 +1,35 @@ + +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:jmap_dart_client/jmap/core/sort/comparator.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart'; +import 'package:jmap_dart_client/jmap/core/extensions/utc_date_extension.dart'; +import 'package:jmap_dart_client/jmap/core/extensions/string_extension.dart'; +import 'package:jmap_dart_client/jmap/core/extensions/unsigned_int_extension.dart'; + +extension ListEmailExtension on List { + + Email? findEmail(EmailId emailId) { + try { + return firstWhere((email) => email.id == emailId); + } catch (e) { + return null; + } + } + + void sortBy(Comparator comparator) { + sort((email1, email2) { + if (comparator.property == EmailComparatorProperty.sentAt + || comparator.property == EmailComparatorProperty.receivedAt) { + final emailTime1 = email1.sentAt ?? email1.receivedAt; + final emailTime2 = email2.sentAt ?? email2.receivedAt; + return emailTime1.compareToSort(emailTime2, comparator.isAscending); + } if (comparator.property == EmailComparatorProperty.subject) { + return email1.subject.compareToSort(email2.subject, comparator.isAscending); + } if (comparator.property == EmailComparatorProperty.size) { + return email1.size.compareToSort(email2.size, comparator.isAscending); + } else { + return 0; + } + }); + } +} \ No newline at end of file diff --git a/model/lib/extensions/list_extension.dart b/model/lib/extensions/list_extension.dart new file mode 100644 index 000000000..4ff837340 --- /dev/null +++ b/model/lib/extensions/list_extension.dart @@ -0,0 +1,10 @@ + +extension ListExtension on List? { + + List? union(List? other) { + if (other != null) { + this?.addAll(other); + } + return this; + } +} \ No newline at end of file diff --git a/model/lib/model.dart b/model/lib/model.dart index db70ffed1..c6a8494ab 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -27,6 +27,7 @@ export 'email/read_actions.dart'; export 'email/attachment.dart'; export 'email/move_action.dart'; export 'email/mark_star_action.dart'; +export 'email/email_property.dart'; // Extensions export 'extensions/email_address_extension.dart'; @@ -46,6 +47,8 @@ export 'extensions/mailbox_extension.dart'; export 'extensions/mailbox_name_extension.dart'; export 'extensions/properties_extension.dart'; export 'extensions/list_mailbox_extension.dart'; +export 'extensions/list_extension.dart'; +export 'extensions/list_email_extension.dart'; // Download export 'download/download_task_id.dart';