diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 47819aea80..b2dec66340 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -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, + ) : 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) -> Unit, + ) : OnboardingWallet2Action() + + data class ImportWallet( + val mnemonicComponents: List, + val callback: (CompletionResult) -> Unit, + ) : OnboardingWallet2Action() + + data class WalletWasCreated( + val result: CompletionResult, + ) : OnboardingWallet2Action() +} + sealed class BackupAction : Action { object IntroduceBackup : BackupAction() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index a6eafe02d9..ce3a707b4d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -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 = { 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 diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 0c50b1028f..30b94a73c6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -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 { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index d2ef761e70..76a115e8a8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -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( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt similarity index 95% rename from app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt rename to app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt index 394e03adb4..b4c5bf2c60 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt @@ -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, ) { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingSeedPhraseStateHandler.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingSeedPhraseStateHandler.kt new file mode 100644 index 0000000000..2b9370bdd1 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingSeedPhraseStateHandler.kt @@ -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(), + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 0f8715a237..7ec50bc7ed 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -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, 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() + + 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) -> Unit) { + store.dispatch(OnboardingWallet2Action.CreateWallet(callback)) + } + + override fun onWalletCreated(result: CompletionResult) { + store.dispatch(OnboardingWallet2Action.WalletWasCreated(result)) + } + + override fun importWallet( + mnemonicComponents: List, + callback: (CompletionResult) -> Unit, + ) { + store.dispatch(OnboardingWallet2Action.ImportWallet(mnemonicComponents, callback)) + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 33174db903..59a23e9ab4 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -228,6 +228,13 @@ android:layout_height="match_parent" android:visibility="gone" /> + + + \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt index d62e391dfb..77dafd0c4e 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt @@ -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 diff --git a/features/onboarding/build.gradle.kts b/features/onboarding/build.gradle.kts index 61df104ad9..5ad4ad1102 100644 --- a/features/onboarding/build.gradle.kts +++ b/features/onboarding/build.gradle.kts @@ -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")) diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhrase.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhrase.kt new file mode 100644 index 0000000000..2e54d828c6 --- /dev/null +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhrase.kt @@ -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, + ) + } + } +} \ No newline at end of file diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhraseApi.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhraseApi.kt new file mode 100644 index 0000000000..364cfa1a65 --- /dev/null +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/api/OnboardingSeedPhraseApi.kt @@ -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) +} \ No newline at end of file diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/data/model/CreateWalletResponse.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/data/model/CreateWalletResponse.kt new file mode 100644 index 0000000000..76f4027a1b --- /dev/null +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/data/model/CreateWalletResponse.kt @@ -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 = mapOf(), + val primaryCard: PrimaryCard? = null, +) \ No newline at end of file diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/OnboardingSeedPhraseState.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/OnboardingSeedPhraseState.kt index 9eea61c93b..74b732e86b 100644 --- a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/OnboardingSeedPhraseState.kt +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/OnboardingSeedPhraseState.kt @@ -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, diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/UiActions.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/UiActions.kt index 419b277b9d..5a63039118 100644 --- a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/UiActions.kt +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/model/UiActions.kt @@ -12,6 +12,7 @@ data class UiActions( val checkSeedPhraseActions: CheckSeedPhraseUiAction, val importSeedPhraseActions: ImportSeedPhraseUiAction, val menuChatClick: () -> Unit, + val menuNavigateBackClick: () -> Unit, ) data class IntroUiAction( diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/ui/stateBuiders/StateBuilder.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/ui/stateBuiders/StateBuilder.kt index f240c101ce..2b58078ed0 100644 --- a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/ui/stateBuiders/StateBuilder.kt +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/ui/stateBuiders/StateBuilder.kt @@ -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, diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseMediator.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseMediator.kt new file mode 100644 index 0000000000..d0a59581ec --- /dev/null +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseMediator.kt @@ -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) -> Unit) + fun importWallet(mnemonicComponents: List, callback: (CompletionResult) -> Unit) + + fun onWalletCreated(result: CompletionResult) +} \ No newline at end of file diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseRouter.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseRouter.kt new file mode 100644 index 0000000000..03aef5e7dc --- /dev/null +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseRouter.kt @@ -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 +} \ No newline at end of file diff --git a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseViewModel.kt b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseViewModel.kt index 4fbee7352f..10e1a59896 100644 --- a/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseViewModel.kt +++ b/features/onboarding/src/main/java/com/tangem/feature/onboarding/presentation/wallet2/viewmodel/SeedPhraseViewModel.kt @@ -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() private var suggestionWordInserted: AtomicBoolean = AtomicBoolean(false) + private var generatedMnemonicComponents: List? = null + private var importedMnemonicComponents: List? = 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?) { + mnemonicComponents ?: return + + viewModelScope.launch(dispatchers.io) { + mediator.importWallet(mnemonicComponents, ::handleWalletCreationResult) + } + } + + private fun handleWalletCreationResult(result: CompletionResult) { + 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