TF-145 Implement LoadMoreEmails in ThreadView

This commit is contained in:
dab246
2021-10-07 17:41:31 +07:00
committed by Dat H. Pham
parent 1224173fa0
commit ee58a77758
29 changed files with 337 additions and 173 deletions
+14
View File
@@ -16,6 +16,20 @@ class UIState extends ViewState {
class LoadingState extends UIState { class LoadingState extends UIState {
LoadingState(); LoadingState();
@override
List<Object?> get props => [];
}
class LoadingMoreState extends UIState {
LoadingMoreState();
@override
List<Object?> get props => [];
}
class RefreshingState extends UIState {
RefreshingState();
@override @override
List<Object?> get props => []; List<Object?> get props => [];
} }
+8 -1
View File
@@ -1,4 +1,5 @@
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/mailbox_cache_client.dart';
import 'package:tmail_ui_user/features/caching/state_cache_client.dart'; import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
@@ -6,13 +7,19 @@ class CachingManager {
final MailboxCacheClient _mailboxCacheClient; final MailboxCacheClient _mailboxCacheClient;
final StateCacheClient _stateCacheClient; final StateCacheClient _stateCacheClient;
final EmailCacheClient _emailCacheClient;
CachingManager(this._mailboxCacheClient, this._stateCacheClient); CachingManager(
this._mailboxCacheClient,
this._stateCacheClient,
this._emailCacheClient
);
Future<void> clearAll() async { Future<void> clearAll() async {
await Future.wait([ await Future.wait([
_stateCacheClient.deleteBox(), _stateCacheClient.deleteBox(),
_mailboxCacheClient.deleteBox(), _mailboxCacheClient.deleteBox(),
_emailCacheClient.deleteBox(),
]); ]);
} }
} }
@@ -15,6 +15,8 @@ class RefreshAllMailboxInteractor {
Stream<Either<Failure, Success>> execute(AccountId accountId, jmapState.State currentState) async* { Stream<Either<Failure, Success>> execute(AccountId accountId, jmapState.State currentState) async* {
try { try {
yield Right<Failure, Success>(RefreshingState());
yield* _mailboxRepository yield* _mailboxRepository
.refresh(accountId, currentState) .refresh(accountId, currentState)
.map(_toGetMailboxState); .map(_toGetMailboxState);
@@ -10,10 +10,9 @@ import 'package:tmail_ui_user/features/thread/data/model/email_change_response.d
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
abstract class ThreadDataSource { abstract class ThreadDataSource {
Future<EmailResponse> getAllEmail( Future<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, Filter? filter,
@@ -18,10 +18,9 @@ class LocalThreadDataSourceImpl extends ThreadDataSource {
LocalThreadDataSourceImpl(this._emailCacheManager); LocalThreadDataSourceImpl(this._emailCacheManager);
@override @override
Future<EmailResponse> getAllEmail( Future<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, Filter? filter,
@@ -18,23 +18,18 @@ class ThreadDataSourceImpl extends ThreadDataSource {
ThreadDataSourceImpl(this.threadAPI); ThreadDataSourceImpl(this.threadAPI);
@override @override
Future<EmailResponse> getAllEmail( Future<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, Filter? filter,
Properties? properties, Properties? properties,
Properties? propertiesCreated,
Properties? propertiesUpdated,
MailboxId? inMailboxId
} }
) { ) {
return Future.sync(() async { return Future.sync(() async {
return await threadAPI.getAllEmail( return await threadAPI.getAllEmail(
accountId, accountId,
position: position,
limit: limit, limit: limit,
sort: sort, sort: sort,
filter: filter, filter: filter,
@@ -65,7 +60,7 @@ class ThreadDataSourceImpl extends ThreadDataSource {
} }
@override @override
Future<List<Email>> getAllEmailCache({MailboxId? inMailboxId, Set<Comparator>? sort}) { Future<List<Email>> getAllEmailCache({MailboxId? inMailboxId, Set<Comparator>? sort, UnsignedInt? limit}) {
throw UnimplementedError(); throw UnimplementedError();
} }
@@ -25,9 +25,9 @@ class EmailChangeResponse with EquatableMixin {
}); });
EmailChangeResponse union(EmailChangeResponse other) => EmailChangeResponse( EmailChangeResponse union(EmailChangeResponse other) => EmailChangeResponse(
updated: updated.union(other.updated), updated: updated.unite(other.updated),
created: created.union(other.created), created: created.unite(other.created),
destroyed: destroyed.union(other.destroyed), destroyed: destroyed.unite(other.destroyed),
newStateEmail: other.newStateEmail, newStateEmail: other.newStateEmail,
newStateChanges: other.newStateChanges, newStateChanges: other.newStateChanges,
hasMoreChanges: other.hasMoreChanges, hasMoreChanges: other.hasMoreChanges,
@@ -24,10 +24,9 @@ class ThreadAPI {
ThreadAPI(this.httpClient); ThreadAPI(this.httpClient);
Future<EmailResponse> getAllEmail( Future<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, Filter? filter,
@@ -40,8 +39,6 @@ class ThreadAPI {
final queryEmailMethod = QueryEmailMethod(accountId); final queryEmailMethod = QueryEmailMethod(accountId);
if (position != null) queryEmailMethod..addPosition(position);
if (limit != null) queryEmailMethod..addLimit(limit); if (limit != null) queryEmailMethod..addLimit(limit);
if (sort != null) queryEmailMethod..addSorts(sort); if (sort != null) queryEmailMethod..addSorts(sort);
@@ -74,7 +71,7 @@ class ThreadAPI {
}); });
} }
return EmailResponse(emailList: resultList?.list, state: resultList?.state); return EmailsResponse(emailList: resultList?.list, state: resultList?.state);
} }
Future<EmailChangeResponse> getChanges( Future<EmailChangeResponse> getChanges(
@@ -25,34 +25,31 @@ class ThreadRepositoryImpl extends ThreadRepository {
ThreadRepositoryImpl(this.mapDataSource, this.stateDataSource); ThreadRepositoryImpl(this.mapDataSource, this.stateDataSource);
@override @override
Stream<EmailResponse> getAllEmail( Stream<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, EmailFilter? emailFilter,
Properties? propertiesCreated, Properties? propertiesCreated,
Properties? propertiesUpdated, Properties? propertiesUpdated,
MailboxId? inMailboxId
} }
) async* { ) async* {
final localEmailResponse = await Future.wait([ final localEmailResponse = await Future.wait([
mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort), mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: emailFilter?.mailboxId, sort: sort),
stateDataSource.getState(StateType.email) stateDataSource.getState(StateType.email)
]).then((List response) { ]).then((List response) {
return EmailResponse(emailList: response.first, state: response.last); return EmailsResponse(emailList: response.first, state: response.last);
}); });
EmailResponse? networkEmailResponse; EmailsResponse? networkEmailResponse;
if (!localEmailResponse.hasEmails()) { if (!localEmailResponse.hasEmails()) {
networkEmailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail( networkEmailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail(
accountId, accountId,
position: position,
limit: limit, limit: limit,
sort: sort, sort: sort,
filter: filter, filter: emailFilter?.filter,
properties: propertiesCreated); properties: propertiesCreated);
yield networkEmailResponse; yield networkEmailResponse;
@@ -113,10 +110,10 @@ class ThreadRepositoryImpl extends ThreadRepository {
} }
final newEmailResponse = await Future.wait([ final newEmailResponse = await Future.wait([
mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort), mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: emailFilter?.mailboxId, sort: sort),
stateDataSource.getState(StateType.email) stateDataSource.getState(StateType.email)
]).then((List response) { ]).then((List response) {
return EmailResponse(emailList: response.first, state: response.last); return EmailsResponse(emailList: response.first, state: response.last);
}); });
yield newEmailResponse; yield newEmailResponse;
@@ -132,7 +129,7 @@ class ThreadRepositoryImpl extends ThreadRepository {
if (updatedProperties == null) { if (updatedProperties == null) {
return email; return email;
} else { } else {
final emailOld = emailCacheList?.findEmail(email.id); final emailOld = emailCacheList?.findEmailById(email.id);
if (emailOld != null) { if (emailOld != null) {
return emailOld.combineEmail(email, updatedProperties); return emailOld.combineEmail(email, updatedProperties);
} else { } else {
@@ -162,10 +159,11 @@ class ThreadRepositoryImpl extends ThreadRepository {
} }
@override @override
Stream<EmailResponse> refreshChanges( Stream<EmailsResponse> refreshChanges(
AccountId accountId, AccountId accountId,
State currentState, State currentState,
{ {
UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Properties? propertiesCreated, Properties? propertiesCreated,
Properties? propertiesUpdated, Properties? propertiesUpdated,
@@ -173,8 +171,8 @@ class ThreadRepositoryImpl extends ThreadRepository {
} }
) async* { ) async* {
final localEmailList = await mapDataSource[DataSourceType.local]!.getAllEmailCache( final localEmailList = await mapDataSource[DataSourceType.local]!.getAllEmailCache(
inMailboxId: inMailboxId, inMailboxId: inMailboxId,
sort: sort); sort: sort);
EmailChangeResponse? emailChangeResponse; EmailChangeResponse? emailChangeResponse;
bool hasMoreChanges = true; bool hasMoreChanges = true;
@@ -217,9 +215,38 @@ class ThreadRepositoryImpl extends ThreadRepository {
mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort), mapDataSource[DataSourceType.local]!.getAllEmailCache(inMailboxId: inMailboxId, sort: sort),
stateDataSource.getState(StateType.email) stateDataSource.getState(StateType.email)
]).then((List response) { ]).then((List response) {
return EmailResponse(emailList: response.first, state: response.last); return EmailsResponse(emailList: response.first, state: response.last);
}); });
yield newEmailResponse; yield newEmailResponse;
} }
@override
Stream<EmailsResponse> loadMoreEmails(
AccountId accountId,
{
int? position,
UnsignedInt? limit,
Set<Comparator>? sort,
Filter? filter,
Properties? properties,
}
) async* {
final emailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail(
accountId,
limit: limit,
sort: sort,
filter: filter,
properties: properties);
final newEmailList = emailResponse.emailList != null && emailResponse.emailList!.isNotEmpty
? emailResponse.emailList!.sublist(1)
: <Email>[];
if (newEmailList.isNotEmpty) {
await _updateEmailCache(newCreated: newEmailList);
}
yield EmailsResponse(emailList: newEmailList, state: emailResponse.state);
}
} }
@@ -3,11 +3,11 @@ import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
class EmailResponse with EquatableMixin { class EmailsResponse with EquatableMixin {
final List<Email>? emailList; final List<Email>? emailList;
final State? state; final State? state;
EmailResponse({ EmailsResponse({
this.emailList, this.emailList,
this.state this.state
}); });
@@ -5,23 +5,22 @@ import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
abstract class ThreadRepository { abstract class ThreadRepository {
Stream<EmailResponse> getAllEmail( Stream<EmailsResponse> getAllEmail(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, EmailFilter? emailFilter,
Properties? propertiesCreated, Properties? propertiesCreated,
Properties? propertiesUpdated, Properties? propertiesUpdated,
MailboxId? inMailboxId
} }
); );
Stream<EmailResponse> refreshChanges( Stream<EmailsResponse> refreshChanges(
AccountId accountId, AccountId accountId,
jmap.State currentState, jmap.State currentState,
{ {
@@ -31,4 +30,14 @@ abstract class ThreadRepository {
MailboxId? inMailboxId MailboxId? inMailboxId
} }
); );
Stream<EmailsResponse> loadMoreEmails(
AccountId accountId,
{
UnsignedInt? limit,
Set<Comparator>? sort,
Filter? filter,
Properties? properties,
}
);
} }
@@ -0,0 +1,20 @@
import 'package:core/core.dart';
import 'package:model/model.dart';
class LoadMoreEmailsSuccess extends UIState {
final List<PresentationEmail> emailList;
LoadMoreEmailsSuccess(this.emailList);
@override
List<Object?> get props => [emailList];
}
class LoadMoreEmailsFailure extends FeatureFailure {
final exception;
LoadMoreEmailsFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -1,11 +1,9 @@
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.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/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.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/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/model/email_response.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.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:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
@@ -19,13 +17,11 @@ class GetEmailsInMailboxInteractor {
Stream<Either<Failure, Success>> execute( Stream<Either<Failure, Success>> execute(
AccountId accountId, AccountId accountId,
{ {
int? position,
UnsignedInt? limit, UnsignedInt? limit,
Set<Comparator>? sort, Set<Comparator>? sort,
Filter? filter, EmailFilter? emailFilter,
Properties? propertiesCreated, Properties? propertiesCreated,
Properties? propertiesUpdated, Properties? propertiesUpdated,
MailboxId? inMailboxId
} }
) async* { ) async* {
try { try {
@@ -34,20 +30,18 @@ class GetEmailsInMailboxInteractor {
yield* threadRepository yield* threadRepository
.getAllEmail( .getAllEmail(
accountId, accountId,
position: position,
limit: limit, limit: limit,
sort: sort, sort: sort,
filter: filter, emailFilter: emailFilter,
propertiesCreated: propertiesCreated, propertiesCreated: propertiesCreated,
propertiesUpdated: propertiesUpdated, propertiesUpdated: propertiesUpdated)
inMailboxId: inMailboxId)
.map(_toGetEmailState); .map(_toGetEmailState);
} catch (e) { } catch (e) {
yield Left(GetAllEmailFailure(e)); yield Left(GetAllEmailFailure(e));
} }
} }
Either<Failure, Success> _toGetEmailState(EmailResponse emailResponse) { Either<Failure, Success> _toGetEmailState(EmailsResponse emailResponse) {
final presentationEmailList = emailResponse.emailList final presentationEmailList = emailResponse.emailList
?.map((email) => email.toPresentationEmail()).toList() ?? List.empty(); ?.map((email) => email.toPresentationEmail()).toList() ?? List.empty();
@@ -0,0 +1,49 @@
import 'package:core/core.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:tmail_ui_user/features/thread/domain/model/email_response.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/thread/domain/state/load_more_emails_state.dart';
class LoadMoreEmailsInMailboxInteractor {
final ThreadRepository threadRepository;
LoadMoreEmailsInMailboxInteractor(this.threadRepository);
Stream<Either<Failure, Success>> execute(
AccountId accountId,
{
UnsignedInt? limit,
Set<Comparator>? sort,
Filter? filter,
Properties? properties
}
) async* {
try {
yield Right<Failure, Success>(LoadingMoreState());
yield* threadRepository
.loadMoreEmails(
accountId,
limit: limit,
sort: sort,
filter: filter,
properties: properties)
.map(_toGetEmailState);
} catch (e) {
yield Left(LoadMoreEmailsFailure(e));
}
}
Either<Failure, Success> _toGetEmailState(EmailsResponse emailResponse) {
final presentationEmailList = emailResponse.emailList
?.map((email) => email.toPresentationEmail()).toList() ?? List.empty();
return Right<Failure, Success>(LoadMoreEmailsSuccess(presentationEmailList));
}
}
@@ -25,6 +25,8 @@ class RefreshChangesEmailsInMailboxInteractor {
MailboxId? inMailboxId MailboxId? inMailboxId
} }
) async* { ) async* {
yield Right<Failure, Success>(RefreshingState());
try { try {
yield* threadRepository yield* threadRepository
.refreshChanges( .refreshChanges(
@@ -40,7 +42,7 @@ class RefreshChangesEmailsInMailboxInteractor {
} }
} }
Either<Failure, Success> _toGetEmailState(EmailResponse emailResponse) { Either<Failure, Success> _toGetEmailState(EmailsResponse emailResponse) {
final presentationEmailList = emailResponse.emailList final presentationEmailList = emailResponse.emailList
?.map((email) => email.toPresentationEmail()).toList() ?? List.empty(); ?.map((email) => email.toPresentationEmail()).toList() ?? List.empty();
@@ -1,6 +0,0 @@
enum LoadMoreState {
IDLE,
LOADING,
COMPLETED
}
@@ -21,6 +21,7 @@ import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart'; import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart';
@@ -56,6 +57,7 @@ class ThreadBindings extends Bindings {
Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>())); Get.lazyPut(() => MarkAsStarEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => MarkAsStarMultipleEmailInteractor(Get.find<EmailRepository>())); Get.lazyPut(() => MarkAsStarMultipleEmailInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => RefreshChangesEmailsInMailboxInteractor(Get.find<ThreadRepository>())); Get.lazyPut(() => RefreshChangesEmailsInMailboxInteractor(Get.find<ThreadRepository>()));
Get.lazyPut(() => LoadMoreEmailsInMailboxInteractor(Get.find<ThreadRepository>()));
Get.put(ThreadController( Get.put(ThreadController(
Get.find<ResponsiveUtils>(), Get.find<ResponsiveUtils>(),
Get.find<GetEmailsInMailboxInteractor>(), Get.find<GetEmailsInMailboxInteractor>(),
@@ -66,6 +68,7 @@ class ThreadBindings extends Bindings {
Get.find<MarkAsStarEmailInteractor>(), Get.find<MarkAsStarEmailInteractor>(),
Get.find<MarkAsStarMultipleEmailInteractor>(), Get.find<MarkAsStarMultipleEmailInteractor>(),
Get.find<RefreshChangesEmailsInMailboxInteractor>(), Get.find<RefreshChangesEmailsInMailboxInteractor>(),
Get.find<LoadMoreEmailsInMailboxInteractor>(),
)); ));
} }
} }
@@ -22,15 +22,16 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/load_more_emails_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_email_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_star_multiple_email_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -48,13 +49,12 @@ class ThreadController extends BaseController {
final MarkAsStarEmailInteractor _markAsStarEmailInteractor; final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final MarkAsStarMultipleEmailInteractor _markAsStarMultipleEmailInteractor; final MarkAsStarMultipleEmailInteractor _markAsStarMultipleEmailInteractor;
final RefreshChangesEmailsInMailboxInteractor _refreshChangesEmailsInMailboxInteractor; final RefreshChangesEmailsInMailboxInteractor _refreshChangesEmailsInMailboxInteractor;
final LoadMoreEmailsInMailboxInteractor _loadMoreEmailsInMailboxInteractor;
final emailList = <PresentationEmail>[].obs; final emailList = <PresentationEmail>[].obs;
final loadMoreState = LoadMoreState.IDLE.obs;
final currentSelectMode = SelectMode.INACTIVE.obs; final currentSelectMode = SelectMode.INACTIVE.obs;
int _currentPosition = 0; bool canLoadMore = true;
int _totalNumberOfEmails = 0;
MailboxId? _currentMailboxId; MailboxId? _currentMailboxId;
jmap.State? _currentEmailState; jmap.State? _currentEmailState;
@@ -77,6 +77,7 @@ class ThreadController extends BaseController {
this._markAsStarEmailInteractor, this._markAsStarEmailInteractor,
this._markAsStarMultipleEmailInteractor, this._markAsStarMultipleEmailInteractor,
this._refreshChangesEmailsInMailboxInteractor, this._refreshChangesEmailsInMailboxInteractor,
this._loadMoreEmailsInMailboxInteractor,
); );
@override @override
@@ -122,20 +123,27 @@ class ThreadController extends BaseController {
@override @override
void onData(Either<Failure, Success> newState) { void onData(Either<Failure, Success> newState) {
super.onData(newState); super.onData(newState);
newState.map((success) { newState.fold(
if (success is GetAllEmailSuccess) { (failure) {
_getAllEmailSuccess(success); if (failure is LoadMoreEmailsFailure) {
canLoadMore = false;
}
},
(success) {
if (success is GetAllEmailSuccess) {
_getAllEmailSuccess(success);
} else if (success is LoadMoreEmailsSuccess) {
_loadMoreEmailsSuccess(success);
}
} }
}); );
} }
@override @override
void onDone() { void onDone() {
viewState.value.fold( viewState.value.fold(
(failure) { (failure) {
if (failure is GetAllEmailFailure) { if (failure is MarkAsMultipleEmailReadAllFailure
_resetPositionCurrentAndLoadMoreState();
} else if (failure is MarkAsMultipleEmailReadAllFailure
|| failure is MarkAsMultipleEmailReadFailure) { || failure is MarkAsMultipleEmailReadFailure) {
_markAsSelectedEmailReadFailure(failure); _markAsSelectedEmailReadFailure(failure);
} else if (failure is MarkAsStarMultipleEmailAllFailure } else if (failure is MarkAsStarMultipleEmailAllFailure
@@ -165,49 +173,36 @@ class ThreadController extends BaseController {
void _getAllEmail() { void _getAllEmail() {
if (_accountId != null) { if (_accountId != null) {
_getAllEmailAction(_accountId!, inMailboxId: _currentMailboxId); _getAllEmailAction(_accountId!, mailboxId: _currentMailboxId);
} }
} }
void _resetToOriginalValue() { void _resetToOriginalValue() {
dispatchState(Right(LoadingState())); dispatchState(Right(LoadingState()));
emailList.value = <PresentationEmail>[]; emailList.value = <PresentationEmail>[];
loadMoreState.value = LoadMoreState.IDLE; canLoadMore = true;
_currentPosition = 0;
} }
void _getAllEmailSuccess(Success success) { void _getAllEmailSuccess(GetAllEmailSuccess success) {
if (success is GetAllEmailSuccess) { _currentEmailState = success.currentEmailState;
_currentEmailState = success.currentEmailState; emailList.value = success.emailList;
if (loadMoreState.value == LoadMoreState.LOADING) {
emailList.addAll(success.emailList);
} else {
emailList.value = success.emailList;
}
_totalNumberOfEmails = emailList.length;
loadMoreState.value = success.emailList.isEmpty ? LoadMoreState.COMPLETED : LoadMoreState.IDLE;
}
} }
void _getAllEmailAction(AccountId accountId, {MailboxId? inMailboxId}) { void _getAllEmailAction(AccountId accountId, {MailboxId? mailboxId}) {
consumeState(_getEmailsInMailboxInteractor.execute( consumeState(_getEmailsInMailboxInteractor.execute(
accountId, accountId,
limit: ThreadConstants.defaultLimit, limit: ThreadConstants.defaultLimit,
position: _currentPosition,
sort: _sortOrder, sort: _sortOrder,
filter: _filterCondition, emailFilter: EmailFilter(
filter: _filterCondition,
mailboxId: mailboxId ?? _currentMailboxId),
propertiesCreated: ThreadConstants.propertiesDefault, propertiesCreated: ThreadConstants.propertiesDefault,
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault, propertiesUpdated: ThreadConstants.propertiesUpdatedDefault,
inMailboxId: inMailboxId ?? _currentMailboxId
)); ));
} }
void refreshAllEmail() { void refreshAllEmail() {
dispatchState(Right(LoadingState())); dispatchState(Right(LoadingState()));
loadMoreState.value = LoadMoreState.IDLE;
_currentPosition = 0;
_getAllEmail(); _getAllEmail();
} }
@@ -224,20 +219,28 @@ class ThreadController extends BaseController {
} }
} }
void loadMoreEmailAction() { void loadMoreEmails() {
loadMoreState.value = LoadMoreState.LOADING; if (canLoadMore) {
_currentPosition += _totalNumberOfEmails; if (_accountId != null) {
consumeState(_loadMoreEmailsInMailboxInteractor.execute(
if (_accountId != null) { _accountId!,
_getAllEmailAction(_accountId!); limit: ThreadConstants.defaultLimit,
sort: _sortOrder,
filter: EmailFilterCondition(
inMailbox: mailboxDashBoardController.selectedMailbox.value?.id,
before: emailList.last.receivedAt),
properties: ThreadConstants.propertiesDefault,
));
}
} }
} }
void _resetPositionCurrentAndLoadMoreState() { void _loadMoreEmailsSuccess(LoadMoreEmailsSuccess success) {
if (loadMoreState.value == LoadMoreState.LOADING) { if (success.emailList.isNotEmpty) {
_currentPosition -= _totalNumberOfEmails; emailList.addAll(success.emailList);
} else {
canLoadMore = false;
} }
loadMoreState.value = LoadMoreState.IDLE;
} }
SelectMode getSelectMode(PresentationEmail presentationEmail, PresentationEmail? selectedEmail) { SelectMode getSelectMode(PresentationEmail presentationEmail, PresentationEmail? selectedEmail) {
@@ -421,7 +424,6 @@ class ThreadController extends BaseController {
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value; final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (_accountId != null && mailboxCurrent != null) { if (_accountId != null && mailboxCurrent != null) {
final importantAction = presentationEmail.isFlaggedEmail() ? MarkStarAction.unMarkStar : MarkStarAction.markStar; final importantAction = presentationEmail.isFlaggedEmail() ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
dispatchState(Right(LoadingState()));
consumeState(_markAsStarEmailInteractor.execute(_accountId!, presentationEmail.toEmail(), importantAction)); consumeState(_markAsStarEmailInteractor.execute(_accountId!, presentationEmail.toEmail(), importantAction));
} }
} }
@@ -5,7 +5,6 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:model/email/presentation_email.dart'; import 'package:model/email/presentation_email.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart';
@@ -184,7 +183,7 @@ class ThreadView extends GetWidget<ThreadController> {
Widget _buildLoadingView() { Widget _buildLoadingView() {
return Obx(() => controller.viewState.value.fold( return Obx(() => controller.viewState.value.fold(
(failure) => SizedBox.shrink(), (failure) => SizedBox.shrink(),
(success) => success is LoadingState && controller.loadMoreState.value != LoadMoreState.LOADING (success) => success is LoadingState
? Center(child: Padding( ? Center(child: Padding(
padding: EdgeInsets.only(top: 16, bottom: 16), padding: EdgeInsets.only(top: 16, bottom: 16),
child: SizedBox( child: SizedBox(
@@ -195,14 +194,16 @@ class ThreadView extends GetWidget<ThreadController> {
} }
Widget _buildLoadingViewLoadMore() { Widget _buildLoadingViewLoadMore() {
return Obx(() => controller.loadMoreState.value == LoadMoreState.LOADING return Obx(() => controller.viewState.value.fold(
? Center(child: Padding( (failure) => SizedBox.shrink(),
padding: EdgeInsets.only(top: 16, bottom: 16), (success) => success is LoadingMoreState
child: SizedBox( ? Center(child: Padding(
width: 24, padding: EdgeInsets.only(top: 16, bottom: 16),
height: 24, child: SizedBox(
child: CircularProgressIndicator(color: AppColor.primaryColor)))) width: 24,
: SizedBox.shrink()); height: 24,
child: CircularProgressIndicator(color: AppColor.primaryColor))))
: SizedBox.shrink()));
} }
Widget _buildListEmail(BuildContext context) { Widget _buildListEmail(BuildContext context) {
@@ -232,9 +233,8 @@ class ThreadView extends GetWidget<ThreadController> {
return NotificationListener<ScrollNotification>( return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) { onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo is ScrollEndNotification if (scrollInfo is ScrollEndNotification
&& controller.loadMoreState.value == LoadMoreState.IDLE
&& scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) { && scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
controller.loadMoreEmailAction(); controller.loadMoreEmails();
} }
return false; return false;
}, },
+4 -3
View File
@@ -24,10 +24,11 @@ class LocalBindings extends Bindings {
Get.put(MailboxCacheClient()); Get.put(MailboxCacheClient());
Get.put(StateCacheClient()); Get.put(StateCacheClient());
Get.put(MailboxCacheManager(Get.find<MailboxCacheClient>())); Get.put(MailboxCacheManager(Get.find<MailboxCacheClient>()));
Get.put(CachingManager(
Get.find<MailboxCacheClient>(),
Get.find<StateCacheClient>()));
Get.put(EmailCacheClient()); Get.put(EmailCacheClient());
Get.put(EmailCacheManager(Get.find<EmailCacheClient>())); Get.put(EmailCacheManager(Get.find<EmailCacheClient>()));
Get.put(CachingManager(
Get.find<MailboxCacheClient>(),
Get.find<StateCacheClient>(),
Get.find<EmailCacheClient>()));
} }
} }
+15
View File
@@ -0,0 +1,15 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
class EmailFilter with EquatableMixin {
final Filter? filter;
final MailboxId? mailboxId;
EmailFilter({this.filter, this.mailboxId});
@override
List<Object?> get props => [filter, mailboxId];
}
@@ -8,7 +8,7 @@ import 'package:jmap_dart_client/jmap/core/extensions/unsigned_int_extension.dar
extension ListEmailExtension on List<Email> { extension ListEmailExtension on List<Email> {
Email? findEmail(EmailId emailId) { Email? findEmailById(EmailId emailId) {
try { try {
return firstWhere((email) => email.id == emailId); return firstWhere((email) => email.id == emailId);
} catch (e) { } catch (e) {
+1 -1
View File
@@ -1,7 +1,7 @@
extension ListExtension<T> on List<T>? { extension ListExtension<T> on List<T>? {
List<T>? union(List<T>? other) { List<T>? unite(List<T>? other) {
if (other != null) { if (other != null) {
this?.addAll(other); this?.addAll(other);
} }
+1
View File
@@ -28,6 +28,7 @@ export 'email/attachment.dart';
export 'email/move_action.dart'; export 'email/move_action.dart';
export 'email/mark_star_action.dart'; export 'email/mark_star_action.dart';
export 'email/email_property.dart'; export 'email/email_property.dart';
export 'email/email_filter.dart';
// Extensions // Extensions
export 'extensions/email_address_extension.dart'; export 'extensions/email_address_extension.dart';
@@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:core/core.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
@@ -45,8 +46,9 @@ void main() {
final states = await streamStates.toList(); final states = await streamStates.toList();
expect(states.length, equals(1)); expect(states.length, equals(2));
expect(states, containsAllInOrder({ expect(states, containsAllInOrder({
Right(RefreshingState()),
Right(GetAllMailboxSuccess( Right(GetAllMailboxSuccess(
defaultMailboxList: { defaultMailboxList: {
MailboxFixtures.inboxMailbox.toPresentationMailbox(), MailboxFixtures.inboxMailbox.toPresentationMailbox(),
@@ -38,20 +38,21 @@ void main() {
when(threadRepository.getAllEmail( when(threadRepository.getAllEmail(
AccountFixtures.aliceAccountId, AccountFixtures.aliceAccountId,
limit: UnsignedInt(20), limit: UnsignedInt(20),
position: 0,
sort: Set()..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), sort: Set()..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)),
filter: EmailFilterCondition(inMailbox: MailboxFixtures.inboxMailbox.id), emailFilter: EmailFilter(
filter: EmailFilterCondition(inMailbox: MailboxFixtures.inboxMailbox.id),
mailboxId: MailboxFixtures.inboxMailbox.id,
),
propertiesCreated: ThreadConstants.propertiesDefault, propertiesCreated: ThreadConstants.propertiesDefault,
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault, propertiesUpdated: ThreadConstants.propertiesUpdatedDefault,
inMailboxId: MailboxFixtures.inboxMailbox.id
)).thenAnswer((_) => Stream.fromIterable({ )).thenAnswer((_) => Stream.fromIterable({
EmailResponse( EmailsResponse(
emailList: { emailList: {
EmailFixtures.email1, EmailFixtures.email1,
EmailFixtures.email2 EmailFixtures.email2
}.toList(), }.toList(),
state: jmap.State('s1')), state: jmap.State('s1')),
EmailResponse( EmailsResponse(
emailList: { emailList: {
EmailFixtures.email1, EmailFixtures.email1,
EmailFixtures.email2, EmailFixtures.email2,
@@ -65,12 +66,13 @@ void main() {
final streamStates = getEmailsInMailboxInteractor.execute( final streamStates = getEmailsInMailboxInteractor.execute(
AccountFixtures.aliceAccountId, AccountFixtures.aliceAccountId,
limit: UnsignedInt(20), limit: UnsignedInt(20),
position: 0,
sort: Set()..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), sort: Set()..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)),
filter: EmailFilterCondition(inMailbox: MailboxFixtures.inboxMailbox.id), emailFilter: EmailFilter(
filter: EmailFilterCondition(inMailbox: MailboxFixtures.inboxMailbox.id),
mailboxId: MailboxFixtures.inboxMailbox.id,
),
propertiesCreated: ThreadConstants.propertiesDefault, propertiesCreated: ThreadConstants.propertiesDefault,
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault, propertiesUpdated: ThreadConstants.propertiesUpdatedDefault);
inMailboxId: MailboxFixtures.inboxMailbox.id);
final states = await streamStates.toList(); final states = await streamStates.toList();
@@ -5,13 +5,14 @@
import 'dart:async' as _i3; import 'dart:async' as _i3;
import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5;
import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i8; import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i12;
import 'package:jmap_dart_client/jmap/core/properties/properties.dart' as _i9; import 'package:jmap_dart_client/jmap/core/properties/properties.dart' as _i9;
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart' as _i7; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart' as _i7;
import 'package:jmap_dart_client/jmap/core/state.dart' as _i11; import 'package:jmap_dart_client/jmap/core/state.dart' as _i10;
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart' as _i6; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart' as _i6;
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart' as _i10; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart' as _i11;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:model/email/email_filter.dart' as _i8;
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart' import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'
as _i4; as _i4;
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'
@@ -32,35 +33,31 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository {
} }
@override @override
_i3.Stream<_i4.EmailResponse> getAllEmail(_i5.AccountId? accountId, _i3.Stream<_i4.EmailsResponse> getAllEmail(_i5.AccountId? accountId,
{int? position, {_i6.UnsignedInt? limit,
_i6.UnsignedInt? limit,
Set<_i7.Comparator>? sort, Set<_i7.Comparator>? sort,
_i8.Filter? filter, _i8.EmailFilter? emailFilter,
_i9.Properties? propertiesCreated, _i9.Properties? propertiesCreated,
_i9.Properties? propertiesUpdated, _i9.Properties? propertiesUpdated}) =>
_i10.MailboxId? inMailboxId}) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method(#getAllEmail, [ Invocation.method(#getAllEmail, [
accountId accountId
], { ], {
#position: position,
#limit: limit, #limit: limit,
#sort: sort, #sort: sort,
#filter: filter, #emailFilter: emailFilter,
#propertiesCreated: propertiesCreated, #propertiesCreated: propertiesCreated,
#propertiesUpdated: propertiesUpdated, #propertiesUpdated: propertiesUpdated
#inMailboxId: inMailboxId
}), }),
returnValue: Stream<_i4.EmailResponse>.empty()) returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailResponse>); as _i3.Stream<_i4.EmailsResponse>);
@override @override
_i3.Stream<_i4.EmailResponse> refreshChanges( _i3.Stream<_i4.EmailsResponse> refreshChanges(
_i5.AccountId? accountId, _i11.State? currentState, _i5.AccountId? accountId, _i10.State? currentState,
{Set<_i7.Comparator>? sort, {Set<_i7.Comparator>? sort,
_i9.Properties? propertiesCreated, _i9.Properties? propertiesCreated,
_i9.Properties? propertiesUpdated, _i9.Properties? propertiesUpdated,
_i10.MailboxId? inMailboxId}) => _i11.MailboxId? inMailboxId}) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method(#refreshChanges, [ Invocation.method(#refreshChanges, [
accountId, accountId,
@@ -71,6 +68,23 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository {
#propertiesUpdated: propertiesUpdated, #propertiesUpdated: propertiesUpdated,
#inMailboxId: inMailboxId #inMailboxId: inMailboxId
}), }),
returnValue: Stream<_i4.EmailResponse>.empty()) returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailResponse>); as _i3.Stream<_i4.EmailsResponse>);
@override
_i3.Stream<_i4.EmailsResponse> loadMoreEmails(_i5.AccountId? accountId,
{_i6.UnsignedInt? limit,
Set<_i7.Comparator>? sort,
_i12.Filter? filter,
_i9.Properties? properties}) =>
(super.noSuchMethod(
Invocation.method(#loadMoreEmails, [
accountId
], {
#limit: limit,
#sort: sort,
#filter: filter,
#properties: properties
}),
returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailsResponse>);
} }
@@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
@@ -41,7 +42,7 @@ void main() {
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault, propertiesUpdated: ThreadConstants.propertiesUpdatedDefault,
inMailboxId: MailboxFixtures.inboxMailbox.id inMailboxId: MailboxFixtures.inboxMailbox.id
)).thenAnswer((_) => Stream.fromIterable({ )).thenAnswer((_) => Stream.fromIterable({
EmailResponse( EmailsResponse(
emailList: { emailList: {
EmailFixtures.email1, EmailFixtures.email1,
EmailFixtures.email2, EmailFixtures.email2,
@@ -62,8 +63,9 @@ void main() {
final states = await streamStates.toList(); final states = await streamStates.toList();
expect(states.length, equals(1)); expect(states.length, equals(2));
expect(states, containsAllInOrder({ expect(states, containsAllInOrder({
Right(RefreshingState()),
Right(GetAllEmailSuccess( Right(GetAllEmailSuccess(
emailList: { emailList: {
EmailFixtures.email1.toPresentationEmail(), EmailFixtures.email1.toPresentationEmail(),
@@ -5,13 +5,14 @@
import 'dart:async' as _i3; import 'dart:async' as _i3;
import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5;
import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i8; import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i12;
import 'package:jmap_dart_client/jmap/core/properties/properties.dart' as _i9; import 'package:jmap_dart_client/jmap/core/properties/properties.dart' as _i9;
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart' as _i7; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart' as _i7;
import 'package:jmap_dart_client/jmap/core/state.dart' as _i11; import 'package:jmap_dart_client/jmap/core/state.dart' as _i10;
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart' as _i6; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart' as _i6;
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart' as _i10; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart' as _i11;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:model/email/email_filter.dart' as _i8;
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart' import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'
as _i4; as _i4;
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'
@@ -32,35 +33,31 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository {
} }
@override @override
_i3.Stream<_i4.EmailResponse> getAllEmail(_i5.AccountId? accountId, _i3.Stream<_i4.EmailsResponse> getAllEmail(_i5.AccountId? accountId,
{int? position, {_i6.UnsignedInt? limit,
_i6.UnsignedInt? limit,
Set<_i7.Comparator>? sort, Set<_i7.Comparator>? sort,
_i8.Filter? filter, _i8.EmailFilter? emailFilter,
_i9.Properties? propertiesCreated, _i9.Properties? propertiesCreated,
_i9.Properties? propertiesUpdated, _i9.Properties? propertiesUpdated}) =>
_i10.MailboxId? inMailboxId}) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method(#getAllEmail, [ Invocation.method(#getAllEmail, [
accountId accountId
], { ], {
#position: position,
#limit: limit, #limit: limit,
#sort: sort, #sort: sort,
#filter: filter, #emailFilter: emailFilter,
#propertiesCreated: propertiesCreated, #propertiesCreated: propertiesCreated,
#propertiesUpdated: propertiesUpdated, #propertiesUpdated: propertiesUpdated
#inMailboxId: inMailboxId
}), }),
returnValue: Stream<_i4.EmailResponse>.empty()) returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailResponse>); as _i3.Stream<_i4.EmailsResponse>);
@override @override
_i3.Stream<_i4.EmailResponse> refreshChanges( _i3.Stream<_i4.EmailsResponse> refreshChanges(
_i5.AccountId? accountId, _i11.State? currentState, _i5.AccountId? accountId, _i10.State? currentState,
{Set<_i7.Comparator>? sort, {Set<_i7.Comparator>? sort,
_i9.Properties? propertiesCreated, _i9.Properties? propertiesCreated,
_i9.Properties? propertiesUpdated, _i9.Properties? propertiesUpdated,
_i10.MailboxId? inMailboxId}) => _i11.MailboxId? inMailboxId}) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method(#refreshChanges, [ Invocation.method(#refreshChanges, [
accountId, accountId,
@@ -71,6 +68,23 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository {
#propertiesUpdated: propertiesUpdated, #propertiesUpdated: propertiesUpdated,
#inMailboxId: inMailboxId #inMailboxId: inMailboxId
}), }),
returnValue: Stream<_i4.EmailResponse>.empty()) returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailResponse>); as _i3.Stream<_i4.EmailsResponse>);
@override
_i3.Stream<_i4.EmailsResponse> loadMoreEmails(_i5.AccountId? accountId,
{_i6.UnsignedInt? limit,
Set<_i7.Comparator>? sort,
_i12.Filter? filter,
_i9.Properties? properties}) =>
(super.noSuchMethod(
Invocation.method(#loadMoreEmails, [
accountId
], {
#limit: limit,
#sort: sort,
#filter: filter,
#properties: properties
}),
returnValue: Stream<_i4.EmailsResponse>.empty())
as _i3.Stream<_i4.EmailsResponse>);
} }