TF-2280 Fix mark as read mailbox when token expired on mobile
Signed-off-by: dab246 <tdvu@linagora.com> (cherry picked from commit caab5a896875168f2d98c249207eb3eb537c58ec)
This commit is contained in:
@@ -4,7 +4,6 @@ import 'dart:typed_data';
|
|||||||
|
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:path_provider/path_provider.dart' as path_provider;
|
import 'package:path_provider/path_provider.dart' as path_provider;
|
||||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
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/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_address_hive_cache.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/data/model/email_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 {
|
class HiveCacheConfig {
|
||||||
|
|
||||||
@@ -59,7 +60,11 @@ class HiveCacheConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> initializeEncryptionKey() async {
|
static Future<void> initializeEncryptionKey() async {
|
||||||
final encryptionKeyCacheManager = Get.find<EncryptionKeyCacheManager>();
|
final encryptionKeyCacheManager = getBinding<EncryptionKeyCacheManager>() ?? getBinding<EncryptionKeyCacheManager>(tag: BindingTag.isolateTag);
|
||||||
|
if (encryptionKeyCacheManager == null) {
|
||||||
|
log('HiveCacheConfig::_initializeEncryptionKey(): encryptionKeyCacheManager not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
final encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored();
|
final encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored();
|
||||||
if (encryptionKeyCache == null) {
|
if (encryptionKeyCache == null) {
|
||||||
final secureKey = Hive.generateSecureKey();
|
final secureKey = Hive.generateSecureKey();
|
||||||
@@ -70,7 +75,11 @@ class HiveCacheConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List?> getEncryptionKey() async {
|
static Future<Uint8List?> getEncryptionKey() async {
|
||||||
final encryptionKeyCacheManager = Get.find<EncryptionKeyCacheManager>();
|
final encryptionKeyCacheManager = getBinding<EncryptionKeyCacheManager>() ?? getBinding<EncryptionKeyCacheManager>(tag: BindingTag.isolateTag);
|
||||||
|
if (encryptionKeyCacheManager == null) {
|
||||||
|
log('HiveCacheConfig::getEncryptionKey(): encryptionKeyCacheManager not found');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored();
|
var encryptionKeyCache = await encryptionKeyCacheManager.getEncryptionKeyStored();
|
||||||
|
|
||||||
if (encryptionKeyCache != null) {
|
if (encryptionKeyCache != null) {
|
||||||
|
|||||||
+1
-1
@@ -30,5 +30,5 @@ abstract class AuthenticationClientBase {
|
|||||||
|
|
||||||
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config, OIDCDiscoveryResponse oidcRescovery);
|
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config, OIDCDiscoveryResponse oidcRescovery);
|
||||||
|
|
||||||
factory AuthenticationClientBase() => getAuthenticationClientImplementation();
|
factory AuthenticationClientBase({String? tag}) => getAuthenticationClientImplementation(tag: tag);
|
||||||
}
|
}
|
||||||
+2
-2
@@ -98,5 +98,5 @@ class AuthenticationClientMobile implements AuthenticationClientBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationClientBase getAuthenticationClientImplementation() =>
|
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
||||||
AuthenticationClientMobile(Get.find<FlutterAppAuth>());
|
AuthenticationClientMobile(Get.find<FlutterAppAuth>(tag: tag));
|
||||||
+2
-2
@@ -108,5 +108,5 @@ class AuthenticationClientWeb implements AuthenticationClientBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationClientBase getAuthenticationClientImplementation() =>
|
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
||||||
AuthenticationClientWeb(Get.find<AppAuthWebPlugin>());
|
AuthenticationClientWeb(Get.find<AppAuthWebPlugin>(tag: tag));
|
||||||
@@ -80,79 +80,90 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
|||||||
@override
|
@override
|
||||||
void onError(DioError err, ErrorInterceptorHandler handler) async {
|
void onError(DioError err, ErrorInterceptorHandler handler) async {
|
||||||
logError('AuthorizationInterceptors::onError(): $err');
|
logError('AuthorizationInterceptors::onError(): $err');
|
||||||
|
try {
|
||||||
|
final requestOptions = err.requestOptions;
|
||||||
|
final extraInRequest = requestOptions.extra;
|
||||||
|
var retries = extraInRequest[RETRY_KEY] ?? 0;
|
||||||
|
|
||||||
final requestOptions = err.requestOptions;
|
if (_validateToRefreshToken(err)) {
|
||||||
final extraInRequest = requestOptions.extra;
|
log('AuthorizationInterceptors::onError:>> _validateToRefreshToken');
|
||||||
var retries = extraInRequest[RETRY_KEY] ?? 0;
|
final newToken = await _authenticationClient.refreshingTokensOIDC(
|
||||||
|
_configOIDC!.clientId,
|
||||||
|
_configOIDC!.redirectUrl,
|
||||||
|
_configOIDC!.discoveryUrl,
|
||||||
|
_configOIDC!.scopes,
|
||||||
|
_token!.refreshToken
|
||||||
|
);
|
||||||
|
|
||||||
if (_validateToRefreshToken(err)) {
|
final currentAccount = await _accountCacheManager.getCurrentAccount();
|
||||||
log('AuthorizationInterceptors::onError:>> _validateToRefreshToken');
|
|
||||||
final newToken = await _authenticationClient.refreshingTokensOIDC(
|
|
||||||
_configOIDC!.clientId,
|
|
||||||
_configOIDC!.redirectUrl,
|
|
||||||
_configOIDC!.discoveryUrl,
|
|
||||||
_configOIDC!.scopes,
|
|
||||||
_token!.refreshToken
|
|
||||||
);
|
|
||||||
|
|
||||||
final currentAccount = await _accountCacheManager.getCurrentAccount();
|
await _accountCacheManager.deleteCurrentAccount(currentAccount.id);
|
||||||
|
|
||||||
await _accountCacheManager.deleteCurrentAccount(currentAccount.id);
|
await Future.wait([
|
||||||
|
_tokenOidcCacheManager.persistOneTokenOidc(newToken),
|
||||||
await Future.wait([
|
_accountCacheManager.setCurrentAccount(
|
||||||
_tokenOidcCacheManager.persistOneTokenOidc(newToken),
|
PersonalAccount(
|
||||||
_accountCacheManager.setCurrentAccount(
|
newToken.tokenIdHash,
|
||||||
PersonalAccount(
|
AuthenticationType.oidc,
|
||||||
newToken.tokenIdHash,
|
isSelected: true,
|
||||||
AuthenticationType.oidc,
|
accountId: currentAccount.accountId,
|
||||||
isSelected: true,
|
apiUrl: currentAccount.apiUrl,
|
||||||
accountId: currentAccount.accountId,
|
userName: currentAccount.userName
|
||||||
apiUrl: currentAccount.apiUrl,
|
)
|
||||||
userName: currentAccount.userName
|
|
||||||
)
|
)
|
||||||
)
|
]);
|
||||||
]);
|
_updateNewToken(newToken.toToken());
|
||||||
_updateNewToken(newToken.toToken());
|
|
||||||
|
|
||||||
if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) {
|
if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) {
|
||||||
final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey];
|
final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey];
|
||||||
|
|
||||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token);
|
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token);
|
||||||
requestOptions.headers[HttpHeaders.contentTypeHeader] = uploadExtra[FileUploader.typeExtraKey];
|
requestOptions.headers[HttpHeaders.contentTypeHeader] = uploadExtra[FileUploader.typeExtraKey];
|
||||||
requestOptions.headers[HttpHeaders.contentLengthHeader] = uploadExtra[FileUploader.sizeExtraKey];
|
requestOptions.headers[HttpHeaders.contentLengthHeader] = uploadExtra[FileUploader.sizeExtraKey];
|
||||||
|
|
||||||
final newOptions = Options(
|
final newOptions = Options(
|
||||||
method: requestOptions.method,
|
method: requestOptions.method,
|
||||||
headers: requestOptions.headers,
|
headers: requestOptions.headers,
|
||||||
);
|
);
|
||||||
|
|
||||||
final response = await _dio.request(
|
final response = await _dio.request(
|
||||||
requestOptions.path,
|
requestOptions.path,
|
||||||
data: uploadExtra[FileUploader.platformExtraKey] == 'web'
|
data: _getDataUploadRequest(uploadExtra),
|
||||||
? BodyBytesStream.fromBytes(uploadExtra[FileUploader.bytesExtraKey])
|
queryParameters: requestOptions.queryParameters,
|
||||||
: File(uploadExtra[FileUploader.filePathExtraKey]).openRead(),
|
options: newOptions,
|
||||||
queryParameters: requestOptions.queryParameters,
|
);
|
||||||
options: newOptions,
|
|
||||||
);
|
|
||||||
|
|
||||||
return handler.resolve(response);
|
return handler.resolve(response);
|
||||||
} else {
|
} else {
|
||||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token);
|
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);
|
final response = await _dio.fetch(requestOptions);
|
||||||
return handler.resolve(response);
|
return handler.resolve(response);
|
||||||
|
} else {
|
||||||
|
super.onError(err, handler);
|
||||||
}
|
}
|
||||||
} else if (_validateToRetry(err, retries)) {
|
} catch (e) {
|
||||||
log('AuthorizationInterceptors::onError:>> _validateToRetry | retries: $retries');
|
logError('AuthorizationInterceptors::onError:Exception: $e');
|
||||||
retries++;
|
super.onError(err.copyWith(error: e), handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token);
|
Stream<List<int>>? _getDataUploadRequest(dynamic mapUploadExtra) {
|
||||||
requestOptions.extra = {RETRY_KEY: retries};
|
final currentPlatform = mapUploadExtra[FileUploader.platformExtraKey];
|
||||||
|
if (currentPlatform == 'web') {
|
||||||
final response = await _dio.fetch(requestOptions);
|
return BodyBytesStream.fromBytes(mapUploadExtra[FileUploader.bytesExtraKey]);
|
||||||
return handler.resolve(response);
|
|
||||||
} else {
|
} else {
|
||||||
super.onError(err, handler);
|
return File(mapUploadExtra[FileUploader.filePathExtraKey]).openRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
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/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
@@ -13,13 +14,16 @@ class MailboxMarkAsReadArguments with EquatableMixin {
|
|||||||
final MailboxId mailboxId;
|
final MailboxId mailboxId;
|
||||||
final ThreadAPI threadAPI;
|
final ThreadAPI threadAPI;
|
||||||
final EmailAPI emailAPI;
|
final EmailAPI emailAPI;
|
||||||
|
final RootIsolateToken isolateToken;
|
||||||
|
|
||||||
MailboxMarkAsReadArguments(
|
MailboxMarkAsReadArguments(
|
||||||
this.session,
|
this.session,
|
||||||
this.threadAPI,
|
this.threadAPI,
|
||||||
this.emailAPI,
|
this.emailAPI,
|
||||||
this.accountId,
|
this.accountId,
|
||||||
this.mailboxId);
|
this.mailboxId,
|
||||||
|
this.isolateToken,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
@@ -27,6 +31,7 @@ class MailboxMarkAsReadArguments with EquatableMixin {
|
|||||||
accountId,
|
accountId,
|
||||||
threadAPI,
|
threadAPI,
|
||||||
emailAPI,
|
emailAPI,
|
||||||
mailboxId
|
mailboxId,
|
||||||
|
isolateToken,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import 'package:core/presentation/state/success.dart';
|
|||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:dartz/dartz.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/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.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:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
import 'package:model/email/email_property.dart';
|
import 'package:model/email/email_property.dart';
|
||||||
import 'package:model/email/read_actions.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/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/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/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/data/network/thread_api.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||||
|
import 'package:tmail_ui_user/main/exceptions/isolate_exception.dart';
|
||||||
import 'package:worker_manager/worker_manager.dart';
|
import 'package:worker_manager/worker_manager.dart';
|
||||||
|
|
||||||
class MailboxIsolateWorker {
|
class MailboxIsolateWorker {
|
||||||
@@ -49,13 +52,20 @@ class MailboxIsolateWorker {
|
|||||||
totalEmailUnread,
|
totalEmailUnread,
|
||||||
onProgressController);
|
onProgressController);
|
||||||
} else {
|
} else {
|
||||||
|
final rootIsolateToken = RootIsolateToken.instance;
|
||||||
|
if (rootIsolateToken == null) {
|
||||||
|
throw CanNotGetRootIsolateToken();
|
||||||
|
}
|
||||||
|
|
||||||
final result = await _isolateExecutor.execute(
|
final result = await _isolateExecutor.execute(
|
||||||
arg1: MailboxMarkAsReadArguments(
|
arg1: MailboxMarkAsReadArguments(
|
||||||
session,
|
session,
|
||||||
_threadApi,
|
_threadApi,
|
||||||
_emailApi,
|
_emailApi,
|
||||||
accountId,
|
accountId,
|
||||||
mailboxId),
|
mailboxId,
|
||||||
|
rootIsolateToken
|
||||||
|
),
|
||||||
fun1: _handleMarkAsMailboxReadAction,
|
fun1: _handleMarkAsMailboxReadAction,
|
||||||
notification: (value) {
|
notification: (value) {
|
||||||
if (value is List<Email>) {
|
if (value is List<Email>) {
|
||||||
@@ -74,6 +84,10 @@ class MailboxIsolateWorker {
|
|||||||
MailboxMarkAsReadArguments args,
|
MailboxMarkAsReadArguments args,
|
||||||
TypeSendPort sendPort
|
TypeSendPort sendPort
|
||||||
) async {
|
) async {
|
||||||
|
final rootIsolateToken = args.isolateToken;
|
||||||
|
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
|
||||||
|
await HiveCacheConfig().setUp();
|
||||||
|
|
||||||
List<Email> emailListCompleted = List.empty(growable: true);
|
List<Email> emailListCompleted = List.empty(growable: true);
|
||||||
try {
|
try {
|
||||||
bool mailboxHasEmails = true;
|
bool mailboxHasEmails = true;
|
||||||
|
|||||||
@@ -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<Object?> get props => [mailboxDisplayName];
|
||||||
|
}
|
||||||
|
|
||||||
class MarkAsMailboxReadFailure extends FeatureFailure {
|
class MarkAsMailboxReadFailure extends FeatureFailure {
|
||||||
|
|
||||||
MarkAsMailboxReadFailure(dynamic exception) : super(exception: exception);
|
final String mailboxDisplayName;
|
||||||
|
|
||||||
|
MarkAsMailboxReadFailure({
|
||||||
|
required this.mailboxDisplayName,
|
||||||
|
dynamic exception
|
||||||
|
}) : super(exception: exception);
|
||||||
}
|
}
|
||||||
@@ -54,10 +54,13 @@ class MarkAsMailboxReadInteractor {
|
|||||||
currentEmailState: currentEmailState,
|
currentEmailState: currentEmailState,
|
||||||
currentMailboxState: currentMailboxState));
|
currentMailboxState: currentMailboxState));
|
||||||
} else {
|
} else {
|
||||||
yield Left(MarkAsMailboxReadAllFailure());
|
yield Left(MarkAsMailboxReadAllFailure(mailboxDisplayName: mailboxDisplayName));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
yield Left(MarkAsMailboxReadFailure(e));
|
yield Left(MarkAsMailboxReadFailure(
|
||||||
|
mailboxDisplayName: mailboxDisplayName,
|
||||||
|
exception: e
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+23
-3
@@ -364,8 +364,9 @@ class MailboxDashBoardController extends ReloadableController {
|
|||||||
_handleUpdateEmailAsDraftsFailure(failure);
|
_handleUpdateEmailAsDraftsFailure(failure);
|
||||||
} else if (failure is RemoveEmailDraftsFailure) {
|
} else if (failure is RemoveEmailDraftsFailure) {
|
||||||
clearState();
|
clearState();
|
||||||
} else if (failure is MarkAsMailboxReadAllFailure ||
|
} else if (failure is MarkAsMailboxReadAllFailure) {
|
||||||
failure is MarkAsMailboxReadFailure) {
|
_markAsReadMailboxAllFailure(failure);
|
||||||
|
} else if (failure is MarkAsMailboxReadFailure) {
|
||||||
_markAsReadMailboxFailure(failure);
|
_markAsReadMailboxFailure(failure);
|
||||||
} else if (failure is GetEmailByIdFailure) {
|
} else if (failure is GetEmailByIdFailure) {
|
||||||
_handleGetEmailDetailedFailed(failure);
|
_handleGetEmailDetailedFailed(failure);
|
||||||
@@ -1368,8 +1369,27 @@ class MailboxDashBoardController extends ReloadableController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _markAsReadMailboxFailure(Failure failure) {
|
void _markAsReadMailboxFailure(MarkAsMailboxReadFailure failure) {
|
||||||
viewStateMarkAsReadMailbox.value = Right(UIState.idle);
|
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 {
|
void goToComposer(ComposerArguments arguments) async {
|
||||||
|
|||||||
@@ -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": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3297,5 +3297,27 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"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": {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<TokenOidcCacheClient>(tag: BindingTag.isolateTag)),
|
||||||
|
tag: BindingTag.isolateTag
|
||||||
|
);
|
||||||
|
Get.put(AccountCacheClient(), tag: BindingTag.isolateTag);
|
||||||
|
Get.put(AccountCacheManager(
|
||||||
|
Get.find<AccountCacheClient>(tag: BindingTag.isolateTag)),
|
||||||
|
tag: BindingTag.isolateTag
|
||||||
|
);
|
||||||
|
Get.put(EncryptionKeyCacheClient(), tag: BindingTag.isolateTag);
|
||||||
|
Get.put(EncryptionKeyCacheManager(
|
||||||
|
Get.find<EncryptionKeyCacheClient>(tag: BindingTag.isolateTag)),
|
||||||
|
tag: BindingTag.isolateTag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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/core/core_bindings.dart';
|
||||||
import 'package:tmail_ui_user/main/bindings/credential/credential_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_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_bindings.dart';
|
||||||
import 'package:tmail_ui_user/main/bindings/network/network_isolate_binding.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';
|
import 'package:tmail_ui_user/main/bindings/network_connection/network_connection_bindings.dart';
|
||||||
@@ -12,6 +13,7 @@ class MainBindings extends Bindings {
|
|||||||
Future dependencies() async {
|
Future dependencies() async {
|
||||||
await CoreBindings().dependencies();
|
await CoreBindings().dependencies();
|
||||||
LocalBindings().dependencies();
|
LocalBindings().dependencies();
|
||||||
|
LocalIsolateBindings().dependencies();
|
||||||
NetworkBindings().dependencies();
|
NetworkBindings().dependencies();
|
||||||
NetworkIsolateBindings().dependencies();
|
NetworkIsolateBindings().dependencies();
|
||||||
CredentialBindings().dependencies();
|
CredentialBindings().dependencies();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_appauth/flutter_appauth.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/http/http_client.dart';
|
import 'package:jmap_dart_client/http/http_client.dart';
|
||||||
import 'package:tmail_ui_user/features/email/data/network/email_api.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/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/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/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/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_api.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart';
|
import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart';
|
||||||
@@ -27,15 +29,18 @@ class NetworkIsolateBindings extends Bindings {
|
|||||||
void _bindingDio() {
|
void _bindingDio() {
|
||||||
final dio = Get.put(Dio(Get.find<BaseOptions>()), tag: BindingTag.isolateTag);
|
final dio = Get.put(Dio(Get.find<BaseOptions>()), tag: BindingTag.isolateTag);
|
||||||
Get.put(DioClient(dio), 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);
|
_bindingInterceptors(dio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bindingInterceptors(Dio dio) {
|
void _bindingInterceptors(Dio dio) {
|
||||||
Get.put(AuthorizationInterceptors(
|
Get.put(AuthorizationInterceptors(
|
||||||
dio,
|
dio,
|
||||||
Get.find<AuthenticationClientBase>(),
|
Get.find<AuthenticationClientBase>(tag: BindingTag.isolateTag),
|
||||||
Get.find<TokenOidcCacheManager>(),
|
Get.find<TokenOidcCacheManager>(tag: BindingTag.isolateTag),
|
||||||
Get.find<AccountCacheManager>(),
|
Get.find<AccountCacheManager>(tag: BindingTag.isolateTag),
|
||||||
), tag: BindingTag.isolateTag);
|
), tag: BindingTag.isolateTag);
|
||||||
dio.interceptors.add(Get.find<DynamicUrlInterceptors>());
|
dio.interceptors.add(Get.find<DynamicUrlInterceptors>());
|
||||||
dio.interceptors.add(Get.find<AuthorizationInterceptors>(tag: BindingTag.isolateTag));
|
dio.interceptors.add(Get.find<AuthorizationInterceptors>(tag: BindingTag.isolateTag));
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
class CanNotGetRootIsolateToken implements Exception {}
|
||||||
@@ -3405,4 +3405,20 @@ class AppLocalizations {
|
|||||||
name: 'downloadAll',
|
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]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -30,9 +30,9 @@ BuildContext? get currentContext => Get.context;
|
|||||||
|
|
||||||
BuildContext? get currentOverlayContext => Get.overlayContext;
|
BuildContext? get currentOverlayContext => Get.overlayContext;
|
||||||
|
|
||||||
T? getBinding<T>() {
|
T? getBinding<T>({String? tag}) {
|
||||||
if (Get.isRegistered<T>()) {
|
if (Get.isRegistered<T>(tag: tag)) {
|
||||||
return Get.find<T>();
|
return Get.find<T>(tag: tag);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user