Updated on 2026-08-14
This commit is contained in:
parent
43a7201ac8
commit
c7458d8ab0
20 changed files with 544 additions and 124 deletions
|
|
@ -1,13 +1,21 @@
|
|||
package com.tangem.tap.features.onboarding.products.wallet.redux
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed class OnboardingWalletAction : Action {
|
||||
object Init : OnboardingWalletAction()
|
||||
object GetToCreateWalletStep : OnboardingWalletAction()
|
||||
object GetToSaltPayStep : OnboardingWalletAction()
|
||||
|
||||
object CreateWallet : OnboardingWalletAction()
|
||||
data class WalletWasCreated(
|
||||
val result: CompletionResult<CreateProductWalletTaskResponse>,
|
||||
) : OnboardingWalletAction()
|
||||
|
||||
object Done : OnboardingWalletAction()
|
||||
object FinishOnboarding : OnboardingWalletAction()
|
||||
|
||||
|
|
@ -19,6 +27,24 @@ sealed class OnboardingWalletAction : Action {
|
|||
object OnBackPressed : OnboardingWalletAction()
|
||||
}
|
||||
|
||||
sealed class OnboardingWallet2Action : OnboardingWalletAction() {
|
||||
data class Init(val maxProgress: Int) : OnboardingWallet2Action()
|
||||
data class SetDependencies(val maxProgress: Int) : OnboardingWallet2Action()
|
||||
|
||||
data class CreateWallet(
|
||||
val callback: (CompletionResult<CreateWalletResponse>) -> Unit,
|
||||
) : OnboardingWallet2Action()
|
||||
|
||||
data class ImportWallet(
|
||||
val mnemonicComponents: List<String>,
|
||||
val callback: (CompletionResult<CreateWalletResponse>) -> Unit,
|
||||
) : OnboardingWallet2Action()
|
||||
|
||||
data class WalletWasCreated(
|
||||
val result: CompletionResult<CreateWalletResponse>,
|
||||
) : OnboardingWallet2Action()
|
||||
}
|
||||
|
||||
sealed class BackupAction : Action {
|
||||
|
||||
object IntroduceBackup : BackupAction()
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.extensions.ifNotNull
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -20,6 +21,7 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.home.redux.HomeAction
|
||||
|
|
@ -29,12 +31,6 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivat
|
|||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
|
||||
import com.tangem.tap.features.wallet.models.toCurrencies
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdk
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.tap.userTokensRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.DispatchFunction
|
||||
|
|
@ -47,7 +43,10 @@ object OnboardingWalletMiddleware {
|
|||
private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
handleWalletAction(action, state, dispatch)
|
||||
when (action) {
|
||||
is OnboardingWallet2Action -> handleWallet2Action(action, state)
|
||||
else -> handleWalletAction(action, state, dispatch)
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
}
|
||||
|
|
@ -114,42 +113,44 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
}
|
||||
}
|
||||
is OnboardingWalletAction.CreateWallet -> {
|
||||
scanResponse ?: return
|
||||
scope.launch {
|
||||
scanResponse ?: return@launch
|
||||
val result = tangemSdkManager.createProductWallet(scanResponse)
|
||||
withMainContext {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
// here we must use updated scanResponse after createWallet & derivation
|
||||
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
|
||||
card = result.data.card,
|
||||
derivedKeys = result.data.derivedKeys,
|
||||
primaryCard = result.data.primaryCard,
|
||||
)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
|
||||
store.dispatchOnMain(OnboardingWalletAction.WalletWasCreated(result))
|
||||
}
|
||||
}
|
||||
is OnboardingWalletAction.WalletWasCreated -> {
|
||||
scanResponse ?: return
|
||||
when (val result = action.result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
// here we must use updated scanResponse after createWallet & derivation
|
||||
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
|
||||
card = result.data.card,
|
||||
derivedKeys = result.data.derivedKeys,
|
||||
primaryCard = result.data.primaryCard,
|
||||
)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
|
||||
|
||||
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
|
||||
DemoHelper.config.demoBlockchains
|
||||
} else {
|
||||
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
|
||||
}.map { blockchain ->
|
||||
BlockchainNetwork(blockchain, result.data.card)
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
userTokensRepository.saveUserTokens(
|
||||
card = result.data.card,
|
||||
tokens = blockchainNetworks.toCurrencies(),
|
||||
)
|
||||
}
|
||||
startCardActivation(updatedResponse)
|
||||
store.dispatch(OnboardingWalletAction.ResumeBackup)
|
||||
}
|
||||
is CompletionResult.Failure -> Unit
|
||||
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
|
||||
DemoHelper.config.demoBlockchains
|
||||
} else {
|
||||
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
|
||||
}.map { blockchain ->
|
||||
BlockchainNetwork(blockchain, result.data.card)
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
userTokensRepository.saveUserTokens(
|
||||
card = result.data.card,
|
||||
tokens = blockchainNetworks.toCurrencies(),
|
||||
)
|
||||
}
|
||||
startCardActivation(updatedResponse)
|
||||
store.dispatch(OnboardingWalletAction.ResumeBackup)
|
||||
}
|
||||
is CompletionResult.Failure -> Unit
|
||||
}
|
||||
}
|
||||
OnboardingWalletAction.FinishOnboarding -> {
|
||||
|
|
@ -194,6 +195,62 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleWallet2Action(action: OnboardingWallet2Action, state: () -> AppState?) {
|
||||
val globalState = store.state.globalState
|
||||
val onboardingManager = globalState.onboardingState.onboardingManager
|
||||
|
||||
val scanResponse = onboardingManager?.scanResponse
|
||||
|
||||
when (action) {
|
||||
is OnboardingWallet2Action.Init -> {
|
||||
if (scanResponse?.cardTypesResolver?.isWallet2() == true) {
|
||||
store.dispatch(OnboardingWallet2Action.SetDependencies(action.maxProgress))
|
||||
}
|
||||
}
|
||||
is OnboardingWallet2Action.CreateWallet -> {
|
||||
scanResponse ?: return
|
||||
scope.launch {
|
||||
val mediateResult = when (val result = tangemSdkManager.createProductWallet(scanResponse)) {
|
||||
is CompletionResult.Success -> {
|
||||
val response = CreateWalletResponse(
|
||||
card = result.data.card,
|
||||
derivedKeys = result.data.derivedKeys,
|
||||
primaryCard = result.data.primaryCard,
|
||||
)
|
||||
CompletionResult.Success(response)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
CompletionResult.Failure(result.error)
|
||||
}
|
||||
}
|
||||
withMainContext {
|
||||
action.callback(mediateResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingWallet2Action.ImportWallet -> {
|
||||
// TODO: implement
|
||||
}
|
||||
is OnboardingWallet2Action.WalletWasCreated -> {
|
||||
val result = when (val mediateResult = action.result) {
|
||||
is CompletionResult.Success -> {
|
||||
val response = CreateProductWalletTaskResponse(
|
||||
card = mediateResult.data.card,
|
||||
derivedKeys = mediateResult.data.derivedKeys,
|
||||
primaryCard = mediateResult.data.primaryCard,
|
||||
)
|
||||
CompletionResult.Success(response)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
CompletionResult.Failure(mediateResult.error)
|
||||
}
|
||||
}
|
||||
store.dispatchOnMain(OnboardingWalletAction.WalletWasCreated(result))
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateScanResponseAfterBackup(scanResponse: ScanResponse, backupState: BackupState): ScanResponse {
|
||||
val card = if (backupState.backupCardsNumber > 0) {
|
||||
val cardsCount = backupState.backupCardsNumber
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingWallet
|
|||
is GlobalAction.Onboarding -> ReducerForGlobalAction.reduce(action, state)
|
||||
is OnboardingSaltPayAction -> OnboardingSaltPayReducer.reduce(action, state)
|
||||
is BackupAction -> state.copy(backupState = BackupReducer.reduce(action, state.backupState, state.isSaltPay))
|
||||
|
||||
is OnboardingWalletAction.GetToCreateWalletStep -> OnboardingWalletState(
|
||||
is OnboardingWallet2Action -> OnboardingWallet2Reducer.reduce(action, state)
|
||||
is OnboardingWalletAction.GetToCreateWalletStep -> state.copy(
|
||||
step = OnboardingWalletStep.CreateWallet,
|
||||
)
|
||||
is OnboardingWalletAction.GetToSaltPayStep -> state.copy(
|
||||
|
|
@ -65,6 +65,17 @@ private object ReducerForGlobalAction {
|
|||
private fun maxBackupCards(isSaltPay: Boolean): Int = if (isSaltPay) 1 else 2
|
||||
}
|
||||
|
||||
private object OnboardingWallet2Reducer {
|
||||
fun reduce(action: OnboardingWallet2Action, state: OnboardingWalletState): OnboardingWalletState = when (action) {
|
||||
is OnboardingWallet2Action.SetDependencies -> state.copy(
|
||||
wallet2State = OnboardingWallet2State(
|
||||
maxProgress = action.maxProgress,
|
||||
),
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
||||
private object BackupReducer {
|
||||
@Suppress("ComplexMethod")
|
||||
fun reduce(action: BackupAction, state: BackupState, isSaltPay: Boolean): BackupState {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import org.rekotlin.StateType
|
|||
*/
|
||||
data class OnboardingWalletState(
|
||||
val step: OnboardingWalletStep = OnboardingWalletStep.None,
|
||||
val wallet2State: OnboardingWallet2State? = null,
|
||||
val backupState: BackupState = BackupState(),
|
||||
val onboardingSaltPayState: OnboardingSaltPayState? = null,
|
||||
val isSaltPay: Boolean = false,
|
||||
|
|
@ -31,14 +32,14 @@ data class OnboardingWalletState(
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun getMaxProgress(): Int = when {
|
||||
isSaltPay -> 12
|
||||
else -> 6
|
||||
fun getMaxProgress(): Int {
|
||||
val baseProgress = if (isSaltPay) 12 else 6
|
||||
return getWallet2Progress() + baseProgress
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod", "MagicNumber")
|
||||
fun getProgressStep(): Int {
|
||||
return when {
|
||||
val progressByStep = when {
|
||||
step == OnboardingWalletStep.CreateWallet -> 1
|
||||
step == OnboardingWalletStep.Backup -> {
|
||||
when (backupState.backupStep) {
|
||||
|
|
@ -69,11 +70,19 @@ data class OnboardingWalletState(
|
|||
step == OnboardingWalletStep.Done -> getMaxProgress()
|
||||
else -> 1
|
||||
}
|
||||
|
||||
return getWallet2Progress() + progressByStep
|
||||
}
|
||||
|
||||
private fun getWallet2Progress(): Int = wallet2State?.maxProgress ?: 0
|
||||
}
|
||||
|
||||
data class OnboardingWallet2State(
|
||||
val maxProgress: Int,
|
||||
)
|
||||
|
||||
enum class OnboardingWalletStep {
|
||||
None, CreateWallet, Backup, SaltPay, Done
|
||||
None, CreateWallet, SaltPay, Backup, Done
|
||||
}
|
||||
|
||||
data class BackupState(
|
||||
|
|
|
|||
|
|
@ -18,15 +18,7 @@ import com.tangem.common.extensions.guard
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.compose.PinCodeWidget
|
||||
import com.tangem.tap.common.extensions.configureSettings
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.setDrawable
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.extensions.stop
|
||||
import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.feedback.SupportInfo
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
|
|
@ -34,11 +26,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction
|
|||
import com.tangem.tap.common.toggleWidget.IndeterminateProgressButtonWidget
|
||||
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.*
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebChromeClient
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebViewClient
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
|
||||
|
|
@ -56,7 +44,7 @@ import com.tangem.wallet.databinding.LayoutOnboardingMainBinding
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class OnboardingSaltPayView(
|
||||
internal class OnboardingSaltPayStateHandler(
|
||||
private val walletFragment: OnboardingWalletFragment,
|
||||
) {
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.tangem.tap.features.onboarding.products.wallet.ui
|
||||
|
||||
import com.tangem.feature.onboarding.api.OnboardingSeedPhrase
|
||||
import com.tangem.feature.onboarding.api.OnboardingSeedPhraseApi
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class OnboardingSeedPhraseStateHandler(
|
||||
private val walletFragment: OnboardingWalletFragment,
|
||||
private val onboardingSeedPhraseApi: OnboardingSeedPhraseApi = OnboardingSeedPhrase(),
|
||||
) {
|
||||
|
||||
fun newState(state: OnboardingWalletState, seedPhraseViewModel: SeedPhraseViewModel) {
|
||||
if (state.step == OnboardingWalletStep.CreateWallet && !seedPhraseViewModel.isFinished) {
|
||||
switchToWallet2SeedPhraseOnboarding(state, seedPhraseViewModel)
|
||||
} else {
|
||||
switchToWalletOnboarding(state)
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchToWalletOnboarding(state: OnboardingWalletState) {
|
||||
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.hide()
|
||||
walletFragment.pbBinding.pbState.show()
|
||||
walletFragment.binding.onboardingWalletContainer.show()
|
||||
walletFragment.handleOnboardingStep(state)
|
||||
}
|
||||
|
||||
private fun switchToWallet2SeedPhraseOnboarding(
|
||||
state: OnboardingWalletState,
|
||||
seedPhraseViewModel: SeedPhraseViewModel,
|
||||
) {
|
||||
walletFragment.pbBinding.pbState.hide()
|
||||
walletFragment.binding.onboardingWalletContainer.hide()
|
||||
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.show()
|
||||
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.setContent {
|
||||
onboardingSeedPhraseApi.ScreenContent(
|
||||
viewModel = seedPhraseViewModel,
|
||||
maxProgress = state.getMaxProgress(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import android.widget.FrameLayout
|
|||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.transition.TransitionInflater
|
||||
import androidx.transition.TransitionManager
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
|
|
@ -17,46 +18,53 @@ import coil.load
|
|||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.tangem.common.CardIdFormatter
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseMediator
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseRouter
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
|
||||
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.sdk.ui.widget.leapfrogWidget.PropertyCalculator
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.inflate
|
||||
import com.tangem.tap.common.extensions.resourceUri
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.feedback.SupportInfo
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.BaseFragment
|
||||
import com.tangem.tap.features.FragmentOnBackPressedHandler
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.onboarding.OnboardingMenuProvider
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.*
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayView
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayStateHandler
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.FragmentOnboardingWalletBinding
|
||||
import com.tangem.wallet.databinding.LayoutOnboardingSaltpayBinding
|
||||
import com.tangem.wallet.databinding.LayoutOnboardingSeedPhraseBinding
|
||||
import com.tangem.wallet.databinding.ViewOnboardingProgressBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.rekotlin.StoreSubscriber
|
||||
|
||||
@Suppress("LargeClass", "MagicNumber")
|
||||
@AndroidEntryPoint
|
||||
class OnboardingWalletFragment :
|
||||
BaseFragment(R.layout.fragment_onboarding_wallet),
|
||||
StoreSubscriber<OnboardingWalletState>,
|
||||
FragmentOnBackPressedHandler {
|
||||
|
||||
private val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind)
|
||||
internal val binding: FragmentOnboardingWalletBinding by viewBinding(FragmentOnboardingWalletBinding::bind)
|
||||
internal val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind)
|
||||
|
||||
internal val bindingSeedPhrase: LayoutOnboardingSeedPhraseBinding by lazy { binding.onboardingSeedPhraseContainer }
|
||||
internal val bindingSaltPay: LayoutOnboardingSaltpayBinding by lazy { binding.onboardingSaltpayContainer }
|
||||
|
||||
private val onboardingSaltPayView: OnboardingSaltPayView = OnboardingSaltPayView(this)
|
||||
private val seedPhraseStateHandler: OnboardingSeedPhraseStateHandler = OnboardingSeedPhraseStateHandler(this)
|
||||
private val seedPhraseViewModel by viewModels<SeedPhraseViewModel>()
|
||||
|
||||
private val saltPayStateHandler: OnboardingSaltPayStateHandler = OnboardingSaltPayStateHandler(this)
|
||||
|
||||
private lateinit var cardsWidget: WalletCardsWidget
|
||||
private var accessCodeDialog: AccessCodeDialog? = null
|
||||
|
|
@ -69,6 +77,13 @@ class OnboardingWalletFragment :
|
|||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
seedPhraseViewModel.setRouter(makeSeedPhraseRouter())
|
||||
seedPhraseViewModel.setMediator(makeSeedPhraseMediator())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
|
@ -88,6 +103,7 @@ class OnboardingWalletFragment :
|
|||
binding.toolbar.setNavigationOnClickListener { activity?.onBackPressed() }
|
||||
addBackPressHandler(this)
|
||||
|
||||
store.dispatch(OnboardingWallet2Action.Init(seedPhraseViewModel.maxProgress))
|
||||
store.dispatch(OnboardingWalletAction.Init)
|
||||
store.dispatch(OnboardingSaltPayAction.Init)
|
||||
store.dispatch(
|
||||
|
|
@ -159,13 +175,19 @@ class OnboardingWalletFragment :
|
|||
pbBinding.pbState.max = state.getMaxProgress()
|
||||
pbBinding.pbState.progress = state.getProgressStep()
|
||||
|
||||
if (state.isSaltPay) {
|
||||
onboardingSaltPayView.newState(state)
|
||||
} else {
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard)
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvSecondBackupCard)
|
||||
handleOnboardingStep(state)
|
||||
when {
|
||||
state.wallet2State != null -> {
|
||||
seedPhraseStateHandler.newState(state, seedPhraseViewModel)
|
||||
}
|
||||
state.isSaltPay -> {
|
||||
saltPayStateHandler.newState(state)
|
||||
}
|
||||
else -> {
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard)
|
||||
loadImageIntoImageView(state.cardArtworkUri, binding.imvSecondBackupCard)
|
||||
handleOnboardingStep(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +293,7 @@ class OnboardingWalletFragment :
|
|||
layoutButtonsAddCards.btnContinue.isEnabled = state.backupCardsNumber != 0
|
||||
|
||||
if (isSaltPay) {
|
||||
onboardingSaltPayView.showAddBackupCards(state)
|
||||
saltPayStateHandler.showAddBackupCards(state)
|
||||
} else {
|
||||
when (state.backupCardsNumber) {
|
||||
0 -> {
|
||||
|
|
@ -443,4 +465,33 @@ class OnboardingWalletFragment :
|
|||
resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true)
|
||||
return typedValue.float
|
||||
}
|
||||
|
||||
private fun makeSeedPhraseRouter(): SeedPhraseRouter = SeedPhraseRouter(
|
||||
onBack = ::handleOnBackPressed,
|
||||
onOpenChat = {
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
},
|
||||
onOpenUriClick = { uri ->
|
||||
store.dispatchOpenUrl(uri.toString())
|
||||
},
|
||||
)
|
||||
|
||||
private fun makeSeedPhraseMediator(): SeedPhraseMediator {
|
||||
return object : SeedPhraseMediator {
|
||||
override fun createWallet(callback: (CompletionResult<CreateWalletResponse>) -> Unit) {
|
||||
store.dispatch(OnboardingWallet2Action.CreateWallet(callback))
|
||||
}
|
||||
|
||||
override fun onWalletCreated(result: CompletionResult<CreateWalletResponse>) {
|
||||
store.dispatch(OnboardingWallet2Action.WalletWasCreated(result))
|
||||
}
|
||||
|
||||
override fun importWallet(
|
||||
mnemonicComponents: List<String>,
|
||||
callback: (CompletionResult<CreateWalletResponse>) -> Unit,
|
||||
) {
|
||||
store.dispatch(OnboardingWallet2Action.ImportWallet(mnemonicComponents, callback))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,6 +228,13 @@
|
|||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include
|
||||
android:id="@+id/onboarding_seed_phrase_container"
|
||||
layout="@layout/layout_onboarding_seed_phrase"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<include
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.compose.ui.platform.ComposeView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/onboarding_seed_phrase_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
|
@ -26,7 +26,8 @@ class TangemCardTypesResolver(
|
|||
card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable &&
|
||||
!card.isSaltPay
|
||||
|
||||
override fun isWallet2(): Boolean = card.firmwareVersion >= FirmwareVersion.KeysImportAvailable
|
||||
// override fun isWallet2(): Boolean = card.firmwareVersion >= FirmwareVersion.KeysImportAvailable
|
||||
override fun isWallet2(): Boolean = true
|
||||
override fun isSaltPay(): Boolean = productType == ProductType.SaltPay
|
||||
override fun isSaltPayVisa(): Boolean = card.isSaltPayVisa
|
||||
override fun isSaltPayWallet(): Boolean = card.isSaltPayWallet
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ plugins {
|
|||
dependencies {
|
||||
/** Core modules */
|
||||
implementation(project(":common"))
|
||||
implementation(project(":domain:models"))
|
||||
implementation(project(":core:featuretoggles"))
|
||||
implementation(project(":core:datasource"))
|
||||
implementation(project(":core:analytics"))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
package com.tangem.feature.onboarding.api
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.ui.*
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseScreen
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class OnboardingSeedPhrase : OnboardingSeedPhraseApi {
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(viewModel: SeedPhraseViewModel, maxProgress: Int) {
|
||||
BackHandler(onBack = viewModel.uiState.onBackClick)
|
||||
TangemTheme {
|
||||
Column {
|
||||
ProgressIndicator(viewModel.progress, maxProgress)
|
||||
Content(viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressIndicator(progress: Int, maxProgress: Int) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(top = TangemTheme.dimens.size8),
|
||||
) {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.size16),
|
||||
color = TangemTheme.colors.background.action,
|
||||
backgroundColor = TangemTheme.colors.background.action.copy(alpha = 0.081f),
|
||||
progress = progress.toFloat() / maxProgress,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(viewModel: SeedPhraseViewModel) {
|
||||
when (viewModel.currentScreen) {
|
||||
SeedPhraseScreen.Intro -> {
|
||||
IntroScreen(
|
||||
state = viewModel.uiState.introState,
|
||||
)
|
||||
}
|
||||
SeedPhraseScreen.AboutSeedPhrase -> {
|
||||
AboutSeedPhraseScreen(
|
||||
state = viewModel.uiState.aboutState,
|
||||
)
|
||||
}
|
||||
SeedPhraseScreen.YourSeedPhrase -> {
|
||||
YourSeedPhraseScreen(
|
||||
state = viewModel.uiState.yourSeedPhraseState,
|
||||
)
|
||||
}
|
||||
SeedPhraseScreen.CheckSeedPhrase -> {
|
||||
CheckSeedPhraseScreen(
|
||||
state = viewModel.uiState.checkSeedPhraseState,
|
||||
)
|
||||
}
|
||||
SeedPhraseScreen.ImportSeedPhrase -> {
|
||||
ImportSeedPhraseScreen(
|
||||
state = viewModel.uiState.importSeedPhraseState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.feature.onboarding.api
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface OnboardingSeedPhraseApi {
|
||||
@Suppress("TopLevelComposableFunctions")
|
||||
@Composable
|
||||
fun ScreenContent(viewModel: SeedPhraseViewModel, maxProgress: Int)
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.feature.onboarding.data.model
|
||||
|
||||
import com.tangem.common.extensions.ByteArrayKey
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.operations.backup.PrimaryCard
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
data class CreateWalletResponse(
|
||||
val card: CardDTO,
|
||||
val derivedKeys: Map<ByteArrayKey, ExtendedPublicKeysMap> = mapOf(),
|
||||
val primaryCard: PrimaryCard? = null,
|
||||
)
|
||||
|
|
@ -9,20 +9,15 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
data class OnboardingSeedPhraseState(
|
||||
val step: OnboardingSeedPhraseStep,
|
||||
val introState: IntroState,
|
||||
val aboutState: AboutState,
|
||||
val yourSeedPhraseState: YourSeedPhraseState,
|
||||
val checkSeedPhraseState: CheckSeedPhraseState,
|
||||
val importSeedPhraseState: ImportSeedPhraseState,
|
||||
val menuButtonChat: ButtonState,
|
||||
val isOnboardingFinished: Boolean = false,
|
||||
val onBackClick: () -> Unit,
|
||||
)
|
||||
|
||||
enum class OnboardingSeedPhraseStep {
|
||||
Intro, AboutSeedPhrase, YourSeedPhrase, CheckSeedPhrase, ImportSeedPhrase
|
||||
}
|
||||
|
||||
data class IntroState(
|
||||
val cardImageUrl: String? = null,
|
||||
val buttonCreateWallet: ButtonState,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ data class UiActions(
|
|||
val checkSeedPhraseActions: CheckSeedPhraseUiAction,
|
||||
val importSeedPhraseActions: ImportSeedPhraseUiAction,
|
||||
val menuChatClick: () -> Unit,
|
||||
val menuNavigateBackClick: () -> Unit,
|
||||
)
|
||||
|
||||
data class IntroUiAction(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ class StateBuilder(
|
|||
val importSeedPhrase: ImportSeedPhraseStateBuilder = ImportSeedPhraseStateBuilder()
|
||||
|
||||
fun init(): OnboardingSeedPhraseState = OnboardingSeedPhraseState(
|
||||
step = OnboardingSeedPhraseStep.Intro,
|
||||
introState = IntroState(
|
||||
buttonCreateWallet = ButtonState(
|
||||
onClick = uiActions.introActions.buttonCreateWalletClick,
|
||||
|
|
@ -77,13 +76,9 @@ class StateBuilder(
|
|||
menuButtonChat = ButtonState(
|
||||
onClick = uiActions.menuChatClick,
|
||||
),
|
||||
onBackClick = uiActions.menuNavigateBackClick,
|
||||
)
|
||||
|
||||
fun changeStep(uiState: OnboardingSeedPhraseState, step: OnboardingSeedPhraseStep): OnboardingSeedPhraseState =
|
||||
uiState.copy(
|
||||
step = step,
|
||||
)
|
||||
|
||||
fun generateMnemonicComponents(uiState: OnboardingSeedPhraseState): OnboardingSeedPhraseState {
|
||||
return uiState.copy(
|
||||
aboutState = uiState.aboutState.copy(
|
||||
|
|
@ -103,7 +98,6 @@ class StateBuilder(
|
|||
): OnboardingSeedPhraseState {
|
||||
return updateMnemonicComponents(uiState, mnemonicGridItems)
|
||||
.copy(
|
||||
step = OnboardingSeedPhraseStep.YourSeedPhrase,
|
||||
aboutState = uiState.aboutState.copy(
|
||||
buttonGenerateSeedPhrase = uiState.aboutState.buttonGenerateSeedPhrase.copy(
|
||||
showProgress = false,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.feature.onboarding.presentation.wallet2.viewmodel
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface SeedPhraseMediator {
|
||||
fun createWallet(callback: (CompletionResult<CreateWalletResponse>) -> Unit)
|
||||
fun importWallet(mnemonicComponents: List<String>, callback: (CompletionResult<CreateWalletResponse>) -> Unit)
|
||||
|
||||
fun onWalletCreated(result: CompletionResult<CreateWalletResponse>)
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.tangem.feature.onboarding.presentation.wallet2.viewmodel
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SeedPhraseRouter(
|
||||
private val onBack: () -> Unit,
|
||||
private val onOpenChat: () -> Unit,
|
||||
private val onOpenUriClick: (Uri) -> Unit,
|
||||
) {
|
||||
|
||||
var currentScreen by mutableStateOf(SeedPhraseScreen.Intro)
|
||||
private set
|
||||
|
||||
fun navigateBack() {
|
||||
currentScreen = when (currentScreen) {
|
||||
SeedPhraseScreen.Intro -> {
|
||||
onBack.invoke()
|
||||
return
|
||||
}
|
||||
SeedPhraseScreen.AboutSeedPhrase -> SeedPhraseScreen.Intro
|
||||
SeedPhraseScreen.YourSeedPhrase -> SeedPhraseScreen.AboutSeedPhrase
|
||||
SeedPhraseScreen.CheckSeedPhrase -> SeedPhraseScreen.YourSeedPhrase
|
||||
SeedPhraseScreen.ImportSeedPhrase -> SeedPhraseScreen.AboutSeedPhrase
|
||||
}
|
||||
}
|
||||
|
||||
fun openScreen(screen: SeedPhraseScreen) {
|
||||
currentScreen = screen
|
||||
}
|
||||
|
||||
fun openChat() {
|
||||
onOpenChat.invoke()
|
||||
}
|
||||
|
||||
fun openUri(uri: Uri) {
|
||||
onOpenUriClick.invoke(uri)
|
||||
}
|
||||
}
|
||||
|
||||
enum class SeedPhraseScreen {
|
||||
Intro, AboutSeedPhrase, YourSeedPhrase, CheckSeedPhrase, ImportSeedPhrase
|
||||
}
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
package com.tangem.feature.onboarding.presentation.wallet2.viewmodel
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.feature.onboarding.domain.SeedPhraseError
|
||||
import com.tangem.feature.onboarding.domain.SeedPhraseInteractor
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.model.*
|
||||
|
|
@ -34,18 +37,48 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
var uiState: OnboardingSeedPhraseState by mutableStateOf(uiBuilder.init())
|
||||
private set
|
||||
|
||||
val currentStep: OnboardingSeedPhraseStep
|
||||
get() = uiState.step
|
||||
private lateinit var router: SeedPhraseRouter
|
||||
private lateinit var mediator: SeedPhraseMediator
|
||||
|
||||
val currentScreen: SeedPhraseScreen
|
||||
get() = router.currentScreen
|
||||
|
||||
val progress: Int
|
||||
get() = progressByScreen[currentScreen] ?: 0
|
||||
|
||||
val maxProgress: Int by lazy { progressByScreen.maxOfOrNull { it.value } ?: 0 }
|
||||
|
||||
var isFinished: Boolean = false
|
||||
private set
|
||||
|
||||
private val progressByScreen = mapOf(
|
||||
SeedPhraseScreen.Intro to 1,
|
||||
SeedPhraseScreen.AboutSeedPhrase to 2,
|
||||
SeedPhraseScreen.YourSeedPhrase to 3,
|
||||
SeedPhraseScreen.CheckSeedPhrase to 3,
|
||||
SeedPhraseScreen.ImportSeedPhrase to 3,
|
||||
)
|
||||
|
||||
private val textFieldsDebouncers = mutableMapOf<String, Debouncer>()
|
||||
private var suggestionWordInserted: AtomicBoolean = AtomicBoolean(false)
|
||||
|
||||
private var generatedMnemonicComponents: List<String>? = null
|
||||
private var importedMnemonicComponents: List<String>? = null
|
||||
|
||||
override fun onCleared() {
|
||||
textFieldsDebouncers.forEach { entry -> entry.value.release() }
|
||||
textFieldsDebouncers.clear()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun setRouter(router: SeedPhraseRouter) {
|
||||
this.router = router
|
||||
}
|
||||
|
||||
fun setMediator(mediator: SeedPhraseMediator) {
|
||||
this.mediator = mediator
|
||||
}
|
||||
|
||||
private fun createUiActions(): UiActions = UiActions(
|
||||
introActions = IntroUiAction(
|
||||
buttonCreateWalletClick = ::buttonCreateWalletClick,
|
||||
|
|
@ -60,7 +93,7 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
buttonContinueClick = ::buttonContinueClick,
|
||||
),
|
||||
checkSeedPhraseActions = CheckSeedPhraseUiAction(
|
||||
buttonCreateWalletClick = ::buttonCreateWalletWithSeedPhraseClick,
|
||||
buttonCreateWalletClick = { buttonImportWalletClick(generatedMnemonicComponents) },
|
||||
secondTextFieldAction = TextFieldUiAction(
|
||||
onTextFieldChanged = { value -> onTextFieldChanged(SeedPhraseField.Second, value) },
|
||||
),
|
||||
|
|
@ -76,9 +109,10 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
onTextFieldChanged = { value -> onSeedPhraseTextFieldChanged(value) },
|
||||
),
|
||||
suggestedPhraseClick = ::buttonSuggestedPhraseClick,
|
||||
buttonCreateWalletClick = ::buttonCreateWalletWithSeedPhraseClick,
|
||||
buttonCreateWalletClick = { buttonImportWalletClick(importedMnemonicComponents) },
|
||||
),
|
||||
menuChatClick = ::menuChatClick,
|
||||
menuNavigateBackClick = ::menuNavigateBackClick,
|
||||
)
|
||||
|
||||
// region CheckSeedPhrase
|
||||
|
|
@ -153,12 +187,14 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
interactor.validateMnemonicString(inputMnemonic)
|
||||
.onSuccess {
|
||||
.onSuccess { mnemonicComponents ->
|
||||
importedMnemonicComponents = mnemonicComponents
|
||||
updateUi { uiBuilder.importSeedPhrase.updateError(uiState, null) }
|
||||
}
|
||||
.onFailure {
|
||||
val error = it as? SeedPhraseError ?: return
|
||||
|
||||
importedMnemonicComponents = null
|
||||
val mediateState = when (error) {
|
||||
is SeedPhraseError.InvalidWords -> {
|
||||
uiBuilder.importSeedPhrase.updateInvalidWords(uiState, error.words)
|
||||
|
|
@ -180,22 +216,46 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
// endregion ImportSeedPhrase
|
||||
|
||||
// region ButtonClickHandlers
|
||||
@Suppress("EmptyFunctionBlock")
|
||||
private fun buttonCreateWalletClick() {
|
||||
}
|
||||
|
||||
@Suppress("EmptyFunctionBlock")
|
||||
private fun buttonCreateWalletWithSeedPhraseClick() {
|
||||
}
|
||||
|
||||
private fun buttonOtherOptionsClick() {
|
||||
viewModelScope.launchSingle {
|
||||
updateUi { uiBuilder.changeStep(uiState, OnboardingSeedPhraseStep.AboutSeedPhrase) }
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
mediator.createWallet(::handleWalletCreationResult)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buttonImportWalletClick(mnemonicComponents: List<String>?) {
|
||||
mnemonicComponents ?: return
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
mediator.importWallet(mnemonicComponents, ::handleWalletCreationResult)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleWalletCreationResult(result: CompletionResult<CreateWalletResponse>) {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
isFinished = true
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
// errors shows on the TangemSdk bottom sheet dialog
|
||||
}
|
||||
}
|
||||
mediator.onWalletCreated(result)
|
||||
}
|
||||
|
||||
private fun menuNavigateBackClick() {
|
||||
router.navigateBack()
|
||||
}
|
||||
|
||||
private fun menuChatClick() {
|
||||
router.openChat()
|
||||
}
|
||||
|
||||
private fun buttonOtherOptionsClick() {
|
||||
router.openScreen(SeedPhraseScreen.AboutSeedPhrase)
|
||||
}
|
||||
|
||||
private fun buttonReadMoreAboutSeedPhraseClick() {
|
||||
// TODO: open the about info through a router
|
||||
router.openUri(URI_ABOUT_SEED_PHRASE)
|
||||
}
|
||||
|
||||
private fun buttonGenerateSeedPhraseClick() {
|
||||
|
|
@ -204,10 +264,15 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
delay(DELAY_GENERATE_SEED_PHRASE)
|
||||
interactor.generateMnemonic()
|
||||
.onSuccess { mnemonic ->
|
||||
generatedMnemonicComponents = mnemonic.mnemonicComponents
|
||||
val mnemonicGridItems = generateMnemonicGridList(mnemonic.mnemonicComponents)
|
||||
updateUi { uiBuilder.mnemonicGenerated(uiState, mnemonicGridItems.toImmutableList()) }
|
||||
updateUi {
|
||||
router.openScreen(SeedPhraseScreen.YourSeedPhrase)
|
||||
uiBuilder.mnemonicGenerated(uiState, mnemonicGridItems.toImmutableList())
|
||||
}
|
||||
}
|
||||
.onFailure {
|
||||
generatedMnemonicComponents = null
|
||||
// TODO: show error
|
||||
}
|
||||
}
|
||||
|
|
@ -240,15 +305,11 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun buttonImportSeedPhraseClick() {
|
||||
viewModelScope.launchSingle {
|
||||
updateUi { uiBuilder.changeStep(uiState, OnboardingSeedPhraseStep.ImportSeedPhrase) }
|
||||
}
|
||||
router.openScreen(SeedPhraseScreen.ImportSeedPhrase)
|
||||
}
|
||||
|
||||
private fun buttonContinueClick() {
|
||||
viewModelScope.launchSingle {
|
||||
updateUi { uiBuilder.changeStep(uiState, OnboardingSeedPhraseStep.CheckSeedPhrase) }
|
||||
}
|
||||
router.openScreen(SeedPhraseScreen.CheckSeedPhrase)
|
||||
}
|
||||
|
||||
private fun buttonSuggestedPhraseClick(suggestionIndex: Int) {
|
||||
|
|
@ -269,10 +330,6 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun menuChatClick() {
|
||||
// TODO: open the support chat through a router
|
||||
}
|
||||
// endregion ButtonClickHandlers
|
||||
|
||||
// region Utils
|
||||
|
|
@ -311,6 +368,7 @@ class SeedPhraseViewModel @Inject constructor(
|
|||
// endregion Utils
|
||||
|
||||
companion object {
|
||||
private val URI_ABOUT_SEED_PHRASE = Uri.parse("https://ya.ru")
|
||||
private const val MNEMONIC_DEBOUNCER = "MnemonicDebouncer"
|
||||
private const val MNEMONIC_DEBOUNCE_DELAY = 700L
|
||||
private const val DELAY_GENERATE_SEED_PHRASE = 300L
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue