Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-22 15:25:32 +03:00
parent c07ecae962
commit 44231e988d
5 changed files with 66 additions and 34 deletions

View file

@ -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 [REDACTED_TASK_KEY]
// =============================================
// | 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 {

View file

@ -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,
)

View file

@ -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<SeedPhraseState>,
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<MultiWalletSeedPhraseUM.GenerateSeedPhrase.MnemonicGridItem>,
) {
updateUiState { uiSt ->
state.update { it.copy(words24Option = uiSt.words24OptionSelected.not()) }
changeWords24Option(uiSt.words24OptionSelected.not())
uiSt.copy(
words24OptionSelected = uiSt.words24OptionSelected.not(),

View file

@ -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<SeedPhraseState>,
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<String>().toImmutableList(),

View file

@ -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<SeedPhraseState>,
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