Updated on 2026-08-14

This commit is contained in:
Tangem 2024-03-22 14:25:38 +04:00
parent 3cd82a1782
commit e84ef9a182
4 changed files with 81 additions and 53 deletions

View file

@ -122,34 +122,38 @@ internal class GeneralUserWalletsListManager(
appPreferencesStore.get(key = PreferencesKeys.SAVE_USER_WALLETS_KEY, default = false)
.distinctUntilChanged()
.onEach { shouldSaveUserWallets ->
val manager = if (shouldSaveUserWallets) {
biometricUserWalletsListManager.copyFrom(runtimeUserWalletsListManager)
val possibleManager = if (shouldSaveUserWallets) {
biometricUserWalletsListManager
} else {
runtimeUserWalletsListManager.copyFrom(biometricUserWalletsListManager)
runtimeUserWalletsListManager
}
Timber.d("Switch to ${manager::class.java.simpleName}")
if (possibleManager == implementation.value) {
error("${possibleManager::class.simpleName}} is already selected")
}
implementation.value = manager
Timber.d("Switch to ${possibleManager::class.simpleName}")
clearOldManager(manager)
val previousManager = implementation.value
implementation.value = copySelectedUserWallet(
sourceManager = previousManager,
destinationManager = possibleManager,
)
previousManager.clear()
}
.flowOn(dispatchers.io)
.launchIn(applicationScope)
}
/** Copy data from [old] manager */
private suspend fun UserWalletsListManager.copyFrom(old: UserWalletsListManager): UserWalletsListManager {
old.selectedUserWalletSync?.let { this.save(it) }
return this
}
private suspend fun clearOldManager(current: UserWalletsListManager) {
if (current == biometricUserWalletsListManager) {
runtimeUserWalletsListManager.clear()
} else {
biometricUserWalletsListManager.clear()
private suspend fun copySelectedUserWallet(
sourceManager: UserWalletsListManager,
destinationManager: UserWalletsListManager,
): UserWalletsListManager {
sourceManager.selectedUserWalletSync?.let { selectedWallet ->
destinationManager.save(selectedWallet, canOverride = true)
}
return destinationManager
}
}

View file

@ -87,7 +87,13 @@ object OnboardingHelper {
backupCardsIds = backupCardsIds?.toSet(),
),
)
store.dispatchOnMain(SaveWalletAction.Save)
val toggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
if (toggles.isGeneralManagerEnabled) {
store.dispatchOnMain(SaveWalletAction.AllowToUseBiometrics)
} else {
store.dispatchOnMain(SaveWalletAction.Save)
}
}
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
// then open save wallet screen

View file

@ -12,6 +12,7 @@ import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.userwallets.UserWalletBuilder
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.legacy.isLockable
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.MainScreen
@ -23,11 +24,16 @@ import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.launch
import org.rekotlin.Middleware
import timber.log.Timber
internal class SaveWalletMiddleware {
private val saveWalletJobHolder = JobHolder()
val middleware: Middleware<AppState> = { _, stateProvider ->
{ next ->
{ action ->
@ -99,9 +105,7 @@ internal class SaveWalletMiddleware {
?: return@launch
val featureToggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
if (featureToggles.isGeneralManagerEnabled) {
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
} else {
if (!featureToggles.isGeneralManagerEnabled) {
provideLockableUserWalletsListManagerIfNot()
}
@ -143,7 +147,7 @@ internal class SaveWalletMiddleware {
},
)
}
}
}.saveIn(saveWalletJobHolder)
}
private fun allowToUseBiometrics(state: SaveWalletState) {
@ -152,10 +156,6 @@ internal class SaveWalletMiddleware {
return
}
val scanResponse = state.backupInfo?.scanResponse
?: store.state.globalState.scanResponse
?: return
if (state.backupInfo != null) {
// TODO: Remove after onboarding refactoring
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.On))
@ -164,31 +164,49 @@ internal class SaveWalletMiddleware {
}
scope.launch {
val userWallet = userWalletsListManager.selectedUserWalletSync
?: UserWalletBuilder(scanResponse)
.backupCardsIds(state.backupInfo?.backupCardsIds)
.build()
?: return@launch
val backupInfo = state.backupInfo
val userWalletFromBackup = backupInfo?.scanResponse
?.let(::UserWalletBuilder)
?.backupCardsIds(backupInfo.backupCardsIds)
?.build()
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
if (userWalletFromBackup != null) {
userWalletsListManager.save(userWalletFromBackup, canOverride = true)
.flatMap { saveAccessCodeIfNeeded(backupInfo.accessCode, userWalletFromBackup.cardsInWallet) }
.doOnFailure {
Timber.e(it, "Unable to save user wallet")
saveAccessCodeIfNeeded(accessCode = state.backupInfo?.accessCode, cardsInWallet = userWallet.cardsInWallet)
.flatMap {
userWalletsListManager.save(userWallet, canOverride = true)
}
.doOnFailure { error ->
store.dispatchWithMain(SaveWalletAction.Save.Error(error))
}
.doOnSuccess {
preferencesStorage.shouldSaveAccessCodes = true
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = userWallet.hasAccessCode,
)
store.dispatchWithMain(SaveWalletAction.Save.Error(it))
}
.doOnSuccess {
handleSavingSuccess(userWalletFromBackup)
}
} else {
/*
store.dispatchOnMain(SaveWalletAction.Save.Success)
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
* because it will be automatically saved on UserWalletsListManager switch
* */
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
val error = IllegalStateException("No selected user wallet")
Timber.e(error, "Unable to save user wallet")
store.dispatchWithMain(SaveWalletAction.Save.Error(TangemSdkError.ExceptionError(error)))
return@launch
}
}
handleSavingSuccess(selectedUserWallet)
}
}.saveIn(saveWalletJobHolder)
}
private suspend fun handleSavingSuccess(userWallet: UserWallet) {
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
preferencesStorage.shouldSaveAccessCodes = true
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = userWallet.hasAccessCode,
)
store.dispatchWithMain(SaveWalletAction.Save.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
}
private suspend fun provideLockableUserWalletsListManagerIfNot() {
@ -223,15 +241,15 @@ internal class SaveWalletMiddleware {
cardsInWallet: Set<String>,
): CompletionResult<Unit> {
return when {
accessCode != null -> {
accessCode.isNullOrBlank() -> {
CompletionResult.Success(Unit)
}
else -> {
tangemSdkManager.saveAccessCode(
accessCode = accessCode,
cardsIds = cardsInWallet,
)
}
else -> {
CompletionResult.Success(Unit)
}
}
}
}