From 125b301a3223c2ade40bb2acccb356a023ff3a65 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 May 2024 14:29:37 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../details/redux/DetailsMiddleware.kt | 63 +++++++++++++++---- .../com/tangem/utils/extensions/Collection.kt | 5 ++ .../wallet/viewmodels/WalletViewModel.kt | 23 +++++-- 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 495afd0915..372889fe91 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -17,8 +17,9 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.builder.UserWalletBuilder import com.tangem.domain.wallets.builder.UserWalletIdBuilder +import com.tangem.domain.wallets.legacy.UserWalletsListError import com.tangem.domain.wallets.legacy.asLockable -import com.tangem.tap.* +import com.tangem.domain.wallets.models.UserWallet import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Settings import com.tangem.tap.common.extensions.* @@ -29,6 +30,9 @@ import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.proxy.redux.DaggerGraphState +import com.tangem.tap.scope +import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn import com.tangem.wallet.R @@ -503,37 +507,70 @@ class DetailsMiddleware { store.dispatchOnMain(NavigationAction.PopBackTo()) }, onSuccess = { scanResponse -> - saveUserWalletAndPopBackToWalletScreen(scanResponse) + createUserWallet(scanResponse) + .doOnSuccess { + saveUserWalletAndPopBackToWalletScreen( + userWallet = it, + prevUseBiometricsForAccessCode = prevUseBiometricsForAccessCode, + ) + } .doOnFailure { error -> - // Rollback policy if card saving was failed - cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) - Timber.e(error, "Unable to save user wallet") - - store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Error(error.toTextReference())) + Timber.e(error, "Unable to create user wallet") + handleError(error = error, prevUseBiometricsForAccessCode = prevUseBiometricsForAccessCode) } }, onFailure = { error -> - // Rollback policy if card scanning was failed - cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) Timber.e(error, "Unable to scan card") - store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Error(error.toTextReference())) + handleError(error = error, prevUseBiometricsForAccessCode = prevUseBiometricsForAccessCode) }, ) } - private suspend fun saveUserWalletAndPopBackToWalletScreen(scanResponse: ScanResponse): CompletionResult { + private suspend fun createUserWallet(scanResponse: ScanResponse): CompletionResult { val walletNameGenerateUseCase = store.inject(DaggerGraphState::generateWalletNameUseCase) val userWallet = UserWalletBuilder(scanResponse, walletNameGenerateUseCase).build() - ?: return CompletionResult.Failure(TangemSdkError.WalletIsNotCreated()) + return if (userWallet != null) { + CompletionResult.Success(userWallet) + } else { + CompletionResult.Failure(TangemSdkError.WalletIsNotCreated()) + } + } + + private suspend fun saveUserWalletAndPopBackToWalletScreen( + userWallet: UserWallet, + prevUseBiometricsForAccessCode: Boolean, + ) { val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager) - return userWalletsListManager.save(userWallet) + + userWalletsListManager.save(userWallet) .doOnSuccess { store.onUserWalletSelected(userWallet) store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success) store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet)) } + .doOnFailure { error -> + if (error is UserWalletsListError.WalletAlreadySaved) { + userWalletsListManager.select(userWallet.walletId) + store.onUserWalletSelected(userWallet) + + store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success) + store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet)) + } else { + Timber.e(error, "Unable to create user wallet") + handleError(error, prevUseBiometricsForAccessCode) + } + } + } + + private suspend fun handleError(error: TangemError, prevUseBiometricsForAccessCode: Boolean) { + val cardSdkConfigRepository = store.inject(DaggerGraphState::cardSdkConfigRepository) + + // Rollback policy if card saving was failed + cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) + + store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Error(error.toTextReference())) } private fun TangemError.toTextReference(): TextReference? { diff --git a/core/utils/src/main/java/com/tangem/utils/extensions/Collection.kt b/core/utils/src/main/java/com/tangem/utils/extensions/Collection.kt index 9930c5cb77..6ab240ea41 100644 --- a/core/utils/src/main/java/com/tangem/utils/extensions/Collection.kt +++ b/core/utils/src/main/java/com/tangem/utils/extensions/Collection.kt @@ -18,4 +18,9 @@ fun Collection.isSingleItem(): Boolean = this.size == 1 */ fun Collection.copy(): Collection { return this.map { it } +} + +inline fun List.indexOfFirstOrNull(predicate: (T) -> Boolean): Int? { + val index = indexOfFirst(predicate) + return if (index == -1) null else index } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index 912b4c81a3..44d391e849 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -9,6 +9,7 @@ import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.settings.CanUseBiometryUseCase import com.tangem.domain.settings.IsWalletsScrollPreviewEnabled import com.tangem.domain.settings.ShouldShowSaveWalletScreenUseCase +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.domain.wallets.usecase.GetWalletsUseCase import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler @@ -31,6 +32,7 @@ import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn +import com.tangem.utils.extensions.indexOfFirstOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* @@ -153,16 +155,29 @@ internal class WalletViewModel @Inject constructor( selectedWalletAnalyticsSender.send(selectedWallet) } - walletDeepLinksHandler.registerForWallet( - viewModel = this, - userWallet = selectedWallet, - ) + changeSelectedWalletState(selectedWalletId = selectedWallet.walletId) + + walletDeepLinksHandler.registerForWallet(viewModel = this, userWallet = selectedWallet) } .flowOn(dispatchers.main) .launchIn(viewModelScope) } } + /** Change selected wallet state if selected wallet [selectedWalletId] was changed in the background */ + private suspend fun changeSelectedWalletState(selectedWalletId: UserWalletId) { + if (screenLifecycleProvider.isBackgroundState.value && selectedWalletId != stateHolder.getSelectedWalletId()) { + stateHolder.value.wallets + .indexOfFirstOrNull { prevState -> prevState.walletCardState.id == selectedWalletId } + ?.let { selectedIndex -> + Timber.e("Selected wallet changed from background state: $selectedWalletId") + + delay(timeMillis = 1000) + scrollToWallet(selectedIndex) + } + } + } + // We need to update the current wallet if the application was in the background for more than 10 seconds // and then returned to the foreground private fun subscribeToScreenBackgroundState() {