Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-07 15:15:37 +03:00
parent 51b79c2941
commit cf8d176ab6
4 changed files with 81 additions and 56 deletions

View file

@ -72,6 +72,7 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
observeArtwork()
modelScope.launch {
createUserWalletIfNull()
cardRepository.finishCardActivation(scanResponse.card.cardId)
observeCryptoCurrencyStatus()
refreshBalance()
}
@ -163,10 +164,7 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
val amountToCreateAccount = (status.value as? CryptoCurrencyStatus.NoAccount)?.amountToCreateAccount
if (amount?.isPositive() == true || hasCurrentNetworkTransactions) {
modelScope.launch {
cardRepository.finishCardActivation(scanResponse.card.cardId)
params.onDone()
}
params.onDone()
}
_uiState.update {

View file

@ -27,6 +27,7 @@ import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.common.TwinCardNumber
import com.tangem.domain.common.getTwinCardNumber
import com.tangem.domain.common.util.twinsIsTwinned
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.scan.ScanResponse
@ -54,6 +55,7 @@ import com.tangem.sdk.extensions.localizedDescriptionRes
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.firstOrNull
@ -108,10 +110,14 @@ internal class OnboardingTwinModel @Inject constructor(
)
}
Mode.CreateWallet -> {
OnboardingTwinUM.Welcome(
pairCardNumber = firstCardTwinNumber.pairNumber().number,
onContinueClick = ::navigateToFirstScan,
)
if (params.scanResponse.twinsIsTwinned()) {
OnboardingTwinUM.TopUpPrepare
} else {
OnboardingTwinUM.Welcome(
pairCardNumber = firstCardTwinNumber.pairNumber().number,
onContinueClick = ::navigateToFirstScan,
)
}
}
},
)
@ -120,11 +126,19 @@ internal class OnboardingTwinModel @Inject constructor(
val innerNavigationState = MutableStateFlow(DefaultOnboardingTwinComponent.TwinInnerNavigationState(1))
init {
if (_uiState.value is OnboardingTwinUM.Welcome) {
analyticsEventHandler.send(OnboardingEvent.Twins.ScreenOpened)
modelScope.launch {
saveTwinsOnboardingShownUseCase()
when (_uiState.value) {
is OnboardingTwinUM.Welcome -> {
analyticsEventHandler.send(OnboardingEvent.Twins.ScreenOpened)
modelScope.launch {
saveTwinsOnboardingShownUseCase()
}
}
OnboardingTwinUM.TopUpPrepare -> {
modelScope.launch {
setTopUpState(params.scanResponse)
}
}
else -> {}
}
}
@ -298,55 +312,60 @@ internal class OnboardingTwinModel @Inject constructor(
Mode.CreateWallet -> {
modelScope.launch {
setLoading(true)
val userWallet = userWalletBuilderFactory.create(scanResponse).build() ?: run {
Timber.e("User wallet not created")
setLoading(false)
return@launch
}
userWalletsListManager.save(userWallet, canOverride = true)
fetchCurrencyStatusUseCase.invoke(
userWalletId = userWallet.walletId,
refresh = true,
).onLeft {
Timber.e("Unable to fetch currency status: $it")
setLoading(false)
}
val cryptoCurrencyStatus =
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId).firstOrNull()?.getOrNull()
?: run {
setLoading(false)
Timber.e("Unable to get currency status")
return@launch
}
launch {
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId)
.collect {
it.onRight { status ->
applyCryptoCurrencyStatusToState(status)
}
}
}
_uiState.value = OnboardingTwinUM.TopUp(
onBuyCryptoClick = { onBuyCryptoClick(cryptoCurrencyStatus) },
onRefreshClick = { onRefreshBalanceClick(userWallet) },
onShowAddressClick = { onShowAddressClick(cryptoCurrencyStatus) },
isLoading = true,
)
innerNavigationState.update {
it.copy(stackSize = 4)
}
setTopUpState(scanResponse)
}.saveIn(cryptoCurrencyStatusJobHolder)
}
}
}
private suspend fun setTopUpState(scanResponse: ScanResponse) = coroutineScope {
val userWallet = userWalletBuilderFactory.create(scanResponse).build() ?: run {
Timber.e("User wallet not created")
setLoading(false)
return@coroutineScope
}
userWalletsListManager.save(userWallet, canOverride = true)
cardRepository.finishCardActivation(params.scanResponse.card.cardId)
fetchCurrencyStatusUseCase.invoke(
userWalletId = userWallet.walletId,
refresh = true,
).onLeft {
Timber.e("Unable to fetch currency status: $it")
setLoading(false)
}
val cryptoCurrencyStatus =
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId).firstOrNull()?.getOrNull()
?: run {
setLoading(false)
Timber.e("Unable to get currency status")
return@coroutineScope
}
launch {
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId)
.collect {
it.onRight { status ->
applyCryptoCurrencyStatusToState(status)
}
}
}
_uiState.value = OnboardingTwinUM.TopUp(
onBuyCryptoClick = { onBuyCryptoClick(cryptoCurrencyStatus) },
onRefreshClick = { onRefreshBalanceClick(userWallet) },
onShowAddressClick = { onShowAddressClick(cryptoCurrencyStatus) },
isLoading = true,
)
innerNavigationState.update {
it.copy(stackSize = 4)
}
}
private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) {
val amount = (status.value as? CryptoCurrencyStatus.Loaded)?.amount ?: return
if (amount > BigDecimal.ZERO) {

View file

@ -62,6 +62,7 @@ internal fun OnboardingTwin(state: OnboardingTwinUM, modifier: Modifier = Modifi
is OnboardingTwinUM.ScanCard -> ScanCard(st)
is OnboardingTwinUM.TopUp -> TopUp(st)
is OnboardingTwinUM.Welcome -> Welcome(st)
OnboardingTwinUM.TopUpPrepare -> {}
}
}
}

View file

@ -11,6 +11,12 @@ internal sealed class OnboardingTwinUM {
abstract val isLoading: Boolean
abstract val artwork: TwinWalletArtworkUM
data object TopUpPrepare : OnboardingTwinUM() {
override val stepIndex: Int = 0
override val isLoading: Boolean = false
override val artwork: TwinWalletArtworkUM = TwinWalletArtworkUM.Spread
}
data class Welcome(
override val isLoading: Boolean = false,
val pairCardNumber: Int = 2,
@ -67,5 +73,6 @@ internal sealed class OnboardingTwinUM {
is ResetWarning -> copy()
is ScanCard -> copy(isLoading = isLoading)
is TopUp -> copy(isLoading = isLoading)
TopUpPrepare -> this
}
}