diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt index 2782756634..2506786079 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt @@ -6,6 +6,7 @@ import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener +import com.tangem.crypto.bip39.Mnemonic import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase @@ -26,6 +27,9 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject +// ============================================= +// | DON'T FIXME !!! MODIFY WITH CAUTION !!! | +// ============================================= @Suppress("LongParameterList") @ComponentScoped internal class MultiWalletSeedPhraseModel @Inject constructor( @@ -45,21 +49,40 @@ internal class MultiWalletSeedPhraseModel @Inject constructor( private val _uiState = MutableStateFlow(getStartState()) private val generateSeedPhraseUiStateBuilder = GenerateSeedPhraseUiStateBuilder( - state = state, updateUiState = { block -> updateUiStateSpecific(block) }, onContinue = ::openWordsCheck, + + // ============================================= + // | DON'T FIXME !!! MODIFY WITH CAUTION !!! | + // ============================================= + changeWords24Option = { state.update { it.copy(words24Option = it.words24Option) } }, + // ============================================= ) private val seedPhraseCheckUiStateBuilder = SeedPhraseCheckUiStateBuilder( - state = state, + currentState = { state.value }, currentUiState = { _uiState.value }, updateUiState = { block -> updateUiStateSpecific(block) }, - importWallet = ::importWallet, + readyToImport = { ready -> state.update { it.copy(readyToImport = ready) } }, + + // ============================================= + // | DON'T FIXME !!! MODIFY WITH CAUTION !!! | + // ============================================= + importWallet = importWallet@{ + importWallet( + mnemonic = if (state.value.words24Option) { + state.value.generatedWords24 ?: return@importWallet + } else { + state.value.generatedWords12 ?: return@importWallet + }, + passphrase = null, + ) + }, + // ============================================= ) private val importSeedPhraseUiStateBuilder = ImportSeedPhraseUiStateBuilder( modelScope = modelScope, - state = state, mnemonicRepository = mnemonicRepository, updateUiState = { block -> updateUiStateSpecific(block) }, importWallet = ::importWallet, @@ -133,12 +156,12 @@ internal class MultiWalletSeedPhraseModel @Inject constructor( } } - private fun importWallet(shouldReset: Boolean = false) { - // TODO make stateless AND-9167 + // ============================================= + // | DON'T FIXME !!! MODIFY WITH CAUTION !!! | + // ============================================= + private fun importWallet(mnemonic: Mnemonic, passphrase: String?) { val currentState = state.value - val mnemonic = currentState.importedMnemonic - ?: (if (currentState.words24Option) currentState.generatedWords24 else currentState.generatedWords12) - ?: return + if (currentState.readyToImport.not()) return val scanResponse = params.parentParams.scanResponse @@ -146,8 +169,8 @@ internal class MultiWalletSeedPhraseModel @Inject constructor( val result = tangemSdkManager.importWallet( scanResponse = scanResponse, mnemonic = mnemonic.mnemonicComponents.joinToString(" "), - passphrase = currentState.passphrase, - shouldReset = shouldReset, + passphrase = passphrase, + shouldReset = false, ) when (result) { @@ -176,6 +199,7 @@ internal class MultiWalletSeedPhraseModel @Inject constructor( } } } + // ============================================= private fun handleActivationError() { updateDialog( @@ -187,7 +211,16 @@ internal class MultiWalletSeedPhraseModel @Inject constructor( ) } - private fun resetCard() = importWallet(true) + private fun resetCard() { + val scanResponse = params.parentParams.scanResponse + + modelScope.launch { + tangemSdkManager.resetToFactorySettings( + cardId = scanResponse.card.cardId, + allowsRequestAccessCodeFromRepository = true, + ) + } + } fun navigateToSupportScreen() { modelScope.launch { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/SeedPhraseState.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/SeedPhraseState.kt index 4cca53afba..6deef16632 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/SeedPhraseState.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/SeedPhraseState.kt @@ -6,7 +6,5 @@ data class SeedPhraseState( val generatedWords12: Mnemonic? = null, val generatedWords24: Mnemonic? = null, val words24Option: Boolean = false, - val importedMnemonic: Mnemonic? = null, - val passphrase: String? = null, val readyToImport: Boolean = false, ) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/GenerateSeedPhraseUiStateBuilder.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/GenerateSeedPhraseUiStateBuilder.kt index 2a1d992621..cc7b0d6b5f 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/GenerateSeedPhraseUiStateBuilder.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/GenerateSeedPhraseUiStateBuilder.kt @@ -1,15 +1,12 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.builder import com.tangem.crypto.bip39.Mnemonic -import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.SeedPhraseState import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.update internal class GenerateSeedPhraseUiStateBuilder( - private val state: MutableStateFlow, + private val changeWords24Option: (Boolean) -> Unit, private val updateUiState: ( (MultiWalletSeedPhraseUM.GenerateSeedPhrase) -> MultiWalletSeedPhraseUM.GenerateSeedPhrase, ) -> Unit, @@ -25,7 +22,7 @@ internal class GenerateSeedPhraseUiStateBuilder( }.toImmutableList() return MultiWalletSeedPhraseUM.GenerateSeedPhrase( - words24OptionSelected = state.value.words24Option, + words24OptionSelected = false, words = words12, onWords24OptionSwitch = { switchType(words12, words24) }, onContinueClick = onContinue, @@ -37,7 +34,7 @@ internal class GenerateSeedPhraseUiStateBuilder( generatedWords24: ImmutableList, ) { updateUiState { uiSt -> - state.update { it.copy(words24Option = uiSt.words24OptionSelected.not()) } + changeWords24Option(uiSt.words24OptionSelected.not()) uiSt.copy( words24OptionSelected = uiSt.words24OptionSelected.not(), diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/ImportSeedPhraseUiStateBuilder.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/ImportSeedPhraseUiStateBuilder.kt index b15f4d0bf6..dc50ef4cf1 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/ImportSeedPhraseUiStateBuilder.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/ImportSeedPhraseUiStateBuilder.kt @@ -5,28 +5,27 @@ import androidx.compose.ui.text.input.TextFieldValue import com.tangem.common.core.TangemSdkError import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.extensions.resourceReference +import com.tangem.crypto.bip39.Mnemonic import com.tangem.crypto.bip39.MnemonicErrorResult import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.MnemonicRepository -import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.SeedPhraseState import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch internal class ImportSeedPhraseUiStateBuilder( private val modelScope: CoroutineScope, - private val state: MutableStateFlow, private val mnemonicRepository: MnemonicRepository, private val updateUiState: ((MultiWalletSeedPhraseUM.Import) -> MultiWalletSeedPhraseUM.Import) -> Unit, - private val importWallet: () -> Unit, + private val importWallet: (mnemonic: Mnemonic, passphrase: String?) -> Unit, ) { private val wordsCheckJobHolder = JobHolder() + private var importedMnemonic: Mnemonic? = null + private var passphrase: String? = null fun getState(): MultiWalletSeedPhraseUM { return MultiWalletSeedPhraseUM.Import( @@ -38,15 +37,21 @@ internal class ImportSeedPhraseUiStateBuilder( } }, passPhraseChange = { - state.update { st -> st.copy(passphrase = it.text) } + passphrase = it.text updateUiState { state -> state.copy(passPhrase = it) } }, onPassphraseInfoClick = ::showInfoBS, - createWalletClick = importWallet, + createWalletClick = ::onCreateWallet, onSuggestionClick = { word -> addSuggestedWord(word) }, ) } + private fun onCreateWallet() { + val mnemonic = importedMnemonic ?: return + val passphrase = passphrase?.takeIf { it.isNotEmpty() } + importWallet(mnemonic, passphrase) + } + private fun addSuggestedWord(word: String) { updateUiState { st -> val text = st.words.text @@ -102,7 +107,7 @@ internal class ImportSeedPhraseUiStateBuilder( ) } - state.value = state.value.copy(importedMnemonic = null) + importedMnemonic = null val text = wordsField.text val wordsFromText = text.split(" ").filter { it.isNotBlank() }.map { it.trim() } @@ -120,7 +125,7 @@ internal class ImportSeedPhraseUiStateBuilder( try { val mnemonic = mnemonicRepository.generateMnemonic(text) - state.value = state.value.copy(importedMnemonic = mnemonic) + importedMnemonic = mnemonic updateUiState { it.copy( invalidWords = emptyList().toImmutableList(), diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/SeedPhraseCheckUiStateBuilder.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/SeedPhraseCheckUiStateBuilder.kt index 7634813ce1..88c8da3d42 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/SeedPhraseCheckUiStateBuilder.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/builder/SeedPhraseCheckUiStateBuilder.kt @@ -4,16 +4,15 @@ import androidx.compose.ui.text.input.TextFieldValue import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.SeedPhraseState import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.update internal class SeedPhraseCheckUiStateBuilder( - private val state: MutableStateFlow, + private val currentState: () -> SeedPhraseState, private val currentUiState: () -> MultiWalletSeedPhraseUM, private val updateUiState: ( (MultiWalletSeedPhraseUM.GeneratedWordsCheck) -> MultiWalletSeedPhraseUM.GeneratedWordsCheck, ) -> Unit, private val importWallet: () -> Unit, + private val readyToImport: (Boolean) -> Unit, ) { @Suppress("MagicNumber") @@ -43,7 +42,7 @@ internal class SeedPhraseCheckUiStateBuilder( ) val allFieldsCorrect = newState.allFieldsCorrect() - state.update { it.copy(readyToImport = allFieldsCorrect) } + readyToImport(allFieldsCorrect) newState.copy( createWalletButtonEnabled = allFieldsCorrect, @@ -89,7 +88,7 @@ internal class SeedPhraseCheckUiStateBuilder( } private fun checkWordField(word: String, shownIndex: Int): Boolean { - val currentState = state.value + val currentState = currentState() currentState.generatedWords12 ?: return false currentState.generatedWords24 ?: return false