diff --git a/lib/features/thread/data/repository/thread_repository_impl.dart b/lib/features/thread/data/repository/thread_repository_impl.dart index 18c666d48..2131d0868 100644 --- a/lib/features/thread/data/repository/thread_repository_impl.dart +++ b/lib/features/thread/data/repository/thread_repository_impl.dart @@ -1,5 +1,6 @@ import 'package:core/core.dart'; +import 'package:flutter/foundation.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'; @@ -20,6 +21,7 @@ import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource. import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; +import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; class ThreadRepositoryImpl extends ThreadRepository { @@ -240,34 +242,29 @@ class ThreadRepositoryImpl extends ThreadRepository { } @override - Stream loadMoreEmails( - AccountId accountId, - { - int? position, - UnsignedInt? limit, - Set? sort, - Filter? filter, - Properties? properties, - EmailId? lastEmailId, - } - ) async* { - log('ThreadRepositoryImpl::loadMoreEmails()'); - final emailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail( - accountId, - limit: limit, - sort: sort, - filter: filter, - properties: properties); + Stream loadMoreEmails(GetEmailRequest getEmailRequest) async* { + final response = await compute(_getAllEmailsWithoutLastEmailId, getEmailRequest); + await _updateEmailCache(newCreated: response.emailList); + yield response; + } - final newEmailList = emailResponse.emailList != null && emailResponse.emailList!.isNotEmpty - ? emailResponse.emailList!.where((email) => email.id != lastEmailId).toList() - : []; + Future _getAllEmailsWithoutLastEmailId(GetEmailRequest emailRequest) async { + final emailResponse = await mapDataSource[DataSourceType.network]! + .getAllEmail( + emailRequest.accountId, + limit: emailRequest.limit, + sort: emailRequest.sort, + filter: emailRequest.filter, + properties: emailRequest.properties) + .then((response) { + var listEmails = response.emailList; + if (listEmails != null && listEmails.isNotEmpty) { + listEmails = listEmails.where((email) => email.id != emailRequest.lastEmailId).toList(); + } + return EmailsResponse(emailList: listEmails, state: response.state); + }); - if (newEmailList.isNotEmpty) { - await _updateEmailCache(newCreated: newEmailList); - } - - yield EmailsResponse(emailList: newEmailList, state: emailResponse.state); + return emailResponse; } @override diff --git a/lib/features/thread/domain/repository/thread_repository.dart b/lib/features/thread/domain/repository/thread_repository.dart index 228de215b..bab1b7055 100644 --- a/lib/features/thread/domain/repository/thread_repository.dart +++ b/lib/features/thread/domain/repository/thread_repository.dart @@ -8,6 +8,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email.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/get_email_request.dart'; abstract class ThreadRepository { Stream getAllEmail( @@ -44,16 +45,7 @@ abstract class ThreadRepository { } ); - Stream loadMoreEmails( - AccountId accountId, - { - UnsignedInt? limit, - Set? sort, - Filter? filter, - Properties? properties, - EmailId? lastEmailId, - } - ); + Stream loadMoreEmails(GetEmailRequest emailRequest); Future> searchEmails( AccountId accountId, diff --git a/lib/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart b/lib/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart index af45430be..02ef08afc 100644 --- a/lib/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart +++ b/lib/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart @@ -1,12 +1,7 @@ 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:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; +import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.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'; @@ -16,28 +11,11 @@ class LoadMoreEmailsInMailboxInteractor { LoadMoreEmailsInMailboxInteractor(this.threadRepository); - Stream> execute( - AccountId accountId, - { - UnsignedInt? limit, - Set? sort, - Filter? filter, - Properties? properties, - EmailId? lastEmailId, - } - ) async* { + Stream> execute(GetEmailRequest emailRequest) async* { try { yield Right(LoadingMoreState()); - yield* threadRepository - .loadMoreEmails( - accountId, - limit: limit, - sort: sort, - filter: filter, - properties: properties, - lastEmailId: lastEmailId) - .map(_toGetEmailState); + yield* threadRepository.loadMoreEmails(emailRequest).map(_toGetEmailState); } catch (e) { yield Left(LoadMoreEmailsFailure(e)); } diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 6156b2f87..60a0b316c 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -39,6 +39,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_ema import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; +import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/domain/state/empty_trash_folder_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart'; @@ -382,18 +383,21 @@ class ThreadController extends BaseController { void loadMoreEmails() { if (canLoadMore && _accountId != null) { log('ThreadController::loadMoreEmails(): latest: ${emailList.last.receivedAt}'); + bench.start('loadMoreEmails'); consumeState(_loadMoreEmailsInMailboxInteractor.execute( - _accountId!, - limit: ThreadConstants.defaultLimit, - sort: _sortOrder, - filter: _getFilterCondition(isLoadMore: true), - properties: ThreadConstants.propertiesDefault, - lastEmailId: emailList.last.id + GetEmailRequest( + _accountId!, + limit: ThreadConstants.defaultLimit, + sort: _sortOrder, + filter: _getFilterCondition(isLoadMore: true), + properties: ThreadConstants.propertiesDefault, + lastEmailId: emailList.last.id) )); } } void _loadMoreEmailsSuccess(LoadMoreEmailsSuccess success) { + bench.end('loadMoreEmails'); log('ThreadController::_loadMoreEmailsSuccess(): [BEFORE] totalEmailList = ${emailList.length}'); if (success.emailList.isNotEmpty) { log('ThreadController::_loadMoreEmailsSuccess(): add success: ${success.emailList.length}'); diff --git a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart index 8c053db23..08478dca1 100644 --- a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart +++ b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart @@ -5,7 +5,7 @@ import 'dart:async' as _i3; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; -import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i12; +import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i14; 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/state.dart' as _i10; @@ -16,6 +16,8 @@ import 'package:mockito/mockito.dart' as _i1; import 'package:model/model.dart' as _i8; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart' as _i4; +import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dart' + as _i12; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' as _i2; @@ -56,6 +58,25 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { returnValue: Stream<_i4.EmailsResponse>.empty()) as _i3.Stream<_i4.EmailsResponse>); @override + _i3.Stream<_i4.EmailsResponse> refreshAll(_i5.AccountId? accountId, + {_i6.UnsignedInt? limit, + Set<_i7.Comparator>? sort, + _i8.EmailFilter? emailFilter, + _i9.Properties? propertiesCreated, + _i9.Properties? propertiesUpdated}) => + (super.noSuchMethod( + Invocation.method(#refreshAll, [ + accountId + ], { + #limit: limit, + #sort: sort, + #emailFilter: emailFilter, + #propertiesCreated: propertiesCreated, + #propertiesUpdated: propertiesUpdated + }), + returnValue: Stream<_i4.EmailsResponse>.empty()) + as _i3.Stream<_i4.EmailsResponse>); + @override _i3.Stream<_i4.EmailsResponse> refreshChanges( _i5.AccountId? accountId, _i10.State? currentState, {Set<_i7.Comparator>? sort, @@ -77,29 +98,16 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { returnValue: Stream<_i4.EmailsResponse>.empty()) 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, - _i13.EmailId? lastEmailId}) => - (super.noSuchMethod( - Invocation.method(#loadMoreEmails, [ - accountId - ], { - #limit: limit, - #sort: sort, - #filter: filter, - #properties: properties, - #lastEmailId: lastEmailId - }), + _i3.Stream<_i4.EmailsResponse> loadMoreEmails( + _i12.GetEmailRequest? emailRequest) => + (super.noSuchMethod(Invocation.method(#loadMoreEmails, [emailRequest]), returnValue: Stream<_i4.EmailsResponse>.empty()) as _i3.Stream<_i4.EmailsResponse>); @override _i3.Future> searchEmails(_i5.AccountId? accountId, {_i6.UnsignedInt? limit, Set<_i7.Comparator>? sort, - _i12.Filter? filter, + _i14.Filter? filter, _i9.Properties? properties}) => (super.noSuchMethod( Invocation.method(#searchEmails, [ @@ -112,4 +120,10 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { }), returnValue: Future>.value(<_i13.Email>[])) as _i3.Future>); + @override + _i3.Future emptyTrashFolder( + _i5.AccountId? accountId, _i11.MailboxId? trashMailboxId) => + (super.noSuchMethod( + Invocation.method(#emptyTrashFolder, [accountId, trashMailboxId]), + returnValue: Future.value(false)) as _i3.Future); } diff --git a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart index 50a37e5bd..2189115d9 100644 --- a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart +++ b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart @@ -5,7 +5,7 @@ import 'dart:async' as _i3; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; -import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i12; +import 'package:jmap_dart_client/jmap/core/filter/filter.dart' as _i14; 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/state.dart' as _i10; @@ -16,6 +16,8 @@ import 'package:mockito/mockito.dart' as _i1; import 'package:model/model.dart' as _i8; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart' as _i4; +import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dart' + as _i12; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' as _i2; @@ -56,6 +58,25 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { returnValue: Stream<_i4.EmailsResponse>.empty()) as _i3.Stream<_i4.EmailsResponse>); @override + _i3.Stream<_i4.EmailsResponse> refreshAll(_i5.AccountId? accountId, + {_i6.UnsignedInt? limit, + Set<_i7.Comparator>? sort, + _i8.EmailFilter? emailFilter, + _i9.Properties? propertiesCreated, + _i9.Properties? propertiesUpdated}) => + (super.noSuchMethod( + Invocation.method(#refreshAll, [ + accountId + ], { + #limit: limit, + #sort: sort, + #emailFilter: emailFilter, + #propertiesCreated: propertiesCreated, + #propertiesUpdated: propertiesUpdated + }), + returnValue: Stream<_i4.EmailsResponse>.empty()) + as _i3.Stream<_i4.EmailsResponse>); + @override _i3.Stream<_i4.EmailsResponse> refreshChanges( _i5.AccountId? accountId, _i10.State? currentState, {Set<_i7.Comparator>? sort, @@ -77,29 +98,16 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { returnValue: Stream<_i4.EmailsResponse>.empty()) 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, - _i13.EmailId? lastEmailId}) => - (super.noSuchMethod( - Invocation.method(#loadMoreEmails, [ - accountId - ], { - #limit: limit, - #sort: sort, - #filter: filter, - #properties: properties, - #lastEmailId: lastEmailId - }), + _i3.Stream<_i4.EmailsResponse> loadMoreEmails( + _i12.GetEmailRequest? emailRequest) => + (super.noSuchMethod(Invocation.method(#loadMoreEmails, [emailRequest]), returnValue: Stream<_i4.EmailsResponse>.empty()) as _i3.Stream<_i4.EmailsResponse>); @override _i3.Future> searchEmails(_i5.AccountId? accountId, {_i6.UnsignedInt? limit, Set<_i7.Comparator>? sort, - _i12.Filter? filter, + _i14.Filter? filter, _i9.Properties? properties}) => (super.noSuchMethod( Invocation.method(#searchEmails, [ @@ -112,4 +120,10 @@ class MockThreadRepository extends _i1.Mock implements _i2.ThreadRepository { }), returnValue: Future>.value(<_i13.Email>[])) as _i3.Future>); + @override + _i3.Future emptyTrashFolder( + _i5.AccountId? accountId, _i11.MailboxId? trashMailboxId) => + (super.noSuchMethod( + Invocation.method(#emptyTrashFolder, [accountId, trashMailboxId]), + returnValue: Future.value(false)) as _i3.Future); }