Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-23 14:29:37 +08:00
parent 0b8efe6d02
commit 125b301a32
3 changed files with 74 additions and 17 deletions

View file

@ -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<Unit> {
private suspend fun createUserWallet(scanResponse: ScanResponse): CompletionResult<UserWallet> {
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? {

View file

@ -18,4 +18,9 @@ fun <T> Collection<T>.isSingleItem(): Boolean = this.size == 1
*/
fun <T> Collection<T>.copy(): Collection<T> {
return this.map { it }
}
inline fun <T> List<T>.indexOfFirstOrNull(predicate: (T) -> Boolean): Int? {
val index = indexOfFirst(predicate)
return if (index == -1) null else index
}

View file

@ -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() {