diff --git a/lib/features/base/base_controller.dart b/lib/features/base/base_controller.dart index 05a47874c..55829d9df 100644 --- a/lib/features/base/base_controller.dart +++ b/lib/features/base/base_controller.dart @@ -232,7 +232,7 @@ abstract class BaseController extends GetxController await LocalNotificationManager.instance.setUp(); } FcmInteractorBindings().dependencies(); - FcmController.instance.initialize(accountId: accountId); + FcmController.instance.initialize(session: session,accountId: accountId); } else { throw NotSupportFCMException(); } diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index d1a08ff75..1003a54ae 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -1095,11 +1095,13 @@ class ComposerController extends BaseController { _emailContents = arguments.emailContents; emailContentsViewState.value = Right(GetEmailContentSuccess(_emailContents!, [], [], null)); } else { + final session = mailboxDashBoardController.sessionCurrent; final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: _dynamicUrlInterceptors.jmapUrl); final accountId = mailboxDashBoardController.sessionCurrent?.accounts.keys.first; final emailId = arguments.presentationEmail?.id; - if (emailId != null && baseDownloadUrl != null && accountId != null) { + if (session != null && emailId != null && baseDownloadUrl != null && accountId != null) { consumeState(_getEmailContentInteractor.execute( + session, accountId, emailId, baseDownloadUrl, diff --git a/lib/features/email/data/datasource/email_datasource.dart b/lib/features/email/data/datasource/email_datasource.dart index 6b39c9625..04ca5397f 100644 --- a/lib/features/email/data/datasource/email_datasource.dart +++ b/lib/features/email/data/datasource/email_datasource.dart @@ -5,6 +5,7 @@ import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; @@ -12,7 +13,7 @@ import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_reques import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; abstract class EmailDataSource { - Future getEmailContent(AccountId accountId, EmailId emailId); + Future getEmailContent(Session session, AccountId accountId, EmailId emailId); Future sendEmail(AccountId accountId, EmailRequest emailRequest, {CreateNewMailboxRequest? mailboxRequest}); diff --git a/lib/features/email/data/datasource_impl/email_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_datasource_impl.dart index b42b6ae9a..d4bbf75ad 100644 --- a/lib/features/email/data/datasource_impl/email_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_datasource_impl.dart @@ -7,6 +7,7 @@ import 'package:core/presentation/state/success.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; @@ -24,9 +25,9 @@ class EmailDataSourceImpl extends EmailDataSource { EmailDataSourceImpl(this.emailAPI, this._exceptionThrower); @override - Future getEmailContent(AccountId accountId, EmailId emailId) { + Future getEmailContent(Session session, AccountId accountId, EmailId emailId) { return Future.sync(() async { - return await emailAPI.getEmailContent(accountId, emailId); + return await emailAPI.getEmailContent(session, accountId, emailId); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 7fcb95e85..83057827e 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -17,6 +17,7 @@ import 'package:jmap_dart_client/jmap/core/patch_object.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/core/reference_id.dart'; import 'package:jmap_dart_client/jmap/core/reference_prefix.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/jmap_request.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/get/get_email_method.dart'; @@ -66,7 +67,24 @@ class EmailAPI with HandleSetErrorMixin { EmailAPI(this._httpClient, this._downloadManager, this._dioClient, this._uuid); - Future getEmailContent(AccountId accountId, EmailId emailId) async { + Set _capabilitiesForEmailMethod(Session session, AccountId accountId) { + final getMailboxCreated = GetEmailMethod(accountId); + try { + requireCapability( + session, + accountId, + [CapabilityIdentifier.jmapTeamMailboxes]); + return { + CapabilityIdentifier.jmapCore, + CapabilityIdentifier.jmapMail, + CapabilityIdentifier.jmapTeamMailboxes + }; + } catch (_) { + return getMailboxCreated.requiredCapabilities; + } + } + + Future getEmailContent(Session session, AccountId accountId, EmailId emailId) async { final processingInvocation = ProcessingInvocation(); final jmapRequestBuilder = JmapRequestBuilder(_httpClient, processingInvocation); @@ -86,7 +104,7 @@ class EmailAPI with HandleSetErrorMixin { final getEmailInvocation = jmapRequestBuilder.invocation(getEmailMethod); final result = await (jmapRequestBuilder - ..usings(getEmailMethod.requiredCapabilities)) + ..usings(_capabilitiesForEmailMethod(session, accountId))) .build() .execute(); diff --git a/lib/features/email/data/repository/email_repository_impl.dart b/lib/features/email/data/repository/email_repository_impl.dart index 729dc4c1f..7ed59cbff 100644 --- a/lib/features/email/data/repository/email_repository_impl.dart +++ b/lib/features/email/data/repository/email_repository_impl.dart @@ -6,6 +6,7 @@ import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/model.dart'; @@ -31,8 +32,8 @@ class EmailRepositoryImpl extends EmailRepository { ); @override - Future getEmailContent(AccountId accountId, EmailId emailId) { - return emailDataSource.getEmailContent(accountId, emailId); + Future getEmailContent(Session session, AccountId accountId, EmailId emailId) { + return emailDataSource.getEmailContent(session ,accountId, emailId); } @override diff --git a/lib/features/email/domain/repository/email_repository.dart b/lib/features/email/domain/repository/email_repository.dart index 2828f6cf7..26a7fc767 100644 --- a/lib/features/email/domain/repository/email_repository.dart +++ b/lib/features/email/domain/repository/email_repository.dart @@ -5,6 +5,7 @@ import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:model/model.dart'; @@ -13,7 +14,7 @@ import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_reques import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; abstract class EmailRepository { - Future getEmailContent(AccountId accountId, EmailId emailId); + Future getEmailContent(Session session, AccountId accountId, EmailId emailId); Future sendEmail(AccountId accountId, EmailRequest emailRequest, {CreateNewMailboxRequest? mailboxRequest}); diff --git a/lib/features/email/domain/usecases/get_email_content_interactor.dart b/lib/features/email/domain/usecases/get_email_content_interactor.dart index 4a23bfe2d..d94ea6817 100644 --- a/lib/features/email/domain/usecases/get_email_content_interactor.dart +++ b/lib/features/email/domain/usecases/get_email_content_interactor.dart @@ -4,6 +4,7 @@ import 'package:core/utils/app_logger.dart'; import 'package:core/utils/build_utils.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/extensions/email_extension.dart'; import 'package:model/extensions/list_attachment_extension.dart'; @@ -16,6 +17,7 @@ class GetEmailContentInteractor { GetEmailContentInteractor(this.emailRepository); Stream> execute( + Session session, AccountId accountId, EmailId emailId, String? baseDownloadUrl, @@ -26,7 +28,7 @@ class GetEmailContentInteractor { ) async* { try { yield Right(GetEmailContentLoading()); - final email = await emailRepository.getEmailContent(accountId, emailId); + final email = await emailRepository.getEmailContent(session, accountId, emailId); if (email.emailContentList.isNotEmpty) { final newEmailContents = await emailRepository.transformEmailContent( diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index 7f2f7e664..2b9dc11f8 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -293,6 +293,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } void _getEmailContentAction(EmailId emailId) async { + final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: _dynamicUrlInterceptors.jmapUrl); final emailLoaded = emailSupervisorController.getEmailInQueueByEmailId(emailId); @@ -305,8 +306,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { emailLoaded.emailContentsDisplayed, emailLoaded.attachments, emailLoaded.emailCurrent)))); - } else if (accountId != null && baseDownloadUrl != null) { - consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl)); + } else if (session != null && accountId != null && baseDownloadUrl != null) { + consumeState(_getEmailContentInteractor.execute(session, accountId, emailId, baseDownloadUrl)); } } diff --git a/lib/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart b/lib/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart index ade081aaf..283d3f2cf 100644 --- a/lib/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart +++ b/lib/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart @@ -1,23 +1,32 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; class MailboxMarkAsReadArguments with EquatableMixin { + final Session session; final AccountId accountId; final MailboxId mailboxId; final ThreadAPI threadAPI; final EmailAPI emailAPI; MailboxMarkAsReadArguments( + this.session, this.threadAPI, this.emailAPI, this.accountId, this.mailboxId); @override - List get props => [accountId, mailboxId]; + List get props => [ + session, + accountId, + threadAPI, + emailAPI, + mailboxId + ]; } \ No newline at end of file diff --git a/lib/features/mailbox/data/network/mailbox_isolate_worker.dart b/lib/features/mailbox/data/network/mailbox_isolate_worker.dart index 4429e700c..c8b7a6c4e 100644 --- a/lib/features/mailbox/data/network/mailbox_isolate_worker.dart +++ b/lib/features/mailbox/data/network/mailbox_isolate_worker.dart @@ -43,25 +43,27 @@ class MailboxIsolateWorker { ) async { if (BuildUtils.isWeb) { return _handleMarkAsMailboxReadActionOnWeb( - accountId, - mailboxId, - totalEmailUnread, - onProgressController); + session, + accountId, + mailboxId, + totalEmailUnread, + onProgressController); } else { final result = await _isolateExecutor.execute( arg1: MailboxMarkAsReadArguments( - _threadApi, - _emailApi, - accountId, - mailboxId), + session, + _threadApi, + _emailApi, + accountId, + mailboxId), fun1: _handleMarkAsMailboxReadAction, notification: (value) { if (value is List) { log('MailboxIsolateWorker::markAsMailboxRead(): onUpdateProgress: PERCENT ${value.length / totalEmailUnread}'); onProgressController.add(Right(UpdatingMarkAsMailboxReadState( - mailboxId: mailboxId, - totalUnread: totalEmailUnread, - countRead: value.length))); + mailboxId: mailboxId, + totalUnread: totalEmailUnread, + countRead: value.length))); } }); return result; @@ -80,16 +82,18 @@ class MailboxIsolateWorker { while (mailboxHasEmails) { final emailResponse = await args.threadAPI - .getAllEmail(args.accountId, - limit: UnsignedInt(30), - filter: EmailFilterCondition( + .getAllEmail( + args.session, + args.accountId, + limit: UnsignedInt(30), + filter: EmailFilterCondition( inMailbox: args.mailboxId, notKeyword: KeyWordIdentifier.emailSeen.value, before: lastReceivedDate), - sort: {}..add( - EmailComparator(EmailComparatorProperty.receivedAt) - ..setIsAscending(false)), - properties: Properties({ + sort: {}..add( + EmailComparator(EmailComparatorProperty.receivedAt) + ..setIsAscending(false)), + properties: Properties({ EmailProperty.id, EmailProperty.keywords, EmailProperty.receivedAt, @@ -98,8 +102,8 @@ class MailboxIsolateWorker { var listEmails = response.emailList; if (listEmails != null && listEmails.isNotEmpty && lastEmailId != null) { listEmails = listEmails - .where((email) => email.id != lastEmailId) - .toList(); + .where((email) => email.id != lastEmailId) + .toList(); } return EmailsResponse(emailList: listEmails, state: response.state); }); @@ -131,10 +135,11 @@ class MailboxIsolateWorker { } Future> _handleMarkAsMailboxReadActionOnWeb( - AccountId accountId, - MailboxId mailboxId, - int totalEmailUnread, - StreamController> onProgressController + Session session, + AccountId accountId, + MailboxId mailboxId, + int totalEmailUnread, + StreamController> onProgressController ) async { List emailListCompleted = List.empty(growable: true); try { @@ -144,28 +149,30 @@ class MailboxIsolateWorker { while (mailboxHasEmails) { final emailResponse = await _threadApi - .getAllEmail(accountId, - limit: UnsignedInt(30), - filter: EmailFilterCondition( - inMailbox: mailboxId, - notKeyword: KeyWordIdentifier.emailSeen.value, - before: lastReceivedDate), - sort: {}..add( + .getAllEmail( + session, + accountId, + limit: UnsignedInt(30), + filter: EmailFilterCondition( + inMailbox: mailboxId, + notKeyword: KeyWordIdentifier.emailSeen.value, + before: lastReceivedDate), + sort: {}..add( EmailComparator(EmailComparatorProperty.receivedAt) ..setIsAscending(false)), - properties: Properties({ + properties: Properties({ EmailProperty.id, EmailProperty.keywords, EmailProperty.receivedAt, - })) - .then((response) { - var listEmails = response.emailList; - if (listEmails != null && listEmails.isNotEmpty && lastEmailId != null) { - listEmails = listEmails - .where((email) => email.id != lastEmailId) - .toList(); - } - return EmailsResponse(emailList: listEmails, state: response.state); + }) + ).then((response) { + var listEmails = response.emailList; + if (listEmails != null && listEmails.isNotEmpty && lastEmailId != null) { + listEmails = listEmails + .where((email) => email.id != lastEmailId) + .toList(); + } + return EmailsResponse(emailList: listEmails, state: response.state); }); final listEmailUnread = emailResponse.emailList; diff --git a/lib/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart index ea1a170c3..6e363114b 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart @@ -1,5 +1,6 @@ import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:model/model.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; @@ -17,6 +18,7 @@ class QuickSearchEmailInteractor { QuickSearchEmailInteractor(this.threadRepository); Future> execute( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -27,6 +29,7 @@ class QuickSearchEmailInteractor { ) async { try { final emailList = await threadRepository.searchEmails( + session, accountId, limit: limit, sort: sort, diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index 8d95ecdbc..20790e43c 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -1074,8 +1074,8 @@ class MailboxDashBoardController extends ReloadableController { onCancelSelectionEmail?.call(); final trashMailboxId = mapDefaultMailboxIdByRole[PresentationMailbox.roleTrash]; - if (accountId.value != null && trashMailboxId != null) { - consumeState(_emptyTrashFolderInteractor.execute(accountId.value!, trashMailboxId)); + if (sessionCurrent != null && accountId.value != null && trashMailboxId != null) { + consumeState(_emptyTrashFolderInteractor.execute(sessionCurrent!, accountId.value!, trashMailboxId)); } } @@ -1285,7 +1285,10 @@ class MailboxDashBoardController extends ReloadableController { searchController.addFilterToSuggestionForm(filter); } - Future> quickSearchEmails() => searchController.quickSearchEmails(accountId: accountId.value!); + Future> quickSearchEmails() => searchController.quickSearchEmails( + session: sessionCurrent!, + accountId: accountId.value! + ); void addDownloadTask(DownloadTaskState task) { downloadController.addDownloadTask(task); @@ -1479,11 +1482,12 @@ class MailboxDashBoardController extends ReloadableController { void _handleNotificationMessageFromEmailId(EmailId emailId, {bool onForeground = true}) { final currentAccountId = accountId.value; - if (currentAccountId != null) { + final session = sessionCurrent; + if (currentAccountId != null && session != null) { if (onForeground) { _showWaitingView(); } - _getPresentationEmailFromEmailIdAction(emailId, currentAccountId); + _getPresentationEmailFromEmailIdAction(emailId, currentAccountId, session); } else { dispatchRoute(DashboardRoutes.thread); } @@ -1500,9 +1504,10 @@ class MailboxDashBoardController extends ReloadableController { dispatchRoute(DashboardRoutes.thread); } - void _getPresentationEmailFromEmailIdAction(EmailId emailId, AccountId accountId) { + void _getPresentationEmailFromEmailIdAction(EmailId emailId, AccountId accountId, Session session) { log('MailboxDashBoardController:_getPresentationEmailFromEmailIdAction:emailId: $emailId'); consumeState(_getEmailByIdInteractor.execute( + session, accountId, emailId, properties: ThreadConstants.propertiesDefault diff --git a/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart index fb1f5c14e..e61a38eee 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/search_controller.dart @@ -9,6 +9,7 @@ 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/filter/filter_operator.dart'; import 'package:jmap_dart_client/jmap/core/filter/operator/logic_filter_operator.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.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/utc_date.dart'; @@ -103,10 +104,12 @@ class SearchController extends BaseController with DateRangePickerMixin { } Future> quickSearchEmails({ + required Session session, required AccountId accountId, UserProfile? userProfile }) async { return await _quickSearchEmailInteractor.execute( + session, accountId, limit: UnsignedInt(5), sort: {}..add( diff --git a/lib/features/push_notification/data/repository/fcm_repository_impl.dart b/lib/features/push_notification/data/repository/fcm_repository_impl.dart index 8ddf6d546..f80e97229 100644 --- a/lib/features/push_notification/data/repository/fcm_repository_impl.dart +++ b/lib/features/push_notification/data/repository/fcm_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:fcm/model/firebase_subscription.dart'; import 'package:fcm/model/type_name.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart'; import 'package:tmail_ui_user/features/push_notification/data/extensions/fcm_subscription_extensions.dart'; import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart'; @@ -25,6 +26,7 @@ class FCMRepositoryImpl extends FCMRepository { @override Future getEmailChangesToPushNotification( + Session session, AccountId accountId, jmap.State currentState, { @@ -38,6 +40,7 @@ class FCMRepositoryImpl extends FCMRepository { while (hasMoreChanges && sinceState != null) { final changesResponse = await _threadDataSource.getChanges( + session, accountId, sinceState, propertiesCreated: propertiesCreated, diff --git a/lib/features/push_notification/domain/repository/fcm_repository.dart b/lib/features/push_notification/domain/repository/fcm_repository.dart index 12bd75b66..bc232ed62 100644 --- a/lib/features/push_notification/domain/repository/fcm_repository.dart +++ b/lib/features/push_notification/domain/repository/fcm_repository.dart @@ -2,6 +2,7 @@ import 'package:fcm/model/firebase_subscription.dart'; import 'package:fcm/model/type_name.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart'; import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; @@ -9,6 +10,7 @@ import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; abstract class FCMRepository { Future getEmailChangesToPushNotification( + Session session, AccountId accountId, jmap.State currentState, { diff --git a/lib/features/push_notification/domain/usecases/get_email_changes_to_push_notification_interactor.dart b/lib/features/push_notification/domain/usecases/get_email_changes_to_push_notification_interactor.dart index 57ff490ce..6df61384f 100644 --- a/lib/features/push_notification/domain/usecases/get_email_changes_to_push_notification_interactor.dart +++ b/lib/features/push_notification/domain/usecases/get_email_changes_to_push_notification_interactor.dart @@ -3,6 +3,7 @@ import 'package:core/presentation/state/success.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:model/extensions/email_extension.dart'; import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart'; @@ -14,6 +15,7 @@ class GetEmailChangesToPushNotificationInteractor { GetEmailChangesToPushNotificationInteractor(this._fcmRepository); Stream> execute( + Session session, AccountId accountId, jmap.State currentState, { @@ -25,6 +27,7 @@ class GetEmailChangesToPushNotificationInteractor { yield Right(GetEmailChangesToPushNotificationLoading()); final emailsResponse = await _fcmRepository.getEmailChangesToPushNotification( + session, accountId, currentState, propertiesCreated: propertiesCreated, diff --git a/lib/features/push_notification/presentation/action/fcm_action.dart b/lib/features/push_notification/presentation/action/fcm_action.dart index 9f8205334..847d377de 100644 --- a/lib/features/push_notification/presentation/action/fcm_action.dart +++ b/lib/features/push_notification/presentation/action/fcm_action.dart @@ -1,6 +1,7 @@ import 'package:fcm/model/type_name.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; @@ -20,16 +21,18 @@ class SynchronizeEmailOnForegroundAction extends FcmStateChangeAction { class PushNotificationAction extends FcmStateChangeAction { + final Session session; final AccountId accountId; PushNotificationAction( TypeName typeName, jmap.State newState, + this.session, this.accountId ) : super(typeName, newState); @override - List get props => [typeName, newState, accountId]; + List get props => [typeName, newState, accountId, session]; } class StoreEmailStateToRefreshAction extends FcmStateChangeAction { diff --git a/lib/features/push_notification/presentation/controller/fcm_controller.dart b/lib/features/push_notification/presentation/controller/fcm_controller.dart index 637a67860..41bd0755c 100644 --- a/lib/features/push_notification/presentation/controller/fcm_controller.dart +++ b/lib/features/push_notification/presentation/controller/fcm_controller.dart @@ -10,6 +10,7 @@ import 'package:dartz/dartz.dart'; import 'package:fcm/model/type_name.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/push/state_change.dart'; import 'package:model/oidc/token_oidc.dart'; @@ -37,6 +38,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class FcmController extends BaseController { AccountId? _currentAccountId; + Session? _currentSession; RemoteMessage? _remoteMessageBackground; GetAuthenticatedAccountInteractor? _getAuthenticatedAccountInteractor; @@ -50,7 +52,8 @@ class FcmController extends BaseController { static FcmController get instance => _instance; - void initialize({AccountId? accountId}) { + void initialize({Session? session, AccountId? accountId}) { + _currentSession = session; _currentAccountId = accountId; FcmTokenHandler.instance.initialize(); } @@ -86,10 +89,10 @@ class FcmController extends BaseController { void _handleForegroundMessageAction(RemoteMessage newRemoteMessage) { log('FcmController::_handleForegroundMessageAction():remoteMessage: ${newRemoteMessage.data}'); - if (_currentAccountId != null) { + if (_currentAccountId != null && _currentSession != null) { final stateChange = _convertRemoteMessageToStateChange(newRemoteMessage); final mapTypeState = stateChange.getMapTypeState(_currentAccountId!); - _mappingTypeStateToAction(mapTypeState, _currentAccountId!); + _mappingTypeStateToAction(_currentSession!, mapTypeState, _currentAccountId!); } } @@ -105,6 +108,7 @@ class FcmController extends BaseController { } void _mappingTypeStateToAction( + Session session, Map mapTypeState, AccountId accountId, { bool isForeground = true, @@ -116,7 +120,7 @@ class FcmController extends BaseController { final listEmailActions = listTypeName .where((typeName) => typeName == TypeName.emailType || typeName == TypeName.emailDelivery) - .map((typeName) => toFcmAction(typeName, accountId, mapTypeState, isForeground)) + .map((typeName) => toFcmAction(session, typeName, accountId, mapTypeState, isForeground)) .whereNotNull() .toList(); @@ -128,7 +132,7 @@ class FcmController extends BaseController { final listMailboxActions = listTypeName .where((typeName) => typeName == TypeName.mailboxType) - .map((typeName) => toFcmAction(typeName, accountId, mapTypeState, isForeground)) + .map((typeName) => toFcmAction(session, typeName, accountId, mapTypeState, isForeground)) .whereNotNull() .toList(); @@ -140,6 +144,7 @@ class FcmController extends BaseController { } FcmAction? toFcmAction( + Session session, TypeName typeName, AccountId accountId, Map mapTypeState, @@ -154,7 +159,7 @@ class FcmController extends BaseController { } } else if (typeName == TypeName.emailDelivery) { if (!isForeground) { - return PushNotificationAction(typeName, newState, accountId); + return PushNotificationAction(typeName, newState, session, accountId); } } else if (typeName == TypeName.mailboxType) { if (isForeground) { @@ -243,10 +248,10 @@ class FcmController extends BaseController { void _pushActionFromRemoteMessageBackground() { log('FcmController::_pushActionFromRemoteMessageBackground():'); - if (_remoteMessageBackground != null && _currentAccountId != null) { + if (_remoteMessageBackground != null && _currentAccountId != null && _currentSession != null) { final stateChange = _convertRemoteMessageToStateChange(_remoteMessageBackground!); final mapTypeState = stateChange.getMapTypeState(_currentAccountId!); - _mappingTypeStateToAction(mapTypeState, _currentAccountId!, isForeground: false); + _mappingTypeStateToAction(_currentSession!, mapTypeState, _currentAccountId!, isForeground: false); } _clearRemoteMessageBackground(); } diff --git a/lib/features/push_notification/presentation/listener/email_change_listener.dart b/lib/features/push_notification/presentation/listener/email_change_listener.dart index 253e34993..e5bb69f00 100644 --- a/lib/features/push_notification/presentation/listener/email_change_listener.dart +++ b/lib/features/push_notification/presentation/listener/email_change_listener.dart @@ -6,6 +6,7 @@ import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/build_utils.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:model/email/presentation_email.dart'; import 'package:model/notification/notification_payload.dart'; @@ -41,6 +42,7 @@ class EmailChangeListener extends ChangeListener { jmap.State? _newState; AccountId? _accountId; + Session? _session; EmailChangeListener._internal() { try { @@ -66,7 +68,7 @@ class EmailChangeListener extends ChangeListener { if (action is SynchronizeEmailOnForegroundAction) { _synchronizeEmailOnForegroundAction(action.newState); } else if (action is PushNotificationAction) { - _pushNotificationAction(action.newState, action.accountId); + _pushNotificationAction(action.newState, action.accountId, action.session); } else if (action is StoreEmailStateToRefreshAction) { _handleStoreEmailStateToRefreshAction(action.newState); } @@ -80,7 +82,7 @@ class EmailChangeListener extends ChangeListener { } } - void _pushNotificationAction(jmap.State newState, AccountId accountId) { + void _pushNotificationAction(jmap.State newState, AccountId accountId, Session session) { _newState = newState; _accountId = accountId; log('EmailChangeListener::_pushNotificationAction():newState: $newState'); @@ -116,8 +118,9 @@ class EmailChangeListener extends ChangeListener { } void _getEmailChangesAction(jmap.State state) { - if (_getEmailChangesToPushNotificationInteractor != null && _accountId != null) { + if (_getEmailChangesToPushNotificationInteractor != null && _accountId != null && _session != null) { consumeState(_getEmailChangesToPushNotificationInteractor!.execute( + _session!, _accountId!, state, propertiesCreated: ThreadConstants.propertiesDefault, diff --git a/lib/features/search/email/domain/usecases/refresh_changes_search_email_interactor.dart b/lib/features/search/email/domain/usecases/refresh_changes_search_email_interactor.dart index 7c36cab07..b783044ab 100644 --- a/lib/features/search/email/domain/usecases/refresh_changes_search_email_interactor.dart +++ b/lib/features/search/email/domain/usecases/refresh_changes_search_email_interactor.dart @@ -5,6 +5,7 @@ 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/session/session.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart'; import 'package:model/extensions/email_extension.dart'; @@ -18,23 +19,25 @@ class RefreshChangesSearchEmailInteractor { RefreshChangesSearchEmailInteractor(this.threadRepository); Stream> execute( - AccountId accountId, - { - UnsignedInt? limit, - Set? sort, - Filter? filter, - Properties? properties, - } + Session session, + AccountId accountId, + { + UnsignedInt? limit, + Set? sort, + Filter? filter, + Properties? properties, + } ) async* { try { yield Right(RefreshingChangeSearchEmailState()); final emailList = await threadRepository.searchEmails( - accountId, - limit: limit, - sort: sort, - filter: filter, - properties: properties); + session, + accountId, + limit: limit, + sort: sort, + filter: filter, + properties: properties); final presentationEmailList = emailList .map((email) => email.toPresentationEmail()) diff --git a/lib/features/search/email/presentation/search_email_controller.dart b/lib/features/search/email/presentation/search_email_controller.dart index c1e2f92fd..b0071f4e2 100644 --- a/lib/features/search/email/presentation/search_email_controller.dart +++ b/lib/features/search/email/presentation/search_email_controller.dart @@ -172,8 +172,8 @@ class SearchEmailController extends BaseController textOption: value.isNotEmpty ? Some(SearchQuery(value)) : const None(), beforeOption: const None() ); - if (value.isNotEmpty && accountId != null) { - listSuggestionSearch.value = await quickSearchEmails(accountId: accountId!); + if (value.isNotEmpty && session != null && accountId != null) { + listSuggestionSearch.value = await quickSearchEmails(session: session!, accountId: accountId!); } else { listSuggestionSearch.clear(); } @@ -215,12 +215,13 @@ class SearchEmailController extends BaseController } void _refreshEmailChanges() { - if (searchIsRunning.isTrue && accountId != null) { + if (searchIsRunning.isTrue && session != null && accountId != null) { final limit = listResultSearch.isNotEmpty ? UnsignedInt(listResultSearch.length) : ThreadConstants.defaultLimit; _updateSimpleSearchFilter(beforeOption: const None()); consumeState(_refreshChangesSearchEmailInteractor.execute( + session!, accountId!, limit: limit, sort: {} @@ -259,15 +260,20 @@ class SearchEmailController extends BaseController : [])); } - Future> quickSearchEmails({required AccountId accountId}) async { + Future> quickSearchEmails({ + required AccountId accountId, + required Session session, + }) async { return _quickSearchEmailInteractor - .execute(accountId, - limit: UnsignedInt(5), + .execute( + session, + accountId, + limit: UnsignedInt(5), sort: {}..add( - EmailComparator(EmailComparatorProperty.receivedAt) - ..setIsAscending(false)), - filter: simpleSearchFilter.value.mappingToEmailFilterCondition(), - properties: ThreadConstants.propertiesQuickSearch) + EmailComparator(EmailComparatorProperty.receivedAt) + ..setIsAscending(false)), + filter: simpleSearchFilter.value.mappingToEmailFilterCondition(), + properties: ThreadConstants.propertiesQuickSearch) .then((result) => result.fold( (failure) => [], (success) => success is QuickSearchEmailSuccess @@ -282,12 +288,13 @@ class SearchEmailController extends BaseController void _searchEmailAction(BuildContext context) { FocusScope.of(context).unfocus(); - if (accountId != null) { + if (session != null && accountId != null) { canSearchMore = true; searchIsRunning.value = true; cancelSelectionMode(context); consumeState(_searchEmailInteractor.execute( + session!, accountId!, limit: ThreadConstants.defaultLimit, sort: {} @@ -327,19 +334,20 @@ class SearchEmailController extends BaseController } void searchMoreEmailsAction() { - if (canSearchMore && accountId != null) { + if (canSearchMore && session != null && accountId != null) { final lastEmail = listResultSearch.last; _updateSimpleSearchFilter(beforeOption: optionOf(lastEmail.receivedAt)); consumeState(_searchMoreEmailInteractor.execute( - accountId!, - limit: ThreadConstants.defaultLimit, - sort: {} - ..add(EmailComparator(EmailComparatorProperty.receivedAt) - ..setIsAscending(false)), - filter: simpleSearchFilter.value.mappingToEmailFilterCondition(), - properties: ThreadConstants.propertiesDefault, - lastEmailId: lastEmail.id + session!, + accountId!, + limit: ThreadConstants.defaultLimit, + sort: {} + ..add(EmailComparator(EmailComparatorProperty.receivedAt) + ..setIsAscending(false)), + filter: simpleSearchFilter.value.mappingToEmailFilterCondition(), + properties: ThreadConstants.propertiesDefault, + lastEmailId: lastEmail.id )); } } diff --git a/lib/features/thread/data/datasource/thread_datasource.dart b/lib/features/thread/data/datasource/thread_datasource.dart index fbb4fa334..d85dd6e62 100644 --- a/lib/features/thread/data/datasource/thread_datasource.dart +++ b/lib/features/thread/data/datasource/thread_datasource.dart @@ -3,6 +3,7 @@ import 'dart:async'; 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/session/session.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'; @@ -15,6 +16,7 @@ import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option abstract class ThreadDataSource { Future getAllEmail( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -25,6 +27,7 @@ abstract class ThreadDataSource { ); Future getChanges( + Session session, AccountId accountId, State sinceState, { @@ -38,10 +41,11 @@ abstract class ThreadDataSource { Future update({List? updated, List? created, List? destroyed}); Future> emptyTrashFolder( - AccountId accountId, - MailboxId mailboxId, - Future Function(List? newDestroyed) updateDestroyedEmailCache, + Session session, + AccountId accountId, + MailboxId mailboxId, + Future Function(List? newDestroyed) updateDestroyedEmailCache, ); - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}); + Future getEmailById(Session session, AccountId accountId, EmailId emailId, {Properties? properties}); } \ No newline at end of file diff --git a/lib/features/thread/data/datasource_impl/local_thread_datasource_impl.dart b/lib/features/thread/data/datasource_impl/local_thread_datasource_impl.dart index 382b48b0d..44f285845 100644 --- a/lib/features/thread/data/datasource_impl/local_thread_datasource_impl.dart +++ b/lib/features/thread/data/datasource_impl/local_thread_datasource_impl.dart @@ -3,6 +3,7 @@ import 'dart:async'; 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/session/session.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'; @@ -25,25 +26,27 @@ class LocalThreadDataSourceImpl extends ThreadDataSource { @override Future getAllEmail( - AccountId accountId, - { - UnsignedInt? limit, - Set? sort, - Filter? filter, - Properties? properties - } + Session session, + AccountId accountId, + { + UnsignedInt? limit, + Set? sort, + Filter? filter, + Properties? properties + } ) { throw UnimplementedError(); } @override Future getChanges( - AccountId accountId, - State sinceState, - { - Properties? propertiesCreated, - Properties? propertiesUpdated - } + Session session, + AccountId accountId, + State sinceState, + { + Properties? propertiesCreated, + Properties? propertiesUpdated + } ) { throw UnimplementedError(); } @@ -80,6 +83,7 @@ class LocalThreadDataSourceImpl extends ThreadDataSource { @override Future> emptyTrashFolder( + Session session, AccountId accountId, MailboxId mailboxId, Future Function(List? newDestroyed) updateDestroyedEmailCache @@ -88,7 +92,7 @@ class LocalThreadDataSourceImpl extends ThreadDataSource { } @override - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}) { + Future getEmailById(Session session, AccountId accountId, EmailId emailId, {Properties? properties}) { throw UnimplementedError(); } } \ No newline at end of file diff --git a/lib/features/thread/data/datasource_impl/thread_datasource_impl.dart b/lib/features/thread/data/datasource_impl/thread_datasource_impl.dart index 328d0b052..cb0b55918 100644 --- a/lib/features/thread/data/datasource_impl/thread_datasource_impl.dart +++ b/lib/features/thread/data/datasource_impl/thread_datasource_impl.dart @@ -3,6 +3,7 @@ import 'dart:async'; 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/session/session.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'; @@ -32,6 +33,7 @@ class ThreadDataSourceImpl extends ThreadDataSource { @override Future getAllEmail( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -42,6 +44,7 @@ class ThreadDataSourceImpl extends ThreadDataSource { ) { return Future.sync(() async { return await threadAPI.getAllEmail( + session, accountId, limit: limit, sort: sort, @@ -52,15 +55,17 @@ class ThreadDataSourceImpl extends ThreadDataSource { @override Future getChanges( - AccountId accountId, - State sinceState, - { - Properties? propertiesCreated, - Properties? propertiesUpdated - } + Session session, + AccountId accountId, + State sinceState, + { + Properties? propertiesCreated, + Properties? propertiesUpdated + } ) { return Future.sync(() async { return await threadAPI.getChanges( + session, accountId, sinceState, propertiesCreated: propertiesCreated, @@ -79,20 +84,26 @@ class ThreadDataSourceImpl extends ThreadDataSource { } @override - Future> emptyTrashFolder(AccountId accountId, MailboxId mailboxId, Future Function(List? newDestroyed) updateDestroyedEmailCache) { + Future> emptyTrashFolder( + Session session, + AccountId accountId, + MailboxId mailboxId, + Future Function(List? newDestroyed) updateDestroyedEmailCache + ) { return Future.sync(() async { return await _threadIsolateWorker.emptyTrashFolder( - accountId, - mailboxId, - updateDestroyedEmailCache, + session, + accountId, + mailboxId, + updateDestroyedEmailCache, ); }).catchError(_exceptionThrower.throwException); } @override - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}) { + Future getEmailById(Session session, AccountId accountId, EmailId emailId, {Properties? properties}) { return Future.sync(() async { - final email = await threadAPI.getEmailById(accountId, emailId, properties: properties); + final email = await threadAPI.getEmailById(session, accountId, emailId, properties: properties); return email.toPresentationEmail(); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/thread/data/model/empty_trash_folder_arguments.dart b/lib/features/thread/data/model/empty_trash_folder_arguments.dart index fc3e89399..ade64b69e 100644 --- a/lib/features/thread/data/model/empty_trash_folder_arguments.dart +++ b/lib/features/thread/data/model/empty_trash_folder_arguments.dart @@ -1,16 +1,19 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; class EmptyTrashFolderArguments with EquatableMixin { + final Session session; final AccountId accountId; final MailboxId trashMailboxId; final ThreadAPI threadAPI; final EmailAPI emailAPI; EmptyTrashFolderArguments( + this.session, this.threadAPI, this.emailAPI, this.accountId, @@ -18,5 +21,11 @@ class EmptyTrashFolderArguments with EquatableMixin { ); @override - List get props => [accountId, trashMailboxId]; + List get props => [ + session, + accountId, + emailAPI, + threadAPI, + trashMailboxId + ]; } diff --git a/lib/features/thread/data/network/thread_api.dart b/lib/features/thread/data/network/thread_api.dart index a00084af4..ff513344f 100644 --- a/lib/features/thread/data/network/thread_api.dart +++ b/lib/features/thread/data/network/thread_api.dart @@ -2,9 +2,11 @@ import 'dart:async'; import 'package:jmap_dart_client/http/http_client.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.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/request/reference_path.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.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'; @@ -17,6 +19,7 @@ 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'; +import 'package:tmail_ui_user/main/error/capability_validator.dart'; class ThreadAPI { @@ -24,7 +27,25 @@ class ThreadAPI { ThreadAPI(this.httpClient); + Set _capabilitiesForEmailMethod(Session session, AccountId accountId) { + final getMailboxCreated = GetEmailMethod(accountId); + try { + requireCapability( + session, + accountId, + [CapabilityIdentifier.jmapTeamMailboxes]); + return { + CapabilityIdentifier.jmapCore, + CapabilityIdentifier.jmapMail, + CapabilityIdentifier.jmapTeamMailboxes + }; + } catch (_) { + return getMailboxCreated.requiredCapabilities; + } + } + Future getAllEmail( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -58,7 +79,7 @@ class ThreadAPI { final getEmailInvocation = jmapRequestBuilder.invocation(getEmailMethod); final result = await (jmapRequestBuilder - ..usings(getEmailMethod.requiredCapabilities)) + ..usings(_capabilitiesForEmailMethod(session, accountId))) .build() .execute(); @@ -75,6 +96,7 @@ class ThreadAPI { } Future getChanges( + Session session, AccountId accountId, State sinceState, { @@ -112,7 +134,7 @@ class ThreadAPI { final getEmailCreatedInvocation = jmapRequestBuilder.invocation(getEmailCreated); final result = await (jmapRequestBuilder - ..usings(getEmailCreated.requiredCapabilities)) + ..usings(_capabilitiesForEmailMethod(session, accountId))) .build() .execute(); @@ -140,7 +162,7 @@ class ThreadAPI { updatedProperties: propertiesUpdated); } - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}) async { + Future getEmailById(Session session, AccountId accountId, EmailId emailId, {Properties? properties}) async { final processingInvocation = ProcessingInvocation(); final jmapRequestBuilder = JmapRequestBuilder(httpClient, processingInvocation); @@ -154,7 +176,7 @@ class ThreadAPI { final getEmailInvocation = jmapRequestBuilder.invocation(getEmailMethod); final result = await (jmapRequestBuilder - ..usings(getEmailMethod.requiredCapabilities)) + ..usings(_capabilitiesForEmailMethod(session, accountId))) .build() .execute(); diff --git a/lib/features/thread/data/network/thread_isolate_worker.dart b/lib/features/thread/data/network/thread_isolate_worker.dart index 26b9f92e6..6fa39de4c 100644 --- a/lib/features/thread/data/network/thread_isolate_worker.dart +++ b/lib/features/thread/data/network/thread_isolate_worker.dart @@ -4,6 +4,7 @@ import 'package:core/utils/app_logger.dart'; import 'package:core/utils/build_utils.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart'; @@ -25,15 +26,16 @@ class ThreadIsolateWorker { ThreadIsolateWorker(this._threadAPI, this._emailAPI, this._isolateExecutor); Future> emptyTrashFolder( + Session session, AccountId accountId, MailboxId mailboxId, Future Function(List? newDestroyed) updateDestroyedEmailCache, ) async { if (BuildUtils.isWeb) { - return _emptyTrashFolderOnWeb(accountId, mailboxId, updateDestroyedEmailCache); + return _emptyTrashFolderOnWeb(session, accountId, mailboxId, updateDestroyedEmailCache); } else { final result = await _isolateExecutor.execute( - arg1: EmptyTrashFolderArguments(_threadAPI, _emailAPI, accountId, mailboxId), + arg1: EmptyTrashFolderArguments(session, _threadAPI, _emailAPI, accountId, mailboxId), fun1: _emptyTrashFolderAction, notification: (value) { if (value is List) { @@ -52,12 +54,14 @@ class ThreadIsolateWorker { Email? lastEmail; while (hasEmails) { - final emailsResponse = await args.threadAPI.getAllEmail(args.accountId, - sort: {}..add( - EmailComparator(EmailComparatorProperty.receivedAt) - ..setIsAscending(false)), - filter: EmailFilterCondition(inMailbox: args.trashMailboxId, before: lastEmail?.receivedAt), - properties: Properties({EmailProperty.id})); + final emailsResponse = await args.threadAPI.getAllEmail( + args.session, + args.accountId, + sort: {}..add( + EmailComparator(EmailComparatorProperty.receivedAt) + ..setIsAscending(false)), + filter: EmailFilterCondition(inMailbox: args.trashMailboxId, before: lastEmail?.receivedAt), + properties: Properties({EmailProperty.id})); var newEmailList = emailsResponse.emailList ?? []; if (lastEmail != null) { @@ -89,6 +93,7 @@ class ThreadIsolateWorker { } Future> _emptyTrashFolderOnWeb( + Session session, AccountId accountId, MailboxId trashMailboxId, Future Function(List newDestroyed) updateDestroyedEmailCache, @@ -99,12 +104,14 @@ class ThreadIsolateWorker { Email? lastEmail; while (hasEmails) { - final emailsResponse = await _threadAPI.getAllEmail(accountId, - sort: {}..add( - EmailComparator(EmailComparatorProperty.receivedAt) - ..setIsAscending(false)), - filter: EmailFilterCondition(inMailbox: trashMailboxId, before: lastEmail?.receivedAt), - properties: Properties({EmailProperty.id})); + final emailsResponse = await _threadAPI.getAllEmail( + session, + accountId, + sort: {}..add( + EmailComparator(EmailComparatorProperty.receivedAt) + ..setIsAscending(false)), + filter: EmailFilterCondition(inMailbox: trashMailboxId, before: lastEmail?.receivedAt), + properties: Properties({EmailProperty.id})); var newEmailList = emailsResponse.emailList ?? []; if (lastEmail != null) { diff --git a/lib/features/thread/data/repository/thread_repository_impl.dart b/lib/features/thread/data/repository/thread_repository_impl.dart index 79ca91efe..f9829d27f 100644 --- a/lib/features/thread/data/repository/thread_repository_impl.dart +++ b/lib/features/thread/data/repository/thread_repository_impl.dart @@ -4,6 +4,7 @@ import 'package:dartz/dartz.dart' as dartz; 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/session/session.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'; @@ -32,6 +33,7 @@ class ThreadRepositoryImpl extends ThreadRepository { @override Stream getAllEmail( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -58,6 +60,7 @@ class ThreadRepositoryImpl extends ThreadRepository { if (!localEmailResponse.hasEmails() || (localEmailResponse.emailList?.length ?? 0) < ThreadConstants.defaultLimit.value) { networkEmailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail( + session, accountId, limit: limit, sort: sort, @@ -65,6 +68,7 @@ class ThreadRepositoryImpl extends ThreadRepository { properties: propertiesCreated); if (_isApproveFilterOption(emailFilter?.filterOption, networkEmailResponse.emailList)) { _getFirstPage( + session, accountId, sort: sort, mailboxId: emailFilter?.mailboxId, @@ -83,6 +87,7 @@ class ThreadRepositoryImpl extends ThreadRepository { if (localEmailResponse.hasState()) { log('ThreadRepositoryImpl::getAllEmail(): filter = ${emailFilter?.mailboxId} local has state: ${localEmailResponse.state}'); await _synchronizeCacheWithChanges( + session, accountId, localEmailResponse.state!, propertiesCreated: propertiesCreated, @@ -116,6 +121,7 @@ class ThreadRepositoryImpl extends ThreadRepository { } Future _getFirstPage( + Session session, AccountId accountId, { Set? sort, @@ -125,6 +131,7 @@ class ThreadRepositoryImpl extends ThreadRepository { } ) async { final networkEmailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail( + session, accountId, limit: ThreadConstants.defaultLimit, sort: sort, @@ -187,17 +194,19 @@ class ThreadRepositoryImpl extends ThreadRepository { @override Stream refreshChanges( - AccountId accountId, - State currentState, - { - Set? sort, - EmailFilter? emailFilter, - Properties? propertiesCreated, - Properties? propertiesUpdated, - } + Session session, + AccountId accountId, + State currentState, + { + Set? sort, + EmailFilter? emailFilter, + Properties? propertiesCreated, + Properties? propertiesUpdated, + } ) async* { log('ThreadRepositoryImpl::refreshChanges(): $currentState'); await _synchronizeCacheWithChanges( + session, accountId, currentState, propertiesCreated: propertiesCreated, @@ -214,6 +223,7 @@ class ThreadRepositoryImpl extends ThreadRepository { if (!newEmailResponse.hasEmails() || (newEmailResponse.emailList?.length ?? 0) < ThreadConstants.defaultLimit.value) { final networkEmailResponse = await _getFirstPage( + session, accountId, sort: sort, filter: emailFilter?.filter, @@ -237,14 +247,15 @@ class ThreadRepositoryImpl extends ThreadRepository { 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) + emailRequest.session, + emailRequest.accountId, + limit: emailRequest.limit, + sort: emailRequest.sort, + filter: emailRequest.filter, + properties: emailRequest.properties) .then((response) { - var listEmails = response.emailList; - return EmailsResponse(emailList: listEmails, state: response.state); + final listEmails = response.emailList; + return EmailsResponse(emailList: listEmails, state: response.state); }); return emailResponse; @@ -252,6 +263,7 @@ class ThreadRepositoryImpl extends ThreadRepository { @override Future> searchEmails( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -261,6 +273,7 @@ class ThreadRepositoryImpl extends ThreadRepository { } ) async { final emailResponse = await mapDataSource[DataSourceType.network]!.getAllEmail( + session, accountId, limit: limit, sort: sort, @@ -271,8 +284,9 @@ class ThreadRepositoryImpl extends ThreadRepository { } @override - Future> emptyTrashFolder(AccountId accountId, MailboxId trashMailboxId) async { + Future> emptyTrashFolder(Session session, AccountId accountId, MailboxId trashMailboxId) async { return mapDataSource[DataSourceType.network]!.emptyTrashFolder( + session, accountId, trashMailboxId, (listEmailIdDeleted) async { @@ -282,6 +296,7 @@ class ThreadRepositoryImpl extends ThreadRepository { } Future _synchronizeCacheWithChanges( + Session session, AccountId accountId, State currentState, { @@ -299,10 +314,11 @@ class ThreadRepositoryImpl extends ThreadRepository { while(hasMoreChanges && sinceState != null) { log('ThreadRepositoryImpl::_synchronizeCacheWithChanges(): sinceState = $sinceState'); final changesResponse = await mapDataSource[DataSourceType.network]!.getChanges( - accountId, - sinceState, - propertiesCreated: propertiesCreated, - propertiesUpdated: propertiesUpdated); + session, + accountId, + sinceState, + propertiesCreated: propertiesCreated, + propertiesUpdated: propertiesUpdated); hasMoreChanges = changesResponse.hasMoreChanges; sinceState = changesResponse.newStateChanges; @@ -337,7 +353,12 @@ class ThreadRepositoryImpl extends ThreadRepository { } @override - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}) { - return mapDataSource[DataSourceType.network]!.getEmailById(accountId, emailId, properties: properties); + Future getEmailById( + Session session, + AccountId accountId, + EmailId emailId, + {Properties? properties} + ) { + return mapDataSource[DataSourceType.network]!.getEmailById(session, accountId, emailId, properties: properties); } } \ No newline at end of file diff --git a/lib/features/thread/domain/model/get_email_request.dart b/lib/features/thread/domain/model/get_email_request.dart index 54541c0b4..d443288c4 100644 --- a/lib/features/thread/domain/model/get_email_request.dart +++ b/lib/features/thread/domain/model/get_email_request.dart @@ -2,12 +2,14 @@ import 'package:equatable/equatable.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/session/session.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/core/sort/comparator.dart'; import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart'; class GetEmailRequest with EquatableMixin { + final Session session; final AccountId accountId; final UnsignedInt? limit; final Set? sort; @@ -16,15 +18,28 @@ class GetEmailRequest with EquatableMixin { final Properties? properties; final EmailId? lastEmailId; - GetEmailRequest(this.accountId, { - this.limit, - this.sort, - this.filter, - this.filterOption, - this.properties, - this.lastEmailId, - }); + GetEmailRequest( + this.session, + this.accountId, + { + this.limit, + this.sort, + this.filter, + this.filterOption, + this.properties, + this.lastEmailId, + } + ); @override - List get props => [limit, sort, filter, properties, lastEmailId, filterOption]; + List get props => [ + session, + accountId, + limit, + sort, + filter, + properties, + lastEmailId, + filterOption + ]; } \ 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 f82e836cc..109db2ae0 100644 --- a/lib/features/thread/domain/repository/thread_repository.dart +++ b/lib/features/thread/domain/repository/thread_repository.dart @@ -3,6 +3,7 @@ import 'dart:async'; 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/session/session.dart'; 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/unsigned_int.dart'; @@ -15,6 +16,7 @@ import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dar abstract class ThreadRepository { Stream getAllEmail( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -26,6 +28,7 @@ abstract class ThreadRepository { ); Stream refreshChanges( + Session session, AccountId accountId, jmap.State currentState, { @@ -39,6 +42,7 @@ abstract class ThreadRepository { Stream loadMoreEmails(GetEmailRequest emailRequest); Future> searchEmails( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -49,9 +53,15 @@ abstract class ThreadRepository { ); Future> emptyTrashFolder( - AccountId accountId, - MailboxId trashMailboxId, + Session session, + AccountId accountId, + MailboxId trashMailboxId, ); - Future getEmailById(AccountId accountId, EmailId emailId, {Properties? properties}); + Future getEmailById( + Session session, + AccountId accountId, + EmailId emailId, + {Properties? properties} + ); } \ No newline at end of file diff --git a/lib/features/thread/domain/usecases/empty_trash_folder_interactor.dart b/lib/features/thread/domain/usecases/empty_trash_folder_interactor.dart index d74ea460f..52efcf500 100644 --- a/lib/features/thread/domain/usecases/empty_trash_folder_interactor.dart +++ b/lib/features/thread/domain/usecases/empty_trash_folder_interactor.dart @@ -1,6 +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/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; @@ -18,7 +19,7 @@ class EmptyTrashFolderInteractor { this._emailRepository ); - Stream> execute(AccountId accountId, MailboxId trashMailboxId) async* { + Stream> execute(Session session, AccountId accountId, MailboxId trashMailboxId) async* { try { yield Right(LoadingState()); @@ -30,7 +31,7 @@ class EmptyTrashFolderInteractor { final currentMailboxState = listState.first; final currentEmailState = listState.last; - final result = await threadRepository.emptyTrashFolder(accountId, trashMailboxId); + final result = await threadRepository.emptyTrashFolder(session, accountId, trashMailboxId); if (result.isNotEmpty) { yield Right(EmptyTrashFolderSuccess( currentMailboxState: currentMailboxState, diff --git a/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart b/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart index 91c2a9f30..88f0915d5 100644 --- a/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart +++ b/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart @@ -3,6 +3,7 @@ import 'package:core/presentation/state/success.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/state/get_email_by_id_state.dart'; @@ -13,6 +14,7 @@ class GetEmailByIdInteractor { GetEmailByIdInteractor(this._threadRepository); Stream> execute( + Session session, AccountId accountId, EmailId emailId, { @@ -21,7 +23,7 @@ class GetEmailByIdInteractor { ) async* { try { yield Right(GetEmailByIdLoading()); - final email = await _threadRepository.getEmailById(accountId, emailId, properties: properties); + final email = await _threadRepository.getEmailById(session, accountId, emailId, properties: properties); yield Right(GetEmailByIdSuccess(email)); } catch (e) { yield Left(GetEmailByIdFailure(e)); 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 a28b1f9e8..930f1acf7 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 @@ -2,6 +2,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/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.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_filter.dart'; @@ -16,6 +17,7 @@ class GetEmailsInMailboxInteractor { GetEmailsInMailboxInteractor(this.threadRepository); Stream> execute( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -30,6 +32,7 @@ class GetEmailsInMailboxInteractor { yield* threadRepository .getAllEmail( + session, accountId, limit: limit, sort: sort, diff --git a/lib/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart b/lib/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart index 73a75689c..808f365a0 100644 --- a/lib/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart +++ b/lib/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart @@ -2,6 +2,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/properties/properties.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/sort/comparator.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_filter.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; @@ -16,6 +17,7 @@ class RefreshChangesEmailsInMailboxInteractor { RefreshChangesEmailsInMailboxInteractor(this.threadRepository); Stream> execute( + Session session, AccountId accountId, jmap.State currentState, { @@ -30,6 +32,7 @@ class RefreshChangesEmailsInMailboxInteractor { try { yield* threadRepository .refreshChanges( + session, accountId, currentState, sort: sort, diff --git a/lib/features/thread/domain/usecases/search_email_interactor.dart b/lib/features/thread/domain/usecases/search_email_interactor.dart index ab9515bfb..a84318bb8 100644 --- a/lib/features/thread/domain/usecases/search_email_interactor.dart +++ b/lib/features/thread/domain/usecases/search_email_interactor.dart @@ -1,5 +1,6 @@ import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:model/model.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; @@ -17,6 +18,7 @@ class SearchEmailInteractor { SearchEmailInteractor(this.threadRepository); Stream> execute( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -29,6 +31,7 @@ class SearchEmailInteractor { yield Right(SearchingState()); final emailList = await threadRepository.searchEmails( + session, accountId, limit: limit, sort: sort, diff --git a/lib/features/thread/domain/usecases/search_more_email_interactor.dart b/lib/features/thread/domain/usecases/search_more_email_interactor.dart index 06ea63da0..c25ef39f5 100644 --- a/lib/features/thread/domain/usecases/search_more_email_interactor.dart +++ b/lib/features/thread/domain/usecases/search_more_email_interactor.dart @@ -1,5 +1,6 @@ import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/model.dart'; import 'package:dartz/dartz.dart'; @@ -18,6 +19,7 @@ class SearchMoreEmailInteractor { SearchMoreEmailInteractor(this.threadRepository); Stream> execute( + Session session, AccountId accountId, { UnsignedInt? limit, @@ -31,6 +33,7 @@ class SearchMoreEmailInteractor { yield Right(SearchingMoreState()); final emailList = await threadRepository.searchEmails( + session, accountId, limit: limit, sort: sort, diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index fe9a7964d..49edac777 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; 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/unsigned_int.dart'; @@ -104,6 +105,8 @@ class ThreadController extends BaseController with EmailActionController { AccountId? get _accountId => mailboxDashBoardController.accountId.value; + Session? get _session => mailboxDashBoardController.sessionCurrent; + PresentationMailbox? get currentMailbox => mailboxDashBoardController.selectedMailbox.value; SearchController get searchController => mailboxDashBoardController.searchController; @@ -387,8 +390,9 @@ class ThreadController extends BaseController with EmailActionController { } void _getAllEmailAction() { - if (_accountId != null) { + if (_session != null &&_accountId != null) { consumeState(_getEmailsInMailboxInteractor.execute( + _session!, _accountId!, limit: ThreadConstants.defaultLimit, sort: _sortOrder, @@ -458,8 +462,9 @@ class ThreadController extends BaseController with EmailActionController { } else { final newEmailState = currentEmailState ?? _currentEmailState; log('ThreadController::_refreshEmailChanges(): newEmailState: $newEmailState'); - if (_accountId != null && newEmailState != null) { + if (_session != null && _accountId != null && newEmailState != null) { consumeState(_refreshChangesEmailsInMailboxInteractor.execute( + _session!, _accountId!, newEmailState, sort: _sortOrder, @@ -477,12 +482,13 @@ class ThreadController extends BaseController with EmailActionController { void loadMoreEmails() { log('ThreadController::loadMoreEmails()'); - if (canLoadMore && _accountId != null) { + if (canLoadMore && _session != null && _accountId != null) { final oldestEmail = mailboxDashBoardController.emailsInCurrentMailbox.isNotEmpty ? mailboxDashBoardController.emailsInCurrentMailbox.last : null; consumeState(_loadMoreEmailsInMailboxInteractor.execute( GetEmailRequest( + _session!, _accountId!, limit: ThreadConstants.defaultLimit, sort: _sortOrder, @@ -665,7 +671,7 @@ class ThreadController extends BaseController with EmailActionController { } void _searchEmail({UnsignedInt? limit}) { - if (_accountId != null) { + if (_session != null && _accountId != null) { if (listEmailController.hasClients) { listEmailController.jumpTo(0); } @@ -676,6 +682,7 @@ class ThreadController extends BaseController with EmailActionController { searchController.activateSimpleSearch(); consumeState(_searchEmailInteractor.execute( + _session!, _accountId!, limit: limit ?? ThreadConstants.defaultLimit, sort: _sortOrder, @@ -716,12 +723,13 @@ class ThreadController extends BaseController with EmailActionController { } void searchMoreEmails() { - if (canSearchMore && _accountId != null) { + if (canSearchMore && _session != null && _accountId != null) { final oldestEmail = mailboxDashBoardController.emailsInCurrentMailbox.isNotEmpty ? mailboxDashBoardController.emailsInCurrentMailbox.last : null; searchController.updateFilterEmail(beforeOption: optionOf(oldestEmail?.receivedAt)); consumeState(_searchMoreEmailInteractor.execute( + _session!, _accountId!, limit: ThreadConstants.defaultLimit, sort: _sortOrder, @@ -935,8 +943,9 @@ class ThreadController extends BaseController with EmailActionController { } void _getEmailByIdAction(EmailId emailId) { - if (_accountId != null) { + if (_session != null && _accountId != null) { consumeState(_getEmailByIdInteractor.execute( + _session!, _accountId!, emailId, properties: ThreadConstants.propertiesDefault)); diff --git a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.dart b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.dart index 3e058158f..2bafd0e37 100644 --- a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.dart +++ b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.dart @@ -21,6 +21,7 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mail import '../../../../fixtures/account_fixtures.dart'; import '../../../../fixtures/email_fixtures.dart'; import '../../../../fixtures/mailbox_fixtures.dart'; +import '../../../../fixtures/session_fixtures.dart'; import 'get_emails_in_mailbox_interactor_test.mocks.dart'; @GenerateMocks([ThreadRepository]) @@ -37,6 +38,7 @@ void main() { test('getEmailsInMailboxInteractor should execute to get all email from cache and network', () async { when(threadRepository.getAllEmail( + SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, limit: UnsignedInt(20), sort: {}..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), @@ -65,6 +67,7 @@ void main() { })); final streamStates = getEmailsInMailboxInteractor.execute( + SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, limit: UnsignedInt(20), sort: {}..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), diff --git a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.dart b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.dart index 7bee43737..d80637b47 100644 --- a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.dart +++ b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.dart @@ -19,6 +19,7 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_em import '../../../../fixtures/account_fixtures.dart'; import '../../../../fixtures/email_fixtures.dart'; import '../../../../fixtures/mailbox_fixtures.dart'; +import '../../../../fixtures/session_fixtures.dart'; import '../../../../fixtures/state_fixtures.dart'; import 'refresh_changes_emails_in_mailbox_interactor_test.mocks.dart'; @@ -36,6 +37,7 @@ void main() { test('refreshChangesEmailsInMailboxInteractor should execute to get changes email from cache and network', () async { when(threadRepository.refreshChanges( + SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, StateFixtures.currentEmailState, sort: {}..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), @@ -56,6 +58,7 @@ void main() { })); final streamStates = refreshChangesEmailsInMailboxInteractor.execute( + SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, StateFixtures.currentEmailState, sort: {}..add(EmailComparator(EmailComparatorProperty.sentAt)..setIsAscending(false)), diff --git a/test/fixtures/session_fixtures.dart b/test/fixtures/session_fixtures.dart new file mode 100644 index 000000000..5340a5ce6 --- /dev/null +++ b/test/fixtures/session_fixtures.dart @@ -0,0 +1,102 @@ +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/account/account.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; +import 'package:jmap_dart_client/jmap/core/capability/core_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/default_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/mail_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/mdn_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/submission_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/vacation_capability.dart'; +import 'package:jmap_dart_client/jmap/core/capability/websocket_capability.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/sort/collation_identifier.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/core/user_name.dart'; + +class SessionFixtures { + static final aliceSession = Session( + { + CapabilityIdentifier.jmapSubmission: SubmissionCapability(UnsignedInt(0), {}), + CapabilityIdentifier.jmapCore: CoreCapability( + UnsignedInt(20971520), + UnsignedInt(4), + UnsignedInt(10000000), + UnsignedInt(4), + UnsignedInt(16), + UnsignedInt(500), + UnsignedInt(500), + {CollationIdentifier("i;unicode-casemap")} + ), + CapabilityIdentifier.jmapMail: MailCapability( + UnsignedInt(10000000), + null, + UnsignedInt(200), + UnsignedInt(20000000), + {"receivedAt", "sentAt", "size", "from", "to", "subject"}, + true + ), + CapabilityIdentifier.jmapWebSocket: WebSocketCapability( + true, + Uri.parse('ws://domain.com/jmap/ws') + ), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:quota')): DefaultCapability({}), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:shares')): DefaultCapability({}), + CapabilityIdentifier.jmapVacationResponse: VacationCapability(), + CapabilityIdentifier.jmapMdn: MdnCapability(), + }, + { + AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')): Account( + AccountName('bob@domain.tld'), + true, + false, + { + CapabilityIdentifier.jmapSubmission: SubmissionCapability(UnsignedInt(0), {}), + CapabilityIdentifier.jmapWebSocket: WebSocketCapability( + true, + Uri.parse('ws://domain.com/jmap/ws') + ), + CapabilityIdentifier.jmapCore: CoreCapability( + UnsignedInt(20971520), + UnsignedInt(4), + UnsignedInt(10000000), + UnsignedInt(4), + UnsignedInt(16), + UnsignedInt(500), + UnsignedInt(500), + {CollationIdentifier("i;unicode-casemap")} + ), + CapabilityIdentifier.jmapMail: MailCapability( + UnsignedInt(10000000), + null, + UnsignedInt(200), + UnsignedInt(20000000), + {"receivedAt", "sentAt", "size", "from", "to", "subject"}, + true + ), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:quota')): DefaultCapability({}), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:shares')): DefaultCapability({}), + CapabilityIdentifier.jmapVacationResponse: VacationCapability(), + CapabilityIdentifier.jmapMdn: MdnCapability() + } + ) + }, + { + CapabilityIdentifier.jmapSubmission: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapWebSocket: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapCore: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapMail: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:quota')): AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:shares')): AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapVacationResponse: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapMdn: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + }, + UserName('bob@domain.tld'), + Uri.parse('http://domain.com/jmap'), + Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), + Uri.parse('http://domain.com/upload/{accountId}'), + Uri.parse('http://domain.com/eventSource?types={types}&closeAfter={closeafter}&ping={ping}'), + State('2c9f1b12-b35a-43e6-9af2-0106fb53a943') + ); +} \ No newline at end of file