Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-17 18:53:42 +03:00
parent 9868dd2bc2
commit a3295ea181
12 changed files with 123 additions and 107 deletions

View file

@ -41,7 +41,6 @@ import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.legacy.asLockable
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import com.tangem.features.managetokens.navigation.ManageTokensUi
@ -440,10 +439,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
}
private fun navigateToInitialScreen(intentWhichStartedActivity: Intent?) {
val canSaveWallets = runCatching { userWalletsListManager.asLockable()?.isLockedSync }
.fold(onSuccess = { true }, onFailure = { false })
if (canSaveWallets && userWalletsListManager.hasUserWallets) {
if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
store.dispatch(
NavigationAction.NavigateTo(
screen = AppScreen.Welcome,

View file

@ -12,6 +12,7 @@ import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysRepository
import com.tangem.tap.domain.userWalletList.repository.UserWalletsPublicInformationRepository
import com.tangem.tap.domain.userWalletList.repository.UserWalletsSensitiveInformationRepository
import com.tangem.tap.domain.userWalletList.utils.encryptionKey
import com.tangem.tap.domain.userWalletList.utils.lockAll
import com.tangem.tap.domain.userWalletList.utils.toUserWallets
import com.tangem.tap.domain.userWalletList.utils.updateWith
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -27,6 +28,8 @@ internal class BiometricUserWalletsListManager(
) : UserWalletsListManager.Lockable {
private val state = MutableStateFlow(State())
override val isLockable: Boolean = true
override val userWallets: Flow<List<UserWallet>>
get() = state
.mapLatest { it.userWallets }
@ -78,11 +81,13 @@ internal class BiometricUserWalletsListManager(
}
override fun lock() {
state.update { State() }
}
override fun isLockable(): Boolean {
return true
state.update { prevState ->
prevState.copy(
encryptionKeys = emptyList(),
userWallets = prevState.userWallets.lockAll(),
isLocked = true,
)
}
}
override suspend fun select(userWalletId: UserWalletId): CompletionResult<UserWallet> = catching {

View file

@ -33,31 +33,49 @@ internal class GeneralUserWalletsListManager(
) : UserWalletsListManager.Lockable {
private val applicationScope = CoroutineScope(dispatchers.io)
private val implementation = MutableStateFlow(runtimeUserWalletsListManager)
private val implementation: MutableStateFlow<UserWalletsListManager?> = MutableStateFlow(value = null)
private val requireImplementation: UserWalletsListManager
get() = requireNotNull(implementation.value) {
"UserWalletsListManager is not initialized"
}
init {
subscribeOnCurrentManager()
}
override val isLockable: Boolean
get() = requireImplementation.isLockable
override val userWallets: Flow<List<UserWallet>>
get() = implementation.flatMapLatest { it.userWallets }
get() = implementation.transformLatest { impl ->
if (impl != null && impl.hasUserWallets) {
emitAll(impl.userWallets)
}
}
override val selectedUserWallet: Flow<UserWallet>
get() = implementation.flatMapLatest { it.selectedUserWallet }
get() = implementation.transformLatest { impl ->
if (impl != null && impl.hasUserWallets) {
emitAll(impl.selectedUserWallet)
}
}
override val selectedUserWalletSync: UserWallet?
get() = implementation.value.selectedUserWalletSync
get() = requireImplementation.selectedUserWalletSync
override val hasUserWallets: Boolean
get() = implementation.value.hasUserWallets
get() = requireImplementation.hasUserWallets
override val walletsCount: Int
get() = implementation.value.walletsCount
get() = requireImplementation.walletsCount
override val isLocked: Flow<Boolean>
get() = implementation.flatMapLatest {
if (it is UserWalletsListManager.Lockable) {
it.isLocked
get() = implementation.transformLatest { impl ->
if (impl == null) return@transformLatest
if (impl is UserWalletsListManager.Lockable) {
emitAll(impl.isLocked)
} else {
error("RuntimeUserWalletsListManager is not lockable")
}
@ -65,43 +83,45 @@ internal class GeneralUserWalletsListManager(
override val isLockedSync: Boolean
get() {
val implementation = implementation.value
return if (implementation is UserWalletsListManager.Lockable) {
implementation.isLockedSync
val impl = requireImplementation
return if (impl is UserWalletsListManager.Lockable) {
impl.isLockedSync
} else {
error("RuntimeUserWalletsListManager is not lockable")
}
}
override suspend fun select(userWalletId: UserWalletId): CompletionResult<UserWallet> {
return implementation.value.select(userWalletId)
return requireImplementation.select(userWalletId)
}
override suspend fun save(userWallet: UserWallet, canOverride: Boolean): CompletionResult<Unit> {
return implementation.value.save(userWallet, canOverride)
return requireImplementation.save(userWallet, canOverride)
}
override suspend fun update(
userWalletId: UserWalletId,
update: suspend (UserWallet) -> UserWallet,
): CompletionResult<UserWallet> {
return implementation.value.update(userWalletId, update)
return requireImplementation.update(userWalletId, update)
}
override suspend fun delete(userWalletIds: List<UserWalletId>): CompletionResult<Unit> {
return implementation.value.delete(userWalletIds)
return requireImplementation.delete(userWalletIds)
}
override suspend fun clear(): CompletionResult<Unit> {
return implementation.value.clear()
return requireImplementation.clear()
}
override suspend fun get(userWalletId: UserWalletId): CompletionResult<UserWallet> {
return implementation.value.get(userWalletId)
return requireImplementation.get(userWalletId)
}
override suspend fun unlock(type: UserWalletsListManager.Lockable.UnlockType): CompletionResult<UserWallet> {
val implementation = implementation.value
val implementation = requireImplementation
return if (implementation is UserWalletsListManager.Lockable) {
implementation.unlock(type)
} else {
@ -110,7 +130,8 @@ internal class GeneralUserWalletsListManager(
}
override fun lock() {
val implementation = implementation.value
val implementation = requireImplementation
return if (implementation is UserWalletsListManager.Lockable) {
implementation.lock()
} else {
@ -118,10 +139,6 @@ internal class GeneralUserWalletsListManager(
}
}
override fun isLockable(): Boolean {
return implementation.value.isLockable()
}
private fun subscribeOnCurrentManager() {
appPreferencesStore.get(key = PreferencesKeys.SAVE_USER_WALLETS_KEY, default = false)
.distinctUntilChanged()
@ -144,17 +161,17 @@ internal class GeneralUserWalletsListManager(
destinationManager = possibleManager,
)
previousManager.clear()
previousManager?.clear()
}
.flowOn(dispatchers.io)
.launchIn(applicationScope)
}
private suspend fun copySelectedUserWallet(
sourceManager: UserWalletsListManager,
sourceManager: UserWalletsListManager?,
destinationManager: UserWalletsListManager,
): UserWalletsListManager {
sourceManager.selectedUserWalletSync?.let { selectedWallet ->
sourceManager?.selectedUserWalletSync?.let { selectedWallet ->
destinationManager.save(selectedWallet, canOverride = true)
}

View file

@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.*
internal class RuntimeUserWalletsListManager : UserWalletsListManager {
private val state = MutableStateFlow(State())
override val isLockable: Boolean = false
override val userWallets: Flow<List<UserWallet>>
get() = state
.mapLatest { listOfNotNull(it.userWallet) }
@ -34,7 +36,7 @@ internal class RuntimeUserWalletsListManager : UserWalletsListManager {
* only 1 wallet stored in runtime implementation
*/
override val walletsCount: Int
get() = 1
get() = if (hasUserWallets) 1 else 0
override suspend fun select(userWalletId: UserWalletId): CompletionResult<UserWallet> = catching {
state.value.userWallet
@ -85,10 +87,6 @@ internal class RuntimeUserWalletsListManager : UserWalletsListManager {
state.value.userWallet ?: walletNotFound()
}
override fun isLockable(): Boolean {
return false
}
private fun saveInternal(userWallet: UserWallet): CompletionResult<Unit> = catching {
state.update { prevState ->
prevState.copy(

View file

@ -61,4 +61,14 @@ internal fun List<UserWallet>.updateWith(
?: wallet
}
}
}
}
internal fun List<UserWallet>.lockAll(): List<UserWallet> = map(UserWallet::lock)
internal fun UserWallet.lock(): UserWallet = copy(
scanResponse = scanResponse.copy(
card = scanResponse.card.copy(
wallets = emptyList(),
),
),
)