From ad5dff4ac840db5523cf8236d9d412f633c66705 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 27 Oct 2023 20:46:17 +0700 Subject: [PATCH] TF-2280 Fix mark as read mailbox when token expired on mobile Signed-off-by: dab246 (cherry picked from commit caab5a896875168f2d98c249207eb3eb537c58ec) --- .../caching/config/hive_cache_config.dart | 15 ++- .../authentication_client_base.dart | 2 +- .../authentication_client_mobile.dart | 4 +- .../authentication_client_web.dart | 4 +- .../config/authorization_interceptors.dart | 125 ++++++++++-------- .../model/mailbox_mark_as_read_arguments.dart | 9 +- .../data/network/mailbox_isolate_worker.dart | 16 ++- .../state/mark_as_mailbox_read_state.dart | 16 ++- .../mark_as_mailbox_read_interactor.dart | 7 +- .../mailbox_dashboard_controller.dart | 26 +++- lib/l10n/intl_messages.arb | 24 +++- .../local/local_isolate_bindings.dart | 35 +++++ lib/main/bindings/main_bindings.dart | 2 + .../network/network_isolate_binding.dart | 11 +- lib/main/exceptions/isolate_exception.dart | 1 + lib/main/localizations/app_localizations.dart | 16 +++ lib/main/routes/route_navigation.dart | 6 +- 17 files changed, 237 insertions(+), 82 deletions(-) create mode 100644 lib/main/bindings/local/local_isolate_bindings.dart create mode 100644 lib/main/exceptions/isolate_exception.dart diff --git a/lib/features/caching/config/hive_cache_config.dart b/lib/features/caching/config/hive_cache_config.dart index fb54ece11..47cf46640 100644 --- a/lib/features/caching/config/hive_cache_config.dart +++ b/lib/features/caching/config/hive_cache_config.dart @@ -4,7 +4,6 @@ import 'dart:typed_data'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; -import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; @@ -30,6 +29,8 @@ import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscrip import 'package:tmail_ui_user/features/session/data/model/session_hive_obj.dart'; import 'package:tmail_ui_user/features/thread/data/model/email_address_hive_cache.dart'; import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart'; +import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class HiveCacheConfig { @@ -59,7 +60,11 @@ class HiveCacheConfig { } static Future initializeEncryptionKey() async { - final encryptionKeyCacheManager = Get.find(); + final encryptionKeyCacheManager = getBinding() ?? getBinding(tag: BindingTag.isolateTag); + if (encryptionKeyCacheManager == null) { + log('HiveCacheConfig::_initializeEncryptionKey(): encryptionKeyCacheManager not found'); + return; + } final encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored(); if (encryptionKeyCache == null) { final secureKey = Hive.generateSecureKey(); @@ -70,7 +75,11 @@ class HiveCacheConfig { } static Future getEncryptionKey() async { - final encryptionKeyCacheManager = Get.find(); + final encryptionKeyCacheManager = getBinding() ?? getBinding(tag: BindingTag.isolateTag); + if (encryptionKeyCacheManager == null) { + log('HiveCacheConfig::getEncryptionKey(): encryptionKeyCacheManager not found'); + return null; + } var encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored(); if (encryptionKeyCache != null) { diff --git a/lib/features/login/data/network/authentication_client/authentication_client_base.dart b/lib/features/login/data/network/authentication_client/authentication_client_base.dart index 4ecc390f9..a1a097644 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_base.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_base.dart @@ -30,5 +30,5 @@ abstract class AuthenticationClientBase { Future logoutOidc(TokenId tokenId, OIDCConfiguration config, OIDCDiscoveryResponse oidcRescovery); - factory AuthenticationClientBase() => getAuthenticationClientImplementation(); + factory AuthenticationClientBase({String? tag}) => getAuthenticationClientImplementation(tag: tag); } \ No newline at end of file diff --git a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart index 9bfe11283..f22968b8a 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart @@ -98,5 +98,5 @@ class AuthenticationClientMobile implements AuthenticationClientBase { } } -AuthenticationClientBase getAuthenticationClientImplementation() => - AuthenticationClientMobile(Get.find()); \ No newline at end of file +AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) => + AuthenticationClientMobile(Get.find(tag: tag)); \ No newline at end of file diff --git a/lib/features/login/data/network/authentication_client/authentication_client_web.dart b/lib/features/login/data/network/authentication_client/authentication_client_web.dart index 1544923c0..463f79a11 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_web.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_web.dart @@ -108,5 +108,5 @@ class AuthenticationClientWeb implements AuthenticationClientBase { } } -AuthenticationClientBase getAuthenticationClientImplementation() => - AuthenticationClientWeb(Get.find()); \ No newline at end of file +AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) => + AuthenticationClientWeb(Get.find(tag: tag)); \ No newline at end of file diff --git a/lib/features/login/data/network/config/authorization_interceptors.dart b/lib/features/login/data/network/config/authorization_interceptors.dart index 26cbe141b..95c81a36f 100644 --- a/lib/features/login/data/network/config/authorization_interceptors.dart +++ b/lib/features/login/data/network/config/authorization_interceptors.dart @@ -80,79 +80,90 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper { @override void onError(DioError err, ErrorInterceptorHandler handler) async { logError('AuthorizationInterceptors::onError(): $err'); + try { + final requestOptions = err.requestOptions; + final extraInRequest = requestOptions.extra; + var retries = extraInRequest[RETRY_KEY] ?? 0; - final requestOptions = err.requestOptions; - final extraInRequest = requestOptions.extra; - var retries = extraInRequest[RETRY_KEY] ?? 0; + if (_validateToRefreshToken(err)) { + log('AuthorizationInterceptors::onError:>> _validateToRefreshToken'); + final newToken = await _authenticationClient.refreshingTokensOIDC( + _configOIDC!.clientId, + _configOIDC!.redirectUrl, + _configOIDC!.discoveryUrl, + _configOIDC!.scopes, + _token!.refreshToken + ); - if (_validateToRefreshToken(err)) { - log('AuthorizationInterceptors::onError:>> _validateToRefreshToken'); - final newToken = await _authenticationClient.refreshingTokensOIDC( - _configOIDC!.clientId, - _configOIDC!.redirectUrl, - _configOIDC!.discoveryUrl, - _configOIDC!.scopes, - _token!.refreshToken - ); + final currentAccount = await _accountCacheManager.getCurrentAccount(); - final currentAccount = await _accountCacheManager.getCurrentAccount(); + await _accountCacheManager.deleteCurrentAccount(currentAccount.id); - await _accountCacheManager.deleteCurrentAccount(currentAccount.id); - - await Future.wait([ - _tokenOidcCacheManager.persistOneTokenOidc(newToken), - _accountCacheManager.setCurrentAccount( - PersonalAccount( - newToken.tokenIdHash, - AuthenticationType.oidc, - isSelected: true, - accountId: currentAccount.accountId, - apiUrl: currentAccount.apiUrl, - userName: currentAccount.userName + await Future.wait([ + _tokenOidcCacheManager.persistOneTokenOidc(newToken), + _accountCacheManager.setCurrentAccount( + PersonalAccount( + newToken.tokenIdHash, + AuthenticationType.oidc, + isSelected: true, + accountId: currentAccount.accountId, + apiUrl: currentAccount.apiUrl, + userName: currentAccount.userName + ) ) - ) - ]); - _updateNewToken(newToken.toToken()); + ]); + _updateNewToken(newToken.toToken()); - if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) { - final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey]; + if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) { + final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey]; - requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token); - requestOptions.headers[HttpHeaders.contentTypeHeader] = uploadExtra[FileUploader.typeExtraKey]; - requestOptions.headers[HttpHeaders.contentLengthHeader] = uploadExtra[FileUploader.sizeExtraKey]; + requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token); + requestOptions.headers[HttpHeaders.contentTypeHeader] = uploadExtra[FileUploader.typeExtraKey]; + requestOptions.headers[HttpHeaders.contentLengthHeader] = uploadExtra[FileUploader.sizeExtraKey]; - final newOptions = Options( - method: requestOptions.method, - headers: requestOptions.headers, - ); + final newOptions = Options( + method: requestOptions.method, + headers: requestOptions.headers, + ); - final response = await _dio.request( - requestOptions.path, - data: uploadExtra[FileUploader.platformExtraKey] == 'web' - ? BodyBytesStream.fromBytes(uploadExtra[FileUploader.bytesExtraKey]) - : File(uploadExtra[FileUploader.filePathExtraKey]).openRead(), - queryParameters: requestOptions.queryParameters, - options: newOptions, - ); + final response = await _dio.request( + requestOptions.path, + data: _getDataUploadRequest(uploadExtra), + queryParameters: requestOptions.queryParameters, + options: newOptions, + ); - return handler.resolve(response); - } else { - requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token); + return handler.resolve(response); + } else { + requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token); + + final response = await _dio.fetch(requestOptions); + return handler.resolve(response); + } + } else if (_validateToRetry(err, retries)) { + log('AuthorizationInterceptors::onError:>> _validateToRetry | retries: $retries'); + retries++; + + requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token); + requestOptions.extra = {RETRY_KEY: retries}; final response = await _dio.fetch(requestOptions); return handler.resolve(response); + } else { + super.onError(err, handler); } - } else if (_validateToRetry(err, retries)) { - log('AuthorizationInterceptors::onError:>> _validateToRetry | retries: $retries'); - retries++; + } catch (e) { + logError('AuthorizationInterceptors::onError:Exception: $e'); + super.onError(err.copyWith(error: e), handler); + } + } - requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token); - requestOptions.extra = {RETRY_KEY: retries}; - - final response = await _dio.fetch(requestOptions); - return handler.resolve(response); + Stream>? _getDataUploadRequest(dynamic mapUploadExtra) { + final currentPlatform = mapUploadExtra[FileUploader.platformExtraKey]; + if (currentPlatform == 'web') { + return BodyBytesStream.fromBytes(mapUploadExtra[FileUploader.bytesExtraKey]); } else { - super.onError(err, handler); + return File(mapUploadExtra[FileUploader.filePathExtraKey]).openRead(); } } 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 283d3f2cf..0725edf4a 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,5 +1,6 @@ import 'package:equatable/equatable.dart'; +import 'package:flutter/services.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'; @@ -13,13 +14,16 @@ class MailboxMarkAsReadArguments with EquatableMixin { final MailboxId mailboxId; final ThreadAPI threadAPI; final EmailAPI emailAPI; + final RootIsolateToken isolateToken; MailboxMarkAsReadArguments( this.session, this.threadAPI, this.emailAPI, this.accountId, - this.mailboxId); + this.mailboxId, + this.isolateToken, + ); @override List get props => [ @@ -27,6 +31,7 @@ class MailboxMarkAsReadArguments with EquatableMixin { accountId, threadAPI, emailAPI, - mailboxId + mailboxId, + isolateToken, ]; } \ 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 4c35ae9c7..eb0013980 100644 --- a/lib/features/mailbox/data/network/mailbox_isolate_worker.dart +++ b/lib/features/mailbox/data/network/mailbox_isolate_worker.dart @@ -5,6 +5,7 @@ import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; import 'package:dartz/dartz.dart'; +import 'package:flutter/services.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'; @@ -19,11 +20,13 @@ import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/email/email_property.dart'; import 'package:model/email/read_actions.dart'; +import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_mark_as_read_arguments.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; +import 'package:tmail_ui_user/main/exceptions/isolate_exception.dart'; import 'package:worker_manager/worker_manager.dart'; class MailboxIsolateWorker { @@ -49,13 +52,20 @@ class MailboxIsolateWorker { totalEmailUnread, onProgressController); } else { + final rootIsolateToken = RootIsolateToken.instance; + if (rootIsolateToken == null) { + throw CanNotGetRootIsolateToken(); + } + final result = await _isolateExecutor.execute( arg1: MailboxMarkAsReadArguments( session, _threadApi, _emailApi, accountId, - mailboxId), + mailboxId, + rootIsolateToken + ), fun1: _handleMarkAsMailboxReadAction, notification: (value) { if (value is List) { @@ -74,6 +84,10 @@ class MailboxIsolateWorker { MailboxMarkAsReadArguments args, TypeSendPort sendPort ) async { + final rootIsolateToken = args.isolateToken; + BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken); + await HiveCacheConfig().setUp(); + List emailListCompleted = List.empty(growable: true); try { bool mailboxHasEmails = true; diff --git a/lib/features/mailbox/domain/state/mark_as_mailbox_read_state.dart b/lib/features/mailbox/domain/state/mark_as_mailbox_read_state.dart index 19ddb8299..6f16d3e4e 100644 --- a/lib/features/mailbox/domain/state/mark_as_mailbox_read_state.dart +++ b/lib/features/mailbox/domain/state/mark_as_mailbox_read_state.dart @@ -61,9 +61,21 @@ class MarkAsMailboxReadHasSomeEmailFailure extends UIActionState { ]; } -class MarkAsMailboxReadAllFailure extends FeatureFailure {} +class MarkAsMailboxReadAllFailure extends FeatureFailure { + final String mailboxDisplayName; + + MarkAsMailboxReadAllFailure({required this.mailboxDisplayName}); + + @override + List get props => [mailboxDisplayName]; +} class MarkAsMailboxReadFailure extends FeatureFailure { - MarkAsMailboxReadFailure(dynamic exception) : super(exception: exception); + final String mailboxDisplayName; + + MarkAsMailboxReadFailure({ + required this.mailboxDisplayName, + dynamic exception + }) : super(exception: exception); } \ No newline at end of file diff --git a/lib/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart b/lib/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart index b078d9061..bd892595a 100644 --- a/lib/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart +++ b/lib/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart @@ -54,10 +54,13 @@ class MarkAsMailboxReadInteractor { currentEmailState: currentEmailState, currentMailboxState: currentMailboxState)); } else { - yield Left(MarkAsMailboxReadAllFailure()); + yield Left(MarkAsMailboxReadAllFailure(mailboxDisplayName: mailboxDisplayName)); } } catch (e) { - yield Left(MarkAsMailboxReadFailure(e)); + yield Left(MarkAsMailboxReadFailure( + mailboxDisplayName: mailboxDisplayName, + exception: e + )); } } } \ No newline at end of file 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 a8ae3e8ad..e9628e351 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -364,8 +364,9 @@ class MailboxDashBoardController extends ReloadableController { _handleUpdateEmailAsDraftsFailure(failure); } else if (failure is RemoveEmailDraftsFailure) { clearState(); - } else if (failure is MarkAsMailboxReadAllFailure || - failure is MarkAsMailboxReadFailure) { + } else if (failure is MarkAsMailboxReadAllFailure) { + _markAsReadMailboxAllFailure(failure); + } else if (failure is MarkAsMailboxReadFailure) { _markAsReadMailboxFailure(failure); } else if (failure is GetEmailByIdFailure) { _handleGetEmailDetailedFailed(failure); @@ -1368,8 +1369,27 @@ class MailboxDashBoardController extends ReloadableController { } } - void _markAsReadMailboxFailure(Failure failure) { + void _markAsReadMailboxFailure(MarkAsMailboxReadFailure failure) { viewStateMarkAsReadMailbox.value = Right(UIState.idle); + if (currentOverlayContext != null && currentContext != null) { + _appToast.showToastErrorMessage( + currentOverlayContext!, + AppLocalizations.of(currentContext!).toastMessageMarkAsReadFolderFailureWithReason( + failure.mailboxDisplayName, + failure.exception.toString() + ) + ); + } + } + + void _markAsReadMailboxAllFailure(MarkAsMailboxReadAllFailure failure) { + viewStateMarkAsReadMailbox.value = Right(UIState.idle); + if (currentOverlayContext != null && currentContext != null) { + _appToast.showToastErrorMessage( + currentOverlayContext!, + AppLocalizations.of(currentContext!).toastMessageMarkAsReadFolderAllFailure(failure.mailboxDisplayName) + ); + } } void goToComposer(ComposerArguments arguments) async { diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index dbc48e6b9..cf1b59ebc 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2023-10-23T15:47:43.102170", + "@@last_modified": "2023-10-27T20:44:50.998215", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -3297,5 +3297,27 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "toastMessageMarkAsReadFolderAllFailure": "Folder \"{folderName}\" could not be marked as read", + "@toastMessageMarkAsReadFolderAllFailure": { + "type": "text", + "placeholders_order": [ + "folderName" + ], + "placeholders": { + "folderName": {} + } + }, + "toastMessageMarkAsReadFolderFailureWithReason": "Folder \"{folderName}\" could not be marked as read. Due \"{reason}\"", + "@toastMessageMarkAsReadFolderFailureWithReason": { + "type": "text", + "placeholders_order": [ + "folderName", + "reason" + ], + "placeholders": { + "folderName": {}, + "reason": {} + } } } \ No newline at end of file diff --git a/lib/main/bindings/local/local_isolate_bindings.dart b/lib/main/bindings/local/local_isolate_bindings.dart new file mode 100644 index 000000000..2777e5ad9 --- /dev/null +++ b/lib/main/bindings/local/local_isolate_bindings.dart @@ -0,0 +1,35 @@ + +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/caching/clients/account_cache_client.dart'; +import 'package:tmail_ui_user/features/caching/clients/encryption_key_cache_client.dart'; +import 'package:tmail_ui_user/features/caching/clients/token_oidc_cache_client.dart'; +import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/local/encryption_key_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; +import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; + +class LocalIsolateBindings extends Bindings { + + @override + void dependencies() { + _bindingCaching(); + } + + void _bindingCaching() { + Get.put(TokenOidcCacheClient(), tag: BindingTag.isolateTag); + Get.put(TokenOidcCacheManager( + Get.find(tag: BindingTag.isolateTag)), + tag: BindingTag.isolateTag + ); + Get.put(AccountCacheClient(), tag: BindingTag.isolateTag); + Get.put(AccountCacheManager( + Get.find(tag: BindingTag.isolateTag)), + tag: BindingTag.isolateTag + ); + Get.put(EncryptionKeyCacheClient(), tag: BindingTag.isolateTag); + Get.put(EncryptionKeyCacheManager( + Get.find(tag: BindingTag.isolateTag)), + tag: BindingTag.isolateTag + ); + } +} \ No newline at end of file diff --git a/lib/main/bindings/main_bindings.dart b/lib/main/bindings/main_bindings.dart index 702ba45bd..358a6df72 100644 --- a/lib/main/bindings/main_bindings.dart +++ b/lib/main/bindings/main_bindings.dart @@ -2,6 +2,7 @@ import 'package:get/get.dart'; import 'package:tmail_ui_user/main/bindings/core/core_bindings.dart'; import 'package:tmail_ui_user/main/bindings/credential/credential_bindings.dart'; import 'package:tmail_ui_user/main/bindings/local/local_bindings.dart'; +import 'package:tmail_ui_user/main/bindings/local/local_isolate_bindings.dart'; import 'package:tmail_ui_user/main/bindings/network/network_bindings.dart'; import 'package:tmail_ui_user/main/bindings/network/network_isolate_binding.dart'; import 'package:tmail_ui_user/main/bindings/network_connection/network_connection_bindings.dart'; @@ -12,6 +13,7 @@ class MainBindings extends Bindings { Future dependencies() async { await CoreBindings().dependencies(); LocalBindings().dependencies(); + LocalIsolateBindings().dependencies(); NetworkBindings().dependencies(); NetworkIsolateBindings().dependencies(); CredentialBindings().dependencies(); diff --git a/lib/main/bindings/network/network_isolate_binding.dart b/lib/main/bindings/network/network_isolate_binding.dart index 256354ced..ed89815fa 100644 --- a/lib/main/bindings/network/network_isolate_binding.dart +++ b/lib/main/bindings/network/network_isolate_binding.dart @@ -1,6 +1,7 @@ import 'package:core/core.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter_appauth/flutter_appauth.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/http/http_client.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; @@ -8,6 +9,7 @@ import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.da import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; +import 'package:tmail_ui_user/features/login/data/utils/library_platform/app_auth_plugin/app_auth_mobile_plugin.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart'; @@ -27,15 +29,18 @@ class NetworkIsolateBindings extends Bindings { void _bindingDio() { final dio = Get.put(Dio(Get.find()), tag: BindingTag.isolateTag); Get.put(DioClient(dio), tag: BindingTag.isolateTag); + Get.put(const FlutterAppAuth(), tag: BindingTag.isolateTag); + Get.put(AppAuthWebPlugin(), tag: BindingTag.isolateTag); + Get.put(AuthenticationClientBase(tag: BindingTag.isolateTag), tag: BindingTag.isolateTag); _bindingInterceptors(dio); } void _bindingInterceptors(Dio dio) { Get.put(AuthorizationInterceptors( dio, - Get.find(), - Get.find(), - Get.find(), + Get.find(tag: BindingTag.isolateTag), + Get.find(tag: BindingTag.isolateTag), + Get.find(tag: BindingTag.isolateTag), ), tag: BindingTag.isolateTag); dio.interceptors.add(Get.find()); dio.interceptors.add(Get.find(tag: BindingTag.isolateTag)); diff --git a/lib/main/exceptions/isolate_exception.dart b/lib/main/exceptions/isolate_exception.dart new file mode 100644 index 000000000..f6046321f --- /dev/null +++ b/lib/main/exceptions/isolate_exception.dart @@ -0,0 +1 @@ +class CanNotGetRootIsolateToken implements Exception {} diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index c1e6b7ed9..cfba593a9 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -3405,4 +3405,20 @@ class AppLocalizations { name: 'downloadAll', ); } + + String toastMessageMarkAsReadFolderAllFailure(String folderName) { + return Intl.message( + 'Folder "$folderName" could not be marked as read', + name: 'toastMessageMarkAsReadFolderAllFailure', + args: [folderName] + ); + } + + String toastMessageMarkAsReadFolderFailureWithReason(String folderName, String reason) { + return Intl.message( + 'Folder "$folderName" could not be marked as read. Due "$reason"', + name: 'toastMessageMarkAsReadFolderFailureWithReason', + args: [folderName, reason] + ); + } } \ No newline at end of file diff --git a/lib/main/routes/route_navigation.dart b/lib/main/routes/route_navigation.dart index 005bd8fd5..3130fd452 100644 --- a/lib/main/routes/route_navigation.dart +++ b/lib/main/routes/route_navigation.dart @@ -30,9 +30,9 @@ BuildContext? get currentContext => Get.context; BuildContext? get currentOverlayContext => Get.overlayContext; -T? getBinding() { - if (Get.isRegistered()) { - return Get.find(); +T? getBinding({String? tag}) { + if (Get.isRegistered(tag: tag)) { + return Get.find(tag: tag); } else { return null; }