Updated on 2026-08-14
This commit is contained in:
parent
99b1e02c0a
commit
91e0956576
28 changed files with 338 additions and 57 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
@ -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 = {},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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) =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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" },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.model
|
||||
|
||||
data class OnboardingNoteState(
|
||||
val cardArtworkUrl: String? = null,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue