Updated on 2026-08-14

This commit is contained in:
Tangem 2025-03-19 15:01:00 +05:00
parent 99b1e02c0a
commit 91e0956576
28 changed files with 338 additions and 57 deletions

View file

@ -26,9 +26,7 @@ import com.tangem.tap.store
import com.tangem.utils.extensions.stripZeroPlainString
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
@Deprecated("Use OnboardingNoteComponent")
class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
private var previousStep: OnboardingNoteStep = OnboardingNoteStep.None

View file

@ -5,7 +5,7 @@ import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.core.analytics.Analytics
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog

View file

@ -43,6 +43,8 @@ dependencies {
implementation(projects.domain.settings)
implementation(projects.domain.onboarding)
implementation(projects.domain.visa)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)
/** Tangem libraries */
implementation(projects.libs.tangemSdkApi)

View file

@ -1,4 +1,4 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.analytics
package com.tangem.features.onboarding.v2.common.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
@ -38,6 +38,16 @@ sealed class OnboardingEvent(
}
}
sealed class Topup(
event: String,
params: Map<String, String> = mapOf(),
) : OnboardingEvent("Onboarding / Top Up", event, params) {
object ScreenOpened : Topup("Activation Screen Opened")
object ButtonShowWalletAddress : Topup("Button - Show the Wallet Address")
}
sealed class Backup(
event: String,
params: Map<String, String> = mapOf(),

View file

@ -0,0 +1,25 @@
package com.tangem.features.onboarding.v2.common.ui
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
import com.tangem.features.onboarding.v2.impl.R
internal fun exitOnboardingDialog(onConfirm: () -> Unit): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.onboarding_exit_alert_title),
message = resourceReference(R.string.onboarding_exit_alert_message),
firstActionBuilder = {
EventMessageAction(
title = resourceReference(R.string.common_yes),
onClick = onConfirm,
)
},
secondActionBuilder = {
EventMessageAction(
title = resourceReference(R.string.common_cancel),
onClick = {},
)
},
)
}

View file

@ -1,4 +1,4 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.common.ui
package com.tangem.features.onboarding.v2.common.ui
import com.tangem.common.ui.alerts.models.AlertUM
import com.tangem.core.ui.extensions.TextReference

View file

@ -43,7 +43,7 @@ internal fun RefreshButton(isRefreshing: Boolean, onRefreshBalanceClick: () -> U
Icon(
painter = painterResource(id = R.drawable.ic_refresh_24),
contentDescription = null,
tint = TangemTheme.colors.text.disabled,
tint = TangemTheme.colors.text.primary1,
modifier = Modifier.padding(TangemTheme.dimens.spacing12),
)
}

View file

@ -26,7 +26,7 @@ import com.tangem.core.decompose.navigation.inner.InnerNavigation
import com.tangem.core.decompose.navigation.inner.InnerNavigationState
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.MultiWalletAccessCodeComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent

View file

@ -6,7 +6,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.ui.state.MultiWalletAccessCodeUM
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState

View file

@ -19,8 +19,8 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.scan.ProductType
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.backupCardAttestationFailedDialog

View file

@ -11,7 +11,7 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableSharedFlow

View file

@ -16,8 +16,8 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.resetCardDialog

View file

@ -1,7 +1,7 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state
import com.tangem.core.ui.extensions.TextReference
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
internal data class MultiWalletCreateWalletUM(
val title: TextReference,

View file

@ -1,6 +1,6 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui.state
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
internal data class MultiWalletFinalizeUM(
val step: Step = Step.Primary,

View file

@ -13,13 +13,13 @@ import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.builder.GenerateSeedPhraseUiStateBuilder
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.builder.ImportSeedPhraseUiStateBuilder
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.builder.SeedPhraseCheckUiStateBuilder
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.resetCardDialog
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider

View file

@ -4,8 +4,8 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.TextReference
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.GeneratedWordsType
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf

View file

@ -1,6 +1,7 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.common.ui
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.impl.R
internal fun resetCardDialog(onConfirm: () -> Unit, dismiss: () -> Unit, onDismissButtonClick: () -> Unit) =

View file

@ -10,7 +10,7 @@ import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.onboarding.repository.OnboardingRepository
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.interruptBackupDialog
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.FinalizeStage

View file

@ -1,6 +1,6 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.ui.state
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
internal data class OnboardingMultiWalletUM(
val artwork1Url: String? = null,

View file

@ -25,15 +25,16 @@ import com.tangem.features.onboarding.v2.note.api.OnboardingNoteComponent
import com.tangem.features.onboarding.v2.note.impl.child.create.OnboardingNoteCreateWalletComponent
import com.tangem.features.onboarding.v2.note.impl.child.topup.OnboardingNoteTopUpComponent
import com.tangem.features.onboarding.v2.note.impl.model.OnboardingNoteModel
import com.tangem.features.onboarding.v2.note.impl.model.OnboardingNoteCommonState
import com.tangem.features.onboarding.v2.note.impl.route.ONBOARDING_NOTE_STEPS_COUNT
import com.tangem.features.onboarding.v2.note.impl.route.OnboardingNoteRoute
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
internal class DefaultOnboardingNoteComponent @AssistedInject constructor(
@Assisted context: AppComponentContext,
@ -47,6 +48,7 @@ internal class DefaultOnboardingNoteComponent @AssistedInject constructor(
}
private val childParams = ChildParams(
commonState = model.commonUiState,
onBack = ::onChildBack,
parentBackEvent = currentChildBackEventHandle,
)
@ -70,15 +72,13 @@ internal class DefaultOnboardingNoteComponent @AssistedInject constructor(
override val state: StateFlow<InnerNavigationState> = model.innerNavigationState
override fun pop(onComplete: (Boolean) -> Unit) {
// TODO [REDACTED_TASK_KEY]
model.onChildBack(
currentRoute = childStack.value.active.configuration,
)
}
}
init {
componentScope.launch {
model.onDone.collect { params.onDone() }
}
// sets title and stepper value
childStack.subscribe(lifecycle) { stack ->
val currentRoute = stack.active.configuration
@ -96,14 +96,17 @@ internal class DefaultOnboardingNoteComponent @AssistedInject constructor(
appComponentContext = factoryContext,
params = OnboardingNoteCreateWalletComponent.Params(
childParams = childParams,
onDone = { model.stackNavigation.push(OnboardingNoteRoute.TopUp) },
onWalletCreated = { userWallet ->
model.onWalletCreated(userWallet)
model.stackNavigation.push(OnboardingNoteRoute.TopUp)
},
),
)
OnboardingNoteRoute.TopUp -> OnboardingNoteTopUpComponent(
appComponentContext = factoryContext,
params = OnboardingNoteTopUpComponent.Params(
childParams = childParams,
onDone = { model.onDone.tryEmit(Unit) },
onDone = { params.onDone() },
),
)
}
@ -134,6 +137,7 @@ internal class DefaultOnboardingNoteComponent @AssistedInject constructor(
}
data class ChildParams(
val commonState: MutableStateFlow<OnboardingNoteCommonState>,
val onBack: () -> Unit,
val parentBackEvent: SharedFlow<Unit>,
)

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.features.onboarding.v2.note.impl.DefaultOnboardingNoteComponent
import com.tangem.features.onboarding.v2.note.impl.child.create.model.OnboardingNoteCreateWalletModel
import com.tangem.features.onboarding.v2.note.impl.child.create.ui.OnboardingNoteCreateWallet
@ -24,7 +25,7 @@ internal class OnboardingNoteCreateWalletComponent(
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack } })
OnboardingNoteCreateWallet(
modifier = modifier,
@ -34,6 +35,6 @@ internal class OnboardingNoteCreateWalletComponent(
data class Params(
val childParams: DefaultOnboardingNoteComponent.ChildParams,
val onDone: () -> Unit,
val onWalletCreated: (UserWallet) -> Unit,
)
}

View file

@ -1,26 +1,104 @@
package com.tangem.features.onboarding.v2.note.impl.child.create.model
import com.tangem.common.CompletionResult
import com.tangem.core.analytics.Analytics
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.note.impl.child.create.OnboardingNoteCreateWalletComponent
import com.tangem.features.onboarding.v2.note.impl.child.create.ui.state.OnboardingNoteCreateWalletUM
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
@Suppress("UnusedPrivateMember")
@ModelScoped
internal class OnboardingNoteCreateWalletModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val tangemSdkManager: TangemSdkManager,
private val cardRepository: CardRepository,
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
private val saveWalletUseCase: SaveWalletUseCase,
) : Model() {
private val params = paramsContainer.require<OnboardingNoteCreateWalletComponent.Params>()
private val _uiState = MutableStateFlow(
OnboardingNoteCreateWalletUM(),
OnboardingNoteCreateWalletUM(
onCreateClick = ::onCreateWalletClick,
),
)
init {
Analytics.send(OnboardingEvent.CreateWallet.ScreenOpened)
modelScope.launch {
val scanResponse = params.childParams.commonState.value.scanResponse ?: return@launch
if (!cardRepository.isActivationStarted(scanResponse.card.cardId)) {
Analytics.send(OnboardingEvent.Started)
}
}
observeArtwork()
}
val uiState: StateFlow<OnboardingNoteCreateWalletUM> = _uiState
private fun onCreateWalletClick() {
modelScope.launch {
_uiState.update {
it.copy(createWalletInProgress = true)
}
val scanResponse = params.childParams.commonState.value.scanResponse ?: return@launch
val result = tangemSdkManager.createProductWallet(scanResponse)
when (result) {
is CompletionResult.Success -> {
Analytics.send(OnboardingEvent.CreateWallet.WalletCreatedSuccessfully())
cardRepository.startCardActivation(scanResponse.card.cardId)
createWalletAndNavigateBackWithDone(scanResponse.copy(card = result.data.card))
}
is CompletionResult.Failure -> _uiState.update {
it.copy(createWalletInProgress = false)
}
}
}
}
private fun createWalletAndNavigateBackWithDone(scanResponse: ScanResponse) {
modelScope.launch {
val userWallet = createUserWallet(scanResponse)
saveWalletUseCase(userWallet, canOverride = true).onRight {
cardRepository.finishCardActivation(scanResponse.card.cardId)
params.onWalletCreated(userWallet)
}
_uiState.update {
it.copy(createWalletInProgress = false)
}
}
}
private suspend fun createUserWallet(scanResponse: ScanResponse): UserWallet {
return requireNotNull(
value = userWalletBuilderFactory.create(scanResponse = scanResponse).build(),
lazyMessage = { "User wallet not created" },
)
}
private fun observeArtwork() {
modelScope.launch {
params.childParams.commonState.collect {
_uiState.value = _uiState.value.copy(
artworkUrl = it.cardArtworkUrl,
)
}
}
}
}

View file

@ -1,12 +1,23 @@
package com.tangem.features.onboarding.v2.note.impl.child.topup.model
import com.tangem.core.analytics.Analytics
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
import com.tangem.features.onboarding.v2.note.impl.child.topup.OnboardingNoteTopUpComponent
import com.tangem.features.onboarding.v2.note.impl.child.topup.ui.state.OnboardingNoteTopUpUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@Suppress("UnusedPrivateMember")
@ -14,11 +25,113 @@ import javax.inject.Inject
internal class OnboardingNoteTopUpModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
) : Model() {
private val params = paramsContainer.require<OnboardingNoteTopUpComponent.Params>()
private val scanResponse = params.childParams.commonState.value.scanResponse
private var userWallet: UserWallet? = null
private val _uiState = MutableStateFlow(
OnboardingNoteTopUpUM(),
OnboardingNoteTopUpUM(
onRefreshBalanceClick = ::refreshBalance,
onBuyCryptoClick = ::onBuyCryptoClick,
onShowWalletAddressClick = ::onShowWalletAddressClick,
),
)
val uiState: StateFlow<OnboardingNoteTopUpUM> = _uiState
init {
Analytics.send(OnboardingEvent.Topup.ScreenOpened)
observeArtwork()
modelScope.launch {
createUserWalletIfNull()
observeCryptoCurrencyStatus()
refreshBalance()
}
}
private fun refreshBalance() {
modelScope.launch {
showBalanceLoadingProgress(true)
createUserWalletIfNull()
val userWalletId = requireNotNull(userWallet?.walletId)
fetchCurrencyStatusUseCase(
userWalletId = userWalletId,
refresh = true,
)
showBalanceLoadingProgress(false)
}
}
private fun onBuyCryptoClick() {
// TODO [REDACTED_TASK_KEY]
}
private fun onShowWalletAddressClick() {
// TODO [REDACTED_TASK_KEY]
}
private suspend fun createUserWalletIfNull() {
if (userWallet != null) {
return
}
val commonState = params.childParams.commonState.value
userWallet = commonState.userWallet ?: createUserWallet(scanResponse)
}
private fun observeArtwork() {
modelScope.launch {
params.childParams.commonState.collect {
_uiState.value = _uiState.value.copy(
cardArtworkUrl = it.cardArtworkUrl,
)
}
}
}
private fun observeCryptoCurrencyStatus() {
val userWalletId = userWallet?.walletId ?: return
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId).map { it.getOrNull() }.filterNotNull()
.onEach(::applyCryptoCurrencyStatusToState).launchIn(modelScope)
}
private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) {
_uiState.update {
it.copy(
amountToCreateAccount = (status.value as? CryptoCurrencyStatus.NoAccount)
?.amountToCreateAccount
?.format(
{
crypto(
symbol = status.currency.symbol,
decimals = status.currency.decimals,
)
},
),
balance = (status.value as? CryptoCurrencyStatus.Loaded)?.amount?.format({
crypto(
symbol = status.currency.symbol,
decimals = status.currency.decimals,
)
},),
)
}
}
private fun showBalanceLoadingProgress(value: Boolean) {
_uiState.update {
it.copy(isRefreshing = value)
}
}
private suspend fun createUserWallet(scanResponse: ScanResponse): UserWallet {
return requireNotNull(
value = userWalletBuilderFactory.create(scanResponse = scanResponse).build(),
lazyMessage = { "User wallet not created" },
)
}
}

View file

@ -17,7 +17,6 @@ import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.note.impl.ALL_STEPS_TOP_CONTAINER_WEIGHT
import com.tangem.features.onboarding.v2.note.impl.child.topup.ui.state.OnboardingNoteTopUpUM
@Composable
@ -35,15 +34,16 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
isRefreshing = state.isRefreshing,
modifier = Modifier
.padding(horizontal = 34.dp)
.padding(top = 20.dp)
.weight(ALL_STEPS_TOP_CONTAINER_WEIGHT)
.padding(top = 16.dp)
.height(228.dp)
.fillMaxWidth(),
)
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(32.dp)
.padding(horizontal = 32.dp)
.padding(top = 16.dp)
.weight(1.0f),
horizontalAlignment = Alignment.CenterHorizontally,
) {

View file

@ -27,12 +27,14 @@ fun OnboardingNoteTopUpHeader(
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier.fillMaxWidth(),
modifier = modifier
.heightIn(min = 228.dp)
.widthIn(max = 450.dp),
contentAlignment = Alignment.Center,
) {
Box(
modifier = Modifier
.padding(vertical = 24.dp, horizontal = 32.dp)
.padding(vertical = 24.dp)
.fillMaxSize()
.background(
TangemTheme.colors.button.secondary,

View file

@ -0,0 +1,10 @@
package com.tangem.features.onboarding.v2.note.impl.model
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.models.UserWallet
internal data class OnboardingNoteCommonState(
val scanResponse: ScanResponse,
val cardArtworkUrl: String? = null,
val userWallet: UserWallet? = null,
)

View file

@ -4,46 +4,54 @@ import com.arkivanov.decompose.router.stack.StackNavigation
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
import com.tangem.features.onboarding.v2.common.ui.exitOnboardingDialog
import com.tangem.features.onboarding.v2.note.api.OnboardingNoteComponent
import com.tangem.features.onboarding.v2.note.impl.OnboardingNoteInnerNavigationState
import com.tangem.features.onboarding.v2.note.impl.route.OnboardingNoteRoute
import com.tangem.features.onboarding.v2.note.impl.route.stepNum
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
@ModelScoped
internal class OnboardingNoteModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val router: Router,
private val messageSender: UiMessageSender,
private val getCardImageUseCase: GetCardImageUseCase,
) : Model() {
@Suppress("UnusedPrivateMember")
private val params = paramsContainer.require<OnboardingNoteComponent.Params>()
private val _currentScanResponse = MutableStateFlow(params.scanResponse)
val initialRoute = OnboardingNoteRoute.CreateWallet // TODO [REDACTED_TASK_KEY]
val initialRoute = initializeRoute()
private val _innerNavigationState =
MutableStateFlow(OnboardingNoteInnerNavigationState(stackSize = initialRoute.stepNum()))
val currentScanResponse = _currentScanResponse.asStateFlow()
val innerNavigationState = _innerNavigationState.asStateFlow()
val onDone = MutableSharedFlow<Unit>()
val stackNavigation = StackNavigation<OnboardingNoteRoute>()
private val _uiState = MutableStateFlow(
OnboardingNoteState(),
OnboardingNoteCommonState(
scanResponse = params.scanResponse,
),
)
val uiState: StateFlow<OnboardingNoteState> = _uiState
val commonUiState: MutableStateFlow<OnboardingNoteCommonState> = _uiState
init {
loadArtworkUrl()
}
fun updateStepForNewRoute(route: OnboardingNoteRoute) {
_innerNavigationState.value = innerNavigationState.value.copy(
@ -53,6 +61,40 @@ internal class OnboardingNoteModel @Inject constructor(
@Suppress("UnusedPrivateMember")
fun onChildBack(currentRoute: OnboardingNoteRoute) {
// TODO [REDACTED_TASK_KEY]
messageSender.send(
exitOnboardingDialog(
onConfirm = {
router.pop()
},
),
)
}
fun onWalletCreated(userWallet: UserWallet) {
commonUiState.update {
it.copy(userWallet = userWallet)
}
}
private fun initializeRoute(): OnboardingNoteRoute {
val card = params.scanResponse.card
return if (card.wallets.isEmpty()) {
OnboardingNoteRoute.CreateWallet
} else {
OnboardingNoteRoute.TopUp
}
}
private fun loadArtworkUrl() {
modelScope.launch {
val cardInfo = params.scanResponse.card
val url = getCardImageUseCase(
cardId = cardInfo.cardId,
cardPublicKey = cardInfo.cardPublicKey,
)
_uiState.update {
it.copy(cardArtworkUrl = url)
}
}
}
}

View file

@ -1,5 +0,0 @@
package com.tangem.features.onboarding.v2.note.impl.model
data class OnboardingNoteState(
val cardArtworkUrl: String? = null,
)