TF-3082 Restore identity from cache

This commit is contained in:
DatDang
2024-08-22 09:13:04 +07:00
committed by Dat H. Pham
parent fdbbf855b6
commit 5a1fdbb123
20 changed files with 456 additions and 45 deletions
@@ -7,4 +7,10 @@ abstract class IdentityCreatorDataSource {
AccountId accountId,
UserName userName,
{required IdentityCache identityCache});
Future<IdentityCache> getIdentityCacheOnWeb(
AccountId accountId,
UserName userName);
Future<void> removeIdentityCacheOnWeb();
}
@@ -1,5 +1,7 @@
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:core/domain/exceptions/web_session_exception.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:model/extensions/account_id_extensions.dart';
@@ -31,6 +33,31 @@ class LocalIdentityCreatorDataSourceImpl implements IdentityCreatorDataSource {
window.sessionStorage.addAll(entries);
}).catchError(_exceptionThrower.throwException);
}
@override
Future<IdentityCache> getIdentityCacheOnWeb(
AccountId accountId,
UserName userName
) async {
return Future.sync(() {
final cacheKey = _generateTupleKey(accountId, userName);
final result = window.sessionStorage.entries.firstWhereOrNull(
(entry) => entry.key == cacheKey);
if (result != null) {
return IdentityCacheModel.fromJson(jsonDecode(result.value));
} else {
throw NotFoundInWebSessionException();
}
}).catchError(_exceptionThrower.throwException);
}
@override
Future<void> removeIdentityCacheOnWeb() async {
return Future.sync(() {
window.sessionStorage.removeWhere(
(key, value) => key.startsWith(LocalIdentityCreatorDataSourceImpl.sessionStorageKeyword));
}).catchError(_exceptionThrower.throwException);
}
String _generateTupleKey(AccountId accountId, UserName userName) {
return TupleKey(
@@ -18,4 +18,16 @@ class IdentityCreatorRepositoryImpl implements IdentityCreatorRepository {
accountId,
userName,
identityCache: identityCache);
@override
Future<IdentityCache> getIdentityCacheOnWeb(
AccountId accountId,
UserName userName
) => _identityCreatorDataSource.getIdentityCacheOnWeb(
accountId,
userName);
@override
Future<void> removeIdentityCacheOnWeb()
=> _identityCreatorDataSource.removeIdentityCacheOnWeb();
}
@@ -7,4 +7,10 @@ abstract class IdentityCreatorRepository {
AccountId accountId,
UserName userName,
{required IdentityCache identityCache});
Future<IdentityCache> getIdentityCacheOnWeb(
AccountId accountId,
UserName userName);
Future<void> removeIdentityCacheOnWeb();
}
@@ -0,0 +1,18 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/model/identity_cache.dart';
class GettingIdentityCacheOnWeb extends LoadingState {}
class GetIdentityCacheOnWebSuccess extends UIState {
GetIdentityCacheOnWebSuccess(this.identityCache);
final IdentityCache? identityCache;
@override
List<Object?> get props => [identityCache];
}
class GetIdentityCacheOnWebFailure extends FeatureFailure {
GetIdentityCacheOnWebFailure({super.exception});
}
@@ -0,0 +1,10 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class RemovingIdentityCacheOnWeb extends LoadingState {}
class RemoveIdentityCacheOnWebSuccess extends UIState {}
class RemoveIdentityCacheOnWebFailure extends FeatureFailure {
RemoveIdentityCacheOnWebFailure({super.exception});
}
@@ -0,0 +1,31 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/state/get_identity_cache_on_web_state.dart';
class GetIdentityCacheOnWebInteractor {
GetIdentityCacheOnWebInteractor(this._identityCreatorRepository);
final IdentityCreatorRepository _identityCreatorRepository;
Stream<Either<Failure, Success>> execute(
AccountId accountId,
UserName userName
) async* {
try {
yield Right(GettingIdentityCacheOnWeb());
final result = await _identityCreatorRepository.getIdentityCacheOnWeb(
accountId,
userName);
yield Right(GetIdentityCacheOnWebSuccess(result));
} catch (exception) {
logError("$runtimeType::execute: $exception");
yield Left(GetIdentityCacheOnWebFailure(exception: exception));
}
}
}
@@ -0,0 +1,24 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/state/remove_identity_cache_on_web_state.dart';
class RemoveIdentityCacheOnWebInteractor {
RemoveIdentityCacheOnWebInteractor(this._identityCreatorRepository);
final IdentityCreatorRepository _identityCreatorRepository;
Stream<Either<Failure, Success>> execute() async* {
try {
yield Right(RemovingIdentityCacheOnWeb());
await _identityCreatorRepository.removeIdentityCacheOnWeb();
yield Right(RemoveIdentityCacheOnWebSuccess());
} catch (exception) {
logError("$runtimeType::execute: $exception");
yield Left(RemoveIdentityCacheOnWebFailure(exception: exception));
}
}
}
@@ -352,43 +352,31 @@ class IdentityCreatorController extends BaseController with DragDropFileMixin im
listEmailAddressOfReplyTo.value = listEmailAddressOfReplyTo.toSet().toList();
listEmailAddressDefault.value = listEmailAddressDefault.toSet().toList();
if (actionType.value == IdentityActionType.edit && identity != null) {
if (identity?.replyTo?.isNotEmpty == true) {
try {
replyToOfIdentity.value = listEmailAddressOfReplyTo
.firstWhere((emailAddress) => emailAddress == identity?.replyTo!.first);
} catch(e) {
replyToOfIdentity.value = noneEmailAddress;
}
} else {
if (identity?.replyTo?.isNotEmpty == true) {
replyToOfIdentity.value = listEmailAddressOfReplyTo
.firstWhereOrNull((emailAddress) => emailAddress == identity!.replyTo!.first);
if (replyToOfIdentity.value == null && identity!.replyTo!.first == noneEmailAddress) {
replyToOfIdentity.value = noneEmailAddress;
}
if (identity?.bcc?.isNotEmpty == true) {
bccOfIdentity.value = identity?.bcc!.first;
inputBccIdentityController.text = identity?.bcc!.first.emailAddress ?? '';
} else {
bccOfIdentity.value = null;
}
if (identity?.email?.isNotEmpty == true) {
try {
emailOfIdentity.value = listEmailAddressDefault
.firstWhere((emailAddress) => emailAddress.email == identity?.email);
} catch(e) {
emailOfIdentity.value = null;
}
} else {
emailOfIdentity.value = listEmailAddressDefault.isNotEmpty
? listEmailAddressDefault.first
: null;
}
} else if (actionType.value == IdentityActionType.edit) {
replyToOfIdentity.value = noneEmailAddress;
} else {
replyToOfIdentity.value = null;
}
if (identity?.bcc?.isNotEmpty == true) {
bccOfIdentity.value = identity!.bcc!.first;
inputBccIdentityController.text = identity!.bcc!.first.emailAddress;
} else {
bccOfIdentity.value = null;
emailOfIdentity.value = listEmailAddressDefault.isNotEmpty
? listEmailAddressDefault.first
: null;
}
if (identity?.email?.isNotEmpty == true) {
emailOfIdentity.value = listEmailAddressDefault
.firstWhereOrNull((emailAddress) => emailAddress.email == identity!.email);
} else {
emailOfIdentity.value = listEmailAddressDefault.firstOrNull;
}
}
@@ -486,16 +474,19 @@ class IdentityCreatorController extends BaseController with DragDropFileMixin im
Future<({
Identity identity,
PublicAssetsInIdentityArguments publicAssetsInIdentityArguments
})> _generateIdentityAndPublicAssetArguments() async {
})> _generateIdentityAndPublicAssetArguments({bool forCache = false}) async {
final signatureHtmlText = PlatformInfo.isWeb
? contentHtmlEditor
: await _getSignatureHtmlText();
final bccAddress = bccOfIdentity.value != null && bccOfIdentity.value != noneEmailAddress
? {bccOfIdentity.value!}
: <EmailAddress>{};
final replyToAddress = replyToOfIdentity.value != null && replyToOfIdentity.value != noneEmailAddress
? {replyToOfIdentity.value!}
: <EmailAddress>{};
Set<EmailAddress> replyToAddress;
if (replyToOfIdentity.value != null && (replyToOfIdentity.value != noneEmailAddress || forCache)) {
replyToAddress = {replyToOfIdentity.value!};
} else {
replyToAddress = {};
}
final sortOrder = isDefaultIdentitySupported.isTrue
? UnsignedInt(isDefaultIdentity.value ? 0 : 100)
@@ -924,7 +915,8 @@ class IdentityCreatorController extends BaseController with DragDropFileMixin im
Future<void> _saveIdentityCacheOnWebAction() async {
if (accountId != null && session?.username != null) {
final cacheArguments = await _generateIdentityAndPublicAssetArguments();
final cacheArguments = await _generateIdentityAndPublicAssetArguments(
forCache: true);
final identityCache = IdentityCache(
identity: cacheArguments.identity,
identityActionType: actionType.value,
@@ -0,0 +1,61 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource/identity_creator_data_source.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource_impl/local_identity_creator_data_source_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/data/repository/identity_creator_repository_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/remove_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
class RestoreIdentityCacheInteractorBindings extends InteractorsBindings {
static const _tag = BindingTag.restoreIdentityCacheInteractorBindingsTag;
@override
void bindingsDataSource() {
Get.lazyPut<IdentityCreatorDataSource>(
() => Get.find<LocalIdentityCreatorDataSourceImpl>(tag: _tag),
tag: _tag);
}
@override
void bindingsDataSourceImpl() {
Get.lazyPut(
() => LocalIdentityCreatorDataSourceImpl(
Get.find<CacheExceptionThrower>()),
tag: _tag);
}
@override
void bindingsInteractor() {
Get.lazyPut(
() => GetIdentityCacheOnWebInteractor(
Get.find<IdentityCreatorRepository>(tag: _tag)),
tag: _tag);
Get.lazyPut(
() => RemoveIdentityCacheOnWebInteractor(
Get.find<IdentityCreatorRepository>(tag: _tag)),
tag: _tag);
}
@override
void bindingsRepository() {
Get.lazyPut<IdentityCreatorRepository>(
() => Get.find<IdentityCreatorRepositoryImpl>(tag: _tag),
tag: _tag);
}
@override
void bindingsRepositoryImpl() {
Get.lazyPut(
() => IdentityCreatorRepositoryImpl(
Get.find<IdentityCreatorDataSource>(tag: _tag)),
tag: _tag);
}
void close() {
Get.delete<GetIdentityCacheOnWebInteractor>(tag: _tag);
Get.delete<RemoveIdentityCacheOnWebInteractor>(tag: _tag);
}
}
@@ -32,6 +32,11 @@ import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_i
import 'package:tmail_ui_user/features/email/presentation/bindings/email_bindings.dart';
import 'package:tmail_ui_user/features/home/domain/repository/session_repository.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource/identity_creator_data_source.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource_impl/local_identity_creator_data_source_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/data/repository/identity_creator_repository_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart';
@@ -158,6 +163,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<DeleteEmailPermanentlyInteractor>(),
Get.find<MarkAsMailboxReadInteractor>(),
Get.find<GetComposerCacheOnWebInteractor>(),
Get.find<GetIdentityCacheOnWebInteractor>(),
Get.find<MarkAsEmailReadInteractor>(),
Get.find<MarkAsStarEmailInteractor>(),
Get.find<MarkAsMultipleEmailReadInteractor>(),
@@ -197,6 +203,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut<MailboxCacheDataSourceImpl>(() => Get.find<MailboxCacheDataSourceImpl>());
Get.lazyPut<ServerSettingsDataSource>(
() => Get.find<RemoteServerSettingsDataSourceImpl>());
Get.lazyPut<IdentityCreatorDataSource>(() => Get.find<LocalIdentityCreatorDataSourceImpl>());
}
@override
@@ -260,6 +267,9 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<ServerSettingsAPI>(),
Get.find<RemoteExceptionThrower>()
));
Get.lazyPut(() => LocalIdentityCreatorDataSourceImpl(
Get.find<CacheExceptionThrower>()
));
}
@override
@@ -346,6 +356,9 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<IdentityRepository>(),
Get.find<IdentityUtils>()
));
Get.lazyPut(() => GetIdentityCacheOnWebInteractor(
Get.find<IdentityCreatorRepository>()
));
}
@override
@@ -359,6 +372,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut<SpamReportRepository>(() => Get.find<SpamReportRepositoryImpl>());
Get.lazyPut<MailboxRepository>(() => Get.find<MailboxRepositoryImpl>());
Get.lazyPut<ServerSettingsRepository>(() => Get.find<ServerSettingsRepositoryImpl>());
Get.lazyPut<IdentityCreatorRepository>(() => Get.find<IdentityCreatorRepositoryImpl>());
}
@override
@@ -403,5 +417,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<StateDataSource>(),
));
Get.lazyPut(() => ServerSettingsRepositoryImpl(Get.find<ServerSettingsDataSource>()));
Get.lazyPut(() => IdentityCreatorRepositoryImpl(
Get.find<IdentityCreatorDataSource>()
));
}
}
@@ -72,6 +72,8 @@ import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart
import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_recovery_arguments.dart';
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/state/get_identity_cache_on_web_state.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
@@ -174,6 +176,7 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor;
final MarkAsMailboxReadInteractor _markAsMailboxReadInteractor;
final GetComposerCacheOnWebInteractor _getEmailCacheOnWebInteractor;
final GetIdentityCacheOnWebInteractor _getIdentityCacheOnWebInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final MarkAsMultipleEmailReadInteractor _markAsMultipleEmailReadInteractor;
@@ -257,6 +260,7 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
this._deleteEmailPermanentlyInteractor,
this._markAsMailboxReadInteractor,
this._getEmailCacheOnWebInteractor,
this._getIdentityCacheOnWebInteractor,
this._markAsEmailReadInteractor,
this._markAsStarEmailInteractor,
this._markAsMultipleEmailReadInteractor,
@@ -310,6 +314,15 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
sessionCurrent!.username));
}
void _handleIdentityCache() async {
if (accountId.value == null || sessionCurrent == null) return;
consumeState(
_getIdentityCacheOnWebInteractor.execute(
accountId.value!,
sessionCurrent!.username));
}
@override
void handleSuccessViewState(Success success) {
super.handleSuccessViewState(success);
@@ -384,6 +397,8 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
_handleGetAllIdentitiesSuccess(success);
} else if (success is GetComposerCacheSuccess) {
goToComposer(ComposerArguments.fromSessionStorageBrowser(success.composerCache));
} else if (success is GetIdentityCacheOnWebSuccess) {
goToSettings();
}
}
@@ -411,6 +426,8 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo
} else if (failure is EmptySpamFolderFailure
|| failure is MoveMultipleEmailToMailboxFailure) {
toastManager.showMessageFailure(failure);
} else if (failure is GetComposerCacheFailure) {
_handleIdentityCache();
}
}
@@ -13,8 +13,17 @@ 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/session/session.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:model/extensions/identity_request_dto_extension.dart';
import 'package:tmail_ui_user/features/base/before_reconnect_handler.dart';
import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/model/identity_cache.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/state/get_identity_cache_on_web_state.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/remove_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/save_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/restore_identity_cache_interactor_bindings.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart';
import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_default_identity_state.dart';
@@ -47,7 +56,7 @@ import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class IdentitiesController extends BaseController {
class IdentitiesController extends ReloadableController implements BeforeReconnectHandler {
final accountDashBoardController = Get.find<ManageAccountDashBoardController>();
@@ -58,11 +67,16 @@ class IdentitiesController extends BaseController {
final EditIdentityInteractor _editIdentityInteractor;
final EditDefaultIdentityInteractor _editDefaultIdentityInteractor;
final TransformHtmlSignatureInteractor _transformHtmlSignatureInteractor;
final SaveIdentityCacheOnWebInteractor _saveIdentityCacheOnWebInteractor;
final identitySelected = Rxn<Identity>();
final signatureSelected = Rxn<String>();
final listAllIdentities = <Identity>[].obs;
dynamic newIdentityArguments;
final _beforeReconnectManager = Get.find<BeforeReconnectManager>();
IdentitiesController(
this._getAllIdentitiesInteractor,
this._deleteIdentityInteractor,
@@ -70,12 +84,15 @@ class IdentitiesController extends BaseController {
this._editIdentityInteractor,
this._createNewDefaultIdentityInteractor,
this._editDefaultIdentityInteractor,
this._transformHtmlSignatureInteractor
this._transformHtmlSignatureInteractor,
this._saveIdentityCacheOnWebInteractor
);
@override
void onInit() {
_registerObxStreamListener();
RestoreIdentityCacheInteractorBindings().dependencies();
_beforeReconnectManager.addListener(onBeforeReconnect);
super.onInit();
}
@@ -96,6 +113,8 @@ class IdentitiesController extends BaseController {
signatureSelected.value = success.signature;
} else if (success is RemoveIdentityFromPublicAssetsSuccessState) {
_deleteIdentityAction(success.identityId);
} else if (success is GetIdentityCacheOnWebSuccess) {
_openIdentityEditorFromCache(success);
}
}
@@ -108,6 +127,8 @@ class IdentitiesController extends BaseController {
_deleteIdentityAction(failure.identityId);
} else if (failure is NotFoundAnyPublicAssetsFailureState) {
_deleteIdentityAction(failure.identityId);
} else if (failure is GetIdentityCacheOnWebFailure) {
_removeIdentityCache();
}
}
@@ -117,6 +138,7 @@ class IdentitiesController extends BaseController {
if (accountId != null && session != null) {
_getAllIdentities(session, accountId);
_injectCleanUpPublicAssetsInteractorBindings(session, accountId);
_handleIdentityCache();
}
});
}
@@ -164,7 +186,7 @@ class IdentitiesController extends BaseController {
if (accountId != null && session != null) {
final arguments = IdentityCreatorArguments(accountId, session);
final newIdentityArguments = PlatformInfo.isWeb
newIdentityArguments = PlatformInfo.isWeb
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.identityCreator, arguments: arguments)
: await push(AppRoutes.identityCreator, arguments: arguments);
@@ -189,6 +211,8 @@ class IdentitiesController extends BaseController {
}
void _createNewIdentitySuccess(CreateNewIdentitySuccess success) {
_removeIdentityCache();
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastSuccessMessage(
currentOverlayContext!,
@@ -204,6 +228,8 @@ class IdentitiesController extends BaseController {
}
void _createNewDefaultIdentitySuccess(CreateNewDefaultIdentitySuccess success) {
_removeIdentityCache();
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastSuccessMessage(
currentOverlayContext!,
@@ -318,7 +344,7 @@ class IdentitiesController extends BaseController {
identity: identity,
actionType: IdentityActionType.edit);
final newIdentityArguments = PlatformInfo.isWeb
newIdentityArguments = PlatformInfo.isWeb
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.identityCreator, arguments: arguments)
: await push(AppRoutes.identityCreator, arguments: arguments);
@@ -343,6 +369,8 @@ class IdentitiesController extends BaseController {
}
void _editIdentitySuccess(EditIdentitySuccess success) {
_removeIdentityCache();
if (currentOverlayContext != null && currentContext != null) {
appToast.showToastSuccessMessage(
currentOverlayContext!,
@@ -392,9 +420,108 @@ class IdentitiesController extends BaseController {
publicAssetsInIdentityArguments: publicAssetsInIdentityArguments));
}
@override
void handleReloaded(Session session) {
log('IdentitiesController::handleReloaded:');
_handleIdentityCache();
}
Future<void> _openIdentityEditorFromCache(GetIdentityCacheOnWebSuccess success) async {
final identityCache = success.identityCache;
final accountId = accountDashBoardController.accountId.value;
final session = accountDashBoardController.sessionCurrent;
if (identityCache == null || accountId == null || session == null) return;
final arguments = IdentityCreatorArguments(
accountId,
session,
identity: identityCache.identity,
isDefault: identityCache.isDefault,
publicAssetsInIdentityArguments: identityCache.publicAssetsInIdentityArguments,
actionType: identityCache.identityActionType);
newIdentityArguments = PlatformInfo.isWeb
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.identityCreator, arguments: arguments)
: await push(AppRoutes.identityCreator, arguments: arguments);
if (newIdentityArguments == null) {
_removeIdentityCache();
}
if (newIdentityArguments is CreateNewIdentityRequest) {
_createNewIdentityAction(session, accountId, newIdentityArguments);
} else if (newIdentityArguments is EditIdentityRequest) {
_editIdentityAction(session, accountId, newIdentityArguments);
}
}
void _handleIdentityCache() {
final session = accountDashBoardController.sessionCurrent;
final accountId = accountDashBoardController.accountId;
if (session == null
|| accountId.value == null
|| !PlatformInfo.isWeb) return;
final getIdentityCacheOnWebInteractor = getBinding<GetIdentityCacheOnWebInteractor>(
tag: BindingTag.restoreIdentityCacheInteractorBindingsTag);
if (getIdentityCacheOnWebInteractor == null) return;
consumeState(getIdentityCacheOnWebInteractor.execute(
accountId.value!,
session.username));
}
void _removeIdentityCache() {
final removeIdentityCacheOnWebInteractor = getBinding<RemoveIdentityCacheOnWebInteractor>(
tag: BindingTag.restoreIdentityCacheInteractorBindingsTag);
if (removeIdentityCacheOnWebInteractor == null) return;
consumeState(removeIdentityCacheOnWebInteractor.execute());
}
Future<void> _saveIdentityCacheOnWebAction(dynamic requestArgument) async {
final session = accountDashBoardController.sessionCurrent;
final accountId = accountDashBoardController.accountId;
if (accountId.value == null || session?.username == null) return;
IdentityCache? identityCache;
switch (requestArgument) {
case (CreateNewIdentityRequest createNewIdentityRequest):
identityCache = IdentityCache(
identity: createNewIdentityRequest.newIdentity,
identityActionType: IdentityActionType.create,
isDefault: createNewIdentityRequest.isDefaultIdentity,
publicAssetsInIdentityArguments: createNewIdentityRequest.publicAssetsInIdentityArguments);
break;
case (EditIdentityRequest editIdentityRequest):
identityCache = IdentityCache(
identity: editIdentityRequest.identityRequest.toIdentityWithId(editIdentityRequest.identityId),
identityActionType: IdentityActionType.edit,
isDefault: editIdentityRequest.isDefaultIdentity,
publicAssetsInIdentityArguments: editIdentityRequest.publicAssetsInIdentityArguments);
break;
default:
break;
}
if (identityCache == null) return;
consumeState(_saveIdentityCacheOnWebInteractor.execute(
accountId.value!,
session!.username,
identityCache: identityCache
));
}
@override
Future<void> onBeforeReconnect() => _saveIdentityCacheOnWebAction(newIdentityArguments);
@override
void onClose() {
CleanUpPublicAssetsInteractorBindings().close();
RestoreIdentityCacheInteractorBindings().close();
newIdentityArguments = null;
_beforeReconnectManager.removeListener(onBeforeReconnect);
super.onClose();
}
}
@@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/save_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_default_identity_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_identity_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/delete_identity_interactor.dart';
@@ -22,7 +23,8 @@ class IdentityBindings extends Bindings {
Get.find<EditIdentityInteractor>(),
Get.find<CreateNewDefaultIdentityInteractor>(),
Get.find<EditDefaultIdentityInteractor>(),
Get.find<TransformHtmlSignatureInteractor>()
Get.find<TransformHtmlSignatureInteractor>(),
Get.find<SaveIdentityCacheOnWebInteractor>(),
));
}
}
@@ -1,6 +1,11 @@
import 'package:core/presentation/utils/html_transformer/html_transform.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource/identity_creator_data_source.dart';
import 'package:tmail_ui_user/features/identity_creator/data/datasource_impl/local_identity_creator_data_source_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/data/repository/identity_creator_repository_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/save_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/data/datasource/identity_data_source.dart';
import 'package:tmail_ui_user/features/manage_account/data/datasource_impl/identity_data_source_impl.dart';
import 'package:tmail_ui_user/features/manage_account/data/network/identity_api.dart';
@@ -14,6 +19,7 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/edit_ident
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/transform_html_signature_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/utils/identity_utils.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
class IdentityInteractorsBindings extends InteractorsBindings {
@@ -27,6 +33,7 @@ class IdentityInteractorsBindings extends InteractorsBindings {
@override
void bindingsDataSource() {
Get.lazyPut<IdentityDataSource>(() => Get.find<IdentityDataSourceImpl>());
Get.lazyPut<IdentityCreatorDataSource>(() => Get.find<LocalIdentityCreatorDataSourceImpl>());
}
void _bindingsUtils() {
@@ -39,6 +46,9 @@ class IdentityInteractorsBindings extends InteractorsBindings {
Get.find<HtmlTransform>(),
Get.find<IdentityAPI>(),
Get.find<RemoteExceptionThrower>()));
Get.lazyPut(() => LocalIdentityCreatorDataSourceImpl(
Get.find<CacheExceptionThrower>()
));
}
@override
@@ -56,15 +66,20 @@ class IdentityInteractorsBindings extends InteractorsBindings {
Get.find<IdentityRepository>(),
Get.find<IdentityUtils>()));
Get.lazyPut(() => TransformHtmlSignatureInteractor(Get.find<IdentityRepository>()));
Get.lazyPut(() => SaveIdentityCacheOnWebInteractor(Get.find<IdentityCreatorRepository>()));
}
@override
void bindingsRepository() {
Get.lazyPut<IdentityRepository>(() => Get.find<IdentityRepositoryImpl>());
Get.lazyPut<IdentityCreatorRepository>(() => Get.find<IdentityCreatorRepositoryImpl>());
}
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => IdentityRepositoryImpl(Get.find<IdentityDataSource>()));
Get.lazyPut(() => IdentityCreatorRepositoryImpl(
Get.find<IdentityCreatorDataSource>()
));
}
}
@@ -2,4 +2,5 @@ class BindingTag {
static const isolateTag = 'isolateTag';
static const cleanUpPublicAssetsInteractorBindingsTag = 'CleanUpPublicAssetsInteractorBindingsTag';
static const publicAssetBindingsTag = 'PublicAssetBindingsTag';
static const restoreIdentityCacheInteractorBindingsTag = 'RestoreIdentityCacheInteractorBindingsTag';
}
@@ -0,0 +1,14 @@
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:model/identity/identity_request_dto.dart';
extension IdentityRequestDtoExtension on IdentityRequestDto {
Identity toIdentityWithId(IdentityId identityId) => Identity(
id: identityId,
name: name,
replyTo: replyTo,
bcc: bcc,
textSignature: textSignature,
htmlSignature: htmlSignature,
sortOrder: sortOrder,
);
}
@@ -30,6 +30,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/restore_deleted_mes
import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
@@ -171,6 +172,7 @@ const fallbackGenerators = {
MockSpec<ApplicationManager>(),
MockSpec<ToastManager>(),
MockSpec<GetAllIdentitiesInteractor>(),
MockSpec<GetIdentityCacheOnWebInteractor>(),
])
void main() {
// mock mailbox dashboard controller direct dependencies
@@ -179,6 +181,7 @@ void main() {
MockDeleteEmailPermanentlyInteractor();
final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor();
final getEmailCacheOnWebInteractor = MockGetComposerCacheOnWebInteractor();
final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor();
final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor();
final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor();
final markAsMultipleEmailReadInteractor =
@@ -317,6 +320,7 @@ void main() {
deleteEmailPermanentlyInteractor,
markAsMailboxReadInteractor,
getEmailCacheOnWebInteractor,
getIdentityCacheOnWebInteractor,
markAsEmailReadInteractor,
markAsStarEmailInteractor,
markAsMultipleEmailReadInteractor,
@@ -28,6 +28,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/restore_deleted_mes
import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
@@ -170,13 +171,15 @@ const fallbackGenerators = {
MockSpec<ApplicationManager>(),
MockSpec<GetAllIdentitiesInteractor>(),
MockSpec<GetQuotasInteractor>(),
MockSpec<ToastManager>()
MockSpec<ToastManager>(),
MockSpec<GetIdentityCacheOnWebInteractor>(),
])
void main() {
final moveToMailboxInteractor = MockMoveToMailboxInteractor();
final deleteEmailPermanentlyInteractor = MockDeleteEmailPermanentlyInteractor();
final markAsMailboxReadInteractor = MockMarkAsMailboxReadInteractor();
final getEmailCacheOnWebInteractor = MockGetComposerCacheOnWebInteractor();
final getIdentityCacheOnWebInteractor = MockGetIdentityCacheOnWebInteractor();
final markAsEmailReadInteractor = MockMarkAsEmailReadInteractor();
final markAsStarEmailInteractor = MockMarkAsStarEmailInteractor();
final markAsMultipleEmailReadInteractor = MockMarkAsMultipleEmailReadInteractor();
@@ -316,6 +319,7 @@ void main() {
deleteEmailPermanentlyInteractor,
markAsMailboxReadInteractor,
getEmailCacheOnWebInteractor,
getIdentityCacheOnWebInteractor,
markAsEmailReadInteractor,
markAsStarEmailInteractor,
markAsMultipleEmailReadInteractor,
@@ -11,10 +11,15 @@ import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/save_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart';
import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_default_identity_interactor.dart';
@@ -61,6 +66,11 @@ const fallbackGenerators = {
MockSpec<ApplicationManager>(),
MockSpec<ToastManager>(),
// Reloadable controller mockspecs
MockSpec<GetSessionInteractor>(),
MockSpec<GetAuthenticatedAccountInteractor>(),
MockSpec<UpdateAccountCacheInteractor>(),
// Identities controller mockspecs
MockSpec<GetAllIdentitiesInteractor>(),
MockSpec<DeleteIdentityInteractor>(),
@@ -70,6 +80,8 @@ const fallbackGenerators = {
MockSpec<EditDefaultIdentityInteractor>(),
MockSpec<TransformHtmlSignatureInteractor>(),
MockSpec<ManageAccountDashBoardController>(fallbackGenerators: fallbackGenerators),
MockSpec<SaveIdentityCacheOnWebInteractor>(),
MockSpec<BeforeReconnectManager>(),
])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
@@ -98,6 +110,8 @@ void main() {
late MockApplicationManager mockApplicationManager;
late MockToastManager mockToastManager;
late MockSaveIdentityCacheOnWebInteractor mockSaveIdentityCacheOnWebInteractor;
setUpAll(() {
//mock base controller
mockCachingManager = MockCachingManager();
@@ -114,6 +128,8 @@ void main() {
mockApplicationManager = MockApplicationManager();
mockToastManager = MockToastManager();
mockSaveIdentityCacheOnWebInteractor = MockSaveIdentityCacheOnWebInteractor();
Get.put<CachingManager>(mockCachingManager);
Get.put<LanguageCacheManager>(mockLanguageCacheManager);
Get.put<AuthorizationInterceptors>(mockAuthorizationInterceptors);
@@ -132,6 +148,11 @@ void main() {
Get.put<ApplicationManager>(mockApplicationManager);
Get.put<ToastManager>(mockToastManager);
// mock reloadable controller
Get.put<GetSessionInteractor>(MockGetSessionInteractor());
Get.put<GetAuthenticatedAccountInteractor>(MockGetAuthenticatedAccountInteractor());
Get.put<UpdateAccountCacheInteractor>(MockUpdateAccountCacheInteractor());
// mock identities controller
mockGetAllIdentitiesInteractor = MockGetAllIdentitiesInteractor();
mockDeleteIdentityInteractor = MockDeleteIdentityInteractor();
@@ -142,6 +163,7 @@ void main() {
mockTransformHtmlSignatureInteractor = MockTransformHtmlSignatureInteractor();
mockManageAccountDashBoardController = MockManageAccountDashBoardController();
Get.put<BeforeReconnectManager>(MockBeforeReconnectManager());
Get.put<ManageAccountDashBoardController>(mockManageAccountDashBoardController);
@@ -154,7 +176,8 @@ void main() {
mockEditIdentityInteractor,
mockCreateNewDefaultIdentityInteractor,
mockEditDefaultIdentityInteractor,
mockTransformHtmlSignatureInteractor);
mockTransformHtmlSignatureInteractor,
mockSaveIdentityCacheOnWebInteractor);
});
group('identities controller test:', () {