Updated on 2026-08-14
This commit is contained in:
parent
78996521c6
commit
ab5fac9196
41 changed files with 366 additions and 73 deletions
|
|
@ -6,7 +6,8 @@ import arrow.core.raise.ensure
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.builder.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||
import javax.inject.Inject
|
||||
|
|
@ -14,6 +15,7 @@ import javax.inject.Inject
|
|||
internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
|
||||
private val scanCardProcessor: ScanCardProcessor,
|
||||
private val saveWalletUseCase: SaveWalletUseCase,
|
||||
private val generateWalletNameUseCase: GenerateWalletNameUseCase,
|
||||
) {
|
||||
|
||||
private var scanFailsCounter = 0
|
||||
|
|
@ -31,7 +33,7 @@ internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
|
|||
scanFailsCounter = 0
|
||||
|
||||
// If card's public key is null then user wallet will be null
|
||||
val scannedWallet = UserWalletBuilder(scanResponse = result.data).build()
|
||||
val scannedWallet = UserWalletBuilder(result.data, generateWalletNameUseCase).build()
|
||||
|
||||
ensure(walletId == scannedWallet?.walletId) {
|
||||
ScanCardToUnlockWalletError.WrongCardIsScanned
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
|
||||
import timber.log.Timber
|
||||
|
||||
class WalletNameMigrationUseCase(
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val walletNamesMigrationRepository: WalletNamesMigrationRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke() {
|
||||
val wallets = userWalletsListManager.userWalletsSync
|
||||
|
||||
if (walletNamesMigrationRepository.isMigrationDone()) {
|
||||
return
|
||||
}
|
||||
|
||||
val existingNames: MutableSet<String> = mutableSetOf()
|
||||
wallets.indices.forEach { i ->
|
||||
val defaultName = wallets[i].name
|
||||
val suggestedWalletName = suggestedWalletName(defaultName, existingNames)
|
||||
if (defaultName != suggestedWalletName) {
|
||||
userWalletsListManager.update(wallets[i].walletId) { it.copy(name = suggestedWalletName) }
|
||||
}
|
||||
Timber.tag("Migrated names").e(i.toString() + " " + suggestedWalletName)
|
||||
}
|
||||
|
||||
walletNamesMigrationRepository.setMigrationDone()
|
||||
}
|
||||
|
||||
private fun suggestedWalletName(defaultName: String, existingNames: MutableSet<String>): String {
|
||||
val startIndex = 1
|
||||
for (index in startIndex..MAX_WALLETS_LIMIT) {
|
||||
val name = if (index == startIndex) defaultName else "$defaultName $index"
|
||||
|
||||
if (!existingNames.contains(name)) {
|
||||
existingNames.add(name)
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
return defaultName
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_WALLETS_LIMIT = 10000
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ internal sealed interface WalletAlertState {
|
|||
open val text: String = ""
|
||||
open val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
|
||||
abstract val onConfirmClick: (String) -> Unit
|
||||
abstract val errorTextProvider: (String) -> TextReference?
|
||||
}
|
||||
|
||||
data class DefaultAlert(
|
||||
|
|
@ -36,6 +37,7 @@ internal sealed interface WalletAlertState {
|
|||
data class RenameWalletAlert(
|
||||
override val text: String,
|
||||
override val onConfirmClick: (String) -> Unit,
|
||||
override val errorTextProvider: (String) -> TextReference?,
|
||||
) : TextInput() {
|
||||
override val title: TextReference = resourceReference(id = R.string.user_wallet_list_rename_popup_title)
|
||||
override val label: TextReference = resourceReference(id = R.string.user_wallet_list_rename_popup_placeholder)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,9 @@ private fun TextInputAlert(state: WalletAlertState.TextInput, onDismiss: () -> U
|
|||
fieldValue = value,
|
||||
confirmButton = DialogButton(
|
||||
title = state.confirmButtonText.resolveReference(),
|
||||
enabled = value.text.isNotEmpty() && value.text != state.text,
|
||||
enabled = value.text.isNotEmpty() &&
|
||||
value.text != state.text &&
|
||||
state.errorTextProvider(value.text) == null,
|
||||
onClick = {
|
||||
state.onConfirmClick(value.text)
|
||||
onDismiss()
|
||||
|
|
@ -76,6 +78,8 @@ private fun TextInputAlert(state: WalletAlertState.TextInput, onDismiss: () -> U
|
|||
dismissButton = DialogButton(title = stringResource(id = R.string.common_cancel), onClick = onDismiss),
|
||||
textFieldParams = AdditionalTextInputDialogParams(
|
||||
label = state.label.resolveReference(),
|
||||
isError = state.errorTextProvider(value.text) != null,
|
||||
caption = state.errorTextProvider(value.text)?.resolveReference(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler
|
|||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.SelectedWalletAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
|
||||
|
|
@ -57,6 +58,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
private val selectedWalletAnalyticsSender: SelectedWalletAnalyticsSender,
|
||||
private val walletDeepLinksHandler: WalletDeepLinksHandler,
|
||||
private val walletNameMigrationUseCase: WalletNameMigrationUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
val uiState: StateFlow<WalletScreenState> = stateHolder.uiState
|
||||
|
|
@ -71,12 +73,19 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
suggestToEnableBiometrics()
|
||||
|
||||
maybeMigrateNames()
|
||||
subscribeToUserWalletsUpdates()
|
||||
subscribeOnBalanceHiding()
|
||||
subscribeOnSelectedWalletFlow()
|
||||
subscribeToScreenBackgroundState()
|
||||
}
|
||||
|
||||
private fun maybeMigrateNames() {
|
||||
viewModelScope.launch {
|
||||
walletNameMigrationUseCase()
|
||||
}
|
||||
}
|
||||
|
||||
fun setWalletRouter(router: InnerWalletRouter) {
|
||||
this.router = router
|
||||
clickIntents.initialize(router, viewModelScope)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ package com.tangem.feature.wallet.presentation.wallet.viewmodels.intents
|
|||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.wallets.usecase.GetWalletNamesUseCase
|
||||
import com.tangem.domain.wallets.usecase.RenameWalletUseCase
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.domain.card.DeleteSavedAccessCodesUseCase
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
|
|
@ -11,7 +16,6 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.UpdateWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
|
|
@ -40,9 +44,10 @@ internal class WalletCardClickIntentsImplementor @Inject constructor(
|
|||
private val stateHolder: WalletStateController,
|
||||
private val walletEventSender: WalletEventSender,
|
||||
private val walletScreenContentLoader: WalletScreenContentLoader,
|
||||
private val renameWalletUseCase: RenameWalletUseCase,
|
||||
private val getWalletNamesUseCase: GetWalletNamesUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val updateWalletUseCase: UpdateWalletUseCase,
|
||||
private val deleteWalletUseCase: DeleteWalletUseCase,
|
||||
private val deleteSavedAccessCodesUseCase: DeleteSavedAccessCodesUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -54,19 +59,33 @@ internal class WalletCardClickIntentsImplementor @Inject constructor(
|
|||
override fun onRenameBeforeConfirmationClick(userWalletId: UserWalletId) {
|
||||
analyticsEventHandler.send(MainScreen.EditWalletTapped)
|
||||
|
||||
walletEventSender.send(
|
||||
event = WalletEvent.ShowAlert(
|
||||
state = WalletAlertState.RenameWalletAlert(
|
||||
text = stateHolder.getSelectedWallet().walletCardState.title,
|
||||
onConfirmClick = { onRenameAfterConfirmationClick(userWalletId, it) },
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val walletNames = getWalletNamesUseCase()
|
||||
val currentWalletName = stateHolder.getSelectedWallet().walletCardState.title
|
||||
walletEventSender.send(
|
||||
event = WalletEvent.ShowAlert(
|
||||
state = WalletAlertState.RenameWalletAlert(
|
||||
text = currentWalletName,
|
||||
onConfirmClick = { onRenameAfterConfirmationClick(userWalletId, it) },
|
||||
errorTextProvider = { enteredName ->
|
||||
if (walletNames.contains(enteredName) && enteredName != currentWalletName) {
|
||||
resourceReference(
|
||||
R.string.user_wallet_list_rename_popup_error_already_exists,
|
||||
wrappedList(enteredName),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRenameAfterConfirmationClick(userWalletId: UserWalletId, name: String) {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
updateWalletUseCase(userWalletId = userWalletId, update = { it.copy(name = name) })
|
||||
renameWalletUseCase(userWalletId = userWalletId, name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue